diff --git a/assembler/ext/include/boost/pending/integer_log2.hpp b/assembler/ext/include/boost/pending/integer_log2.hpp deleted file mode 100644 index 023ec7af03..0000000000 --- a/assembler/ext/include/boost/pending/integer_log2.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef BOOST_PENDING_INTEGER_LOG2_HPP -#define BOOST_PENDING_INTEGER_LOG2_HPP - -// The header file at this path is deprecated; -// use boost/integer/integer_log2.hpp instead. - -#include - -#endif diff --git a/assembler/ext/include/boost/pending/lowest_bit.hpp b/assembler/ext/include/boost/pending/lowest_bit.hpp deleted file mode 100644 index dd6e6e8c9e..0000000000 --- a/assembler/ext/include/boost/pending/lowest_bit.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// ----------------------------------------------------------- -// lowest_bit.hpp -// -// Position of the lowest bit 'on' -// -// Copyright (c) 2003-2004, 2008 Gennaro Prota -// -// 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) -// -// ----------------------------------------------------------- - -#ifndef BOOST_LOWEST_BIT_HPP_GP_20030301 -#define BOOST_LOWEST_BIT_HPP_GP_20030301 - -#include -#include "boost/pending/integer_log2.hpp" - - -namespace boost { - - template - int lowest_bit(T x) { - - assert(x >= 1); // PRE - - // clear all bits on except the rightmost one, - // then calculate the logarithm base 2 - // - return boost::integer_log2( x - ( x & (x-1) ) ); - - } - - -} - - -#endif // include guard diff --git a/assembler/ext/src/lexy/.clang-format b/assembler/ext/src/lexy/.clang-format deleted file mode 100644 index 88b932e7fa..0000000000 --- a/assembler/ext/src/lexy/.clang-format +++ /dev/null @@ -1,73 +0,0 @@ -AccessModifierOffset: -4 -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: true -AlignConsecutiveDeclarations: true -AlignEscapedNewlinesLeft: Right -AlignOperands: true -AlignTrailingComments: true -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: Empty -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: true -BinPackArguments: true -BinPackParameters: true -BreakBeforeBraces: Custom -BraceWrapping: - AfterClass: true - AfterControlStatement: true - AfterEnum: true - AfterFunction: true - AfterNamespace: true - AfterStruct: true - AfterUnion: true - AfterExternBlock: true - BeforeCatch: true - BeforeElse: true - SplitEmptyFunction: false - SplitEmptyRecord: false - SplitEmptyNamespace: false -BreakBeforeBinaryOperators: All -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeColon -BreakStringLiterals: false -ColumnLimit: 100 -CompactNamespaces: true -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 0 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -FixNamespaceComments: true -IncludeBlocks: Preserve -IndentCaseLabels: false -IndentPPDirectives: AfterHash -IndentWidth: 4 -IndentWrappedFunctionNames: true -KeepEmptyLinesAtTheStartOfBlocks: false -Language: Cpp -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: Inner -PenaltyBreakBeforeFirstCallParameter: 19937 -PenaltyReturnTypeOnItsOwnLine: 19937 -PointerAlignment: Left -ReflowComments: true -SortIncludes: true -SortUsingDeclarations: true -SpaceAfterCStyleCast: false -SpaceAfterTemplateKeyword: true -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Cpp11 -TabWidth: 4 -UseTab: Never diff --git a/assembler/ext/src/lexy/.clang-tidy b/assembler/ext/src/lexy/.clang-tidy deleted file mode 100644 index 44f7fc8595..0000000000 --- a/assembler/ext/src/lexy/.clang-tidy +++ /dev/null @@ -1,32 +0,0 @@ -Checks: > - -*, - bugprone-*, - -bugprone-exception-escape, - -bugprone-easily-swappable-parameters, - clang-analyzer-*, - misc-*, - -misc-definitions-in-headers, - -misc-non-private-member-variables-in-classes, - -misc-no-recursion, - -misc-static-assert, - -misc-unused-alias-decls, - performance-*, - readability-*, - -readability-braces-around-statements, - -readability-convert-member-functions-to-static, - -readability-else-after-return, - -readability-function-cognitive-complexity, - -readability-function-size, - -readability-magic-numbers, - -readability-make-member-function-const, - -readability-misleading-indentation, - -readability-named-parameter, - -readability-qualified-auto, - -readability-redundant-access-specifiers, - -readability-redundant-declaration, - -readability-static-accessed-through-instance, - -readability-uppercase-literal-suffix, -WarningsAsErrors: '*' -FormatStyle: 'file' -HeaderFilterRegex: 'include/lexy(_ext)?/' - diff --git a/assembler/ext/src/lexy/.github/funding.yml b/assembler/ext/src/lexy/.github/funding.yml deleted file mode 100644 index 6ac455a61f..0000000000 --- a/assembler/ext/src/lexy/.github/funding.yml +++ /dev/null @@ -1,2 +0,0 @@ -patreon: foonathan -custom: ['https://jonathanmueller.dev/support-me/'] diff --git a/assembler/ext/src/lexy/.github/workflows/codeql.yml b/assembler/ext/src/lexy/.github/workflows/codeql.yml deleted file mode 100644 index ace082ab75..0000000000 --- a/assembler/ext/src/lexy/.github/workflows/codeql.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: CodeQL - -on: - push: - branches: [main, fix/*] - schedule: - - cron: '30 1 * * 2' - -jobs: - codeql: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Install ninja - run: sudo apt-get -qq update && sudo apt-get install -y ninja-build - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: cpp - - - name: Create Build Environment - run: cmake -E make_directory build - - name: Configure - working-directory: build/ - run: cmake -GNinja $GITHUB_WORKSPACE - - name: Build - working-directory: build/ - run: cmake --build . - - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@v1 - diff --git a/assembler/ext/src/lexy/.github/workflows/feature_ci.yml b/assembler/ext/src/lexy/.github/workflows/feature_ci.yml deleted file mode 100644 index e7fc003516..0000000000 --- a/assembler/ext/src/lexy/.github/workflows/feature_ci.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: Feature CI - -on: - push: - branches-ignore: ['main', 'fix/*'] - pull_request: - -jobs: - linux: - strategy: - fail-fast: false - matrix: - image: ["gcc:7", "gcc:12", "clang:6", "clang:13"] - - runs-on: ubuntu-latest - container: - image: ghcr.io/foonathan/${{matrix.image}} - - steps: - - uses: actions/checkout@v2 - - name: Create Build Environment - run: cmake -E make_directory build - - - name: Configure - working-directory: build/ - run: cmake -GNinja $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=Debug - - name: Build - working-directory: build/ - run: cmake --build . - - name: Test - working-directory: build/ - run: ctest --output-on-failure - - macos: - strategy: - fail-fast: false - matrix: - xcode: ['11', '13'] - - runs-on: macos-11 - - steps: - - uses: actions/checkout@v2 - - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: ${{matrix.xcode}} - - name: Create Build Environment - run: cmake -E make_directory build - - name: Install ninja - run: brew install ninja - - - name: Configure - working-directory: build/ - run: cmake -GNinja $GITHUB_WORKSPACE - - name: Build - working-directory: build/ - run: cmake --build . - - name: Test - working-directory: build/ - run: ctest --output-on-failure - - windows: - runs-on: windows-2019 - - steps: - - uses: actions/checkout@v2 - - name: Create Build Environment - run: cmake -E make_directory build - - - name: Configure - shell: bash - working-directory: build/ - run: cmake $GITHUB_WORKSPACE -G"Visual Studio 16 2019" - - name: Build - working-directory: build/ - run: cmake --build . --config Debug -j 2 - - name: Test - working-directory: build/ - run: ctest -C Debug --output-on-failure - diff --git a/assembler/ext/src/lexy/.github/workflows/main_ci.yml b/assembler/ext/src/lexy/.github/workflows/main_ci.yml deleted file mode 100644 index 76ef4860d7..0000000000 --- a/assembler/ext/src/lexy/.github/workflows/main_ci.yml +++ /dev/null @@ -1,103 +0,0 @@ -name: Main CI - -on: - push: - branches: [main, fix/*] - -jobs: - linux: - strategy: - fail-fast: false - matrix: - image: - - "gcc:7" - - "gcc:8" - - "gcc:9" - - "gcc:10" - - "gcc:11" - - "gcc:12" - - "clang:6" - - "clang:7" - - "clang:8" - - "clang:9" - - "clang:10" - - "clang:11" - - "clang:12" - - "clang:13" - build_type: [Debug, Release] - - runs-on: ubuntu-latest - container: - image: ghcr.io/foonathan/${{matrix.image}} - - steps: - - uses: actions/checkout@v2 - - name: Create Build Environment - run: cmake -E make_directory build - - - name: Configure - working-directory: build/ - run: cmake -GNinja $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{matrix.build_type}} - - name: Build - working-directory: build/ - run: cmake --build . - - name: Test - working-directory: build/ - run: ctest --output-on-failure - - macos: - strategy: - fail-fast: false - matrix: - xcode: - - '11' - - '12' - - '13' - - runs-on: macos-11 - - steps: - - uses: actions/checkout@v2 - - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: ${{matrix.xcode}} - - name: Create Build Environment - run: cmake -E make_directory build - - name: Install ninja - run: brew install ninja - - - name: Configure - working-directory: build/ - run: cmake -GNinja $GITHUB_WORKSPACE - - name: Build - working-directory: build/ - run: cmake --build . - - name: Test - working-directory: build/ - run: ctest --output-on-failure - - windows: - strategy: - fail-fast: false - matrix: - toolset: ['v142', 'ClangCL'] - build_type: [Debug, Release] - - runs-on: windows-2019 - - steps: - - uses: actions/checkout@v2 - - name: Create Build Environment - run: cmake -E make_directory build - - - name: Configure - shell: bash - working-directory: build/ - run: cmake $GITHUB_WORKSPACE -G"Visual Studio 16 2019" -T ${{matrix.toolset}} - - name: Build - working-directory: build/ - run: cmake --build . --config ${{matrix.build_type}} -j 2 - - name: Test - working-directory: build/ - run: ctest -C ${{matrix.build_type}} --output-on-failure - diff --git a/assembler/ext/src/lexy/.github/workflows/release.yml b/assembler/ext/src/lexy/.github/workflows/release.yml deleted file mode 100644 index 8c97d46c34..0000000000 --- a/assembler/ext/src/lexy/.github/workflows/release.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Release -permissions: - contents: write - pull-requests: write - -on: - release: - types: [published] - -jobs: - release: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Create build environment - run: cmake -E make_directory build - - name: Configure - working-directory: build/ - run: cmake $GITHUB_WORKSPACE -DLEXY_BUILD_EXAMPLES=OFF -DLEXY_BUILD_TESTS=OFF - - name: Package source code - working-directory: build/ - run: cmake --build . --target lexy_package - - - name: Write data file for release - run: | - echo "name = \"${{ github.event.release.name }}\"" > docs/data/tags/${{ github.event.release.tag_name }}.toml - echo "url = \"${{ github.event.release.html_url }}\"" >> docs/data/tags/${{ github.event.release.tag_name }}.toml - echo "download = \"https://github.com/${{ github.repository }}/releases/download/${{ github.event.release.tag_name}}/lexy-src.zip\"" >> docs/data/tags/${{ github.event.release.tag_name }}.toml - echo "date = \"${{ github.event.release.published_at }}\"" >> docs/data/tags/${{ github.event.release.tag_name }}.toml - echo "prerelease = ${{ github.event.release.prerelease }}" >> docs/data/tags/${{ github.event.release.tag_name }}.toml - - - name: Add packaged source code to release - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: build/lexy-src.zip - tag: ${{ github.ref }} - - name: Create post PR for this release - uses: peter-evans/create-pull-request@v4 - with: - title: Post-release ${{ github.event.release.tag_name }} - commit-message: Post-release ${{ github.event.release.tag_name }} - add-paths: docs/data/tags/*.toml - base: main diff --git a/assembler/ext/src/lexy/.github/workflows/sanitizers.yml b/assembler/ext/src/lexy/.github/workflows/sanitizers.yml deleted file mode 100644 index ce6f3f52f1..0000000000 --- a/assembler/ext/src/lexy/.github/workflows/sanitizers.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: Sanitizers - -on: - push: - branches: '**' - pull_request: - -jobs: - sanitizers: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Install ninja - run: sudo apt-get -qq update && sudo apt-get install -y ninja-build - - - name: Create Build Environment - run: cmake -E make_directory build - - name: Configure - working-directory: build/ - run: cmake -GNinja $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-DLEXY_DISABLE_CONSTEXPR_TESTS -fsanitize=address,undefined,leak -fno-sanitize-recover=all" -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined,leak" - - name: Build - working-directory: build/ - run: cmake --build . - - name: Test - working-directory: build/ - run: ctest --output-on-failure - env: - ASAN_OPTIONS: detect_stack_use_after_return=1 - - clang-tidy: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Create Build Environment - run: cmake -E make_directory build - - name: Install ninja and clang-tidy - run: sudo apt-get -qq update && sudo apt-get install -y ninja-build clang-tidy-12 - - - name: Configure - working-directory: build/ - run: cmake -GNinja $GITHUB_WORKSPACE -DCMAKE_CXX_CLANG_TIDY="clang-tidy-12;-extra-arg=-Wno-unknown-warning-option" - - name: Build - working-directory: build/ - run: cmake --build . --target lexy_test lexy_ext_test - - benchmarks: # just to ensure that they are compiled - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Create Build Environment - run: cmake -E make_directory build - - name: Install ninja - run: sudo apt-get -qq update && sudo apt-get install -y ninja-build - - - name: Configure - working-directory: build/ - run: cmake -GNinja $GITHUB_WORKSPACE -DLEXY_BUILD_BENCHMARKS=ON - - name: Build - working-directory: build/ - run: cmake --build . - diff --git a/assembler/ext/src/lexy/.github/workflows/website.yml b/assembler/ext/src/lexy/.github/workflows/website.yml deleted file mode 100644 index e344a4accd..0000000000 --- a/assembler/ext/src/lexy/.github/workflows/website.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Website -permissions: - contents: write - -on: - push: - branches: '**' - pull_request: - -jobs: - website: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Install asciidoctor - run: sudo gem install asciidoctor pygments.rb - - name: Install hugo - uses: peaceiris/actions-hugo@v2 - with: - hugo-version: 'latest' - extended: true - - - name: Create Build Environment - run: cmake -E make_directory build - - name: Configure - working-directory: build/ - run: cmake $GITHUB_WORKSPACE -DLEXY_BUILD_DOCS=ON -DLEXY_BUILD_EXAMPLES=OFF -DLEXY_BUILD_TESTS=OFF - - name: Build docs - working-directory: build/ - run: cmake --build . --target lexy_docs - - - name: Deploy - if: github.ref == 'refs/heads/main' - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/public/ - diff --git a/assembler/ext/src/lexy/.gitignore b/assembler/ext/src/lexy/.gitignore deleted file mode 100644 index 497a1168d1..0000000000 --- a/assembler/ext/src/lexy/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -docs/assets/cpp/playground_headers.single.hpp -docs/content/_index.adoc -docs/content/learn/changelog.adoc -docs/static/download/*.zip -docs/public/ -docs/resources/ diff --git a/assembler/ext/src/lexy/CHANGELOG.adoc b/assembler/ext/src/lexy/CHANGELOG.adoc deleted file mode 100644 index ee8af443ca..0000000000 --- a/assembler/ext/src/lexy/CHANGELOG.adoc +++ /dev/null @@ -1,386 +0,0 @@ -= Changelog - -== Upcoming - -* Change `dsl::scan`: it will now be invoked with the previously produced values. -* Add `lexy::lexeme_input` to support multi-pass parsing. -* Turn `dsl::terminator(term)(branch)` into a branch rule, as opposed to being a plain rule (#74). -* Add `dsl::ignore_trailing_sep()` separator. -* Turn `lexy::forward` into a sink. -* Fix bug that prevented `lexy::parse` with a root production whose value is `void`. - -== Release 2022.05.0 - -Initial release. - -''' - -NOTE: The following changelog items track the historic development; only breaking changes are documented. - -== 2022-04-21 - -`dsl::lit_cp` in a char class now requires a Unicode encoding; use `dsl::lit_b` to support default/byte encoding. - -== 2022-03-21 - -* *BEHAVIOR CHANGE*: `lexy::token_production` that define a `::whitespace` member now skip whitespace in the direct rule as well. - Previously, it would only apply the whitespace rule to child productions but not the production itself. -* *BEHAVIOR CHANGE*: production rules that define a `::whitespace` member now skip whitespace before parsing. - This also applies to the root production, so whitespace at the beginning of the input is now skipped automatically. -* `dsl::p` where `Production` defines a `::whitespace` member is now longer a branch rule: as it will now skip whitespace first, it can't be used as a branch condition. -* Remove `dsl::whitespace` (no arguments); it's now unnecessary as initial whitespace is skipped automatically. - -== 2022-03-02 - -* *BEHAVIOR CHANGE*: `dsl::capture_token()` is now `dsl::capture()`, old `dsl::capture()` is removed. - If you're using `dsl::capture_token()` you need to rename it to `dsl::capture()` (compile error). - If you're using `dsl::capture()` on a non-token rule, you need to use `dsl::scan` instead and manually produce the value (compile error). - If you're using `dsl::capture()` on a token, this will no longer capture trailing whitespace (silent behavior change). - I can't imagine a situation where capturing trailing whitespace was intended. -* *BEHAVIOR CHANGE*: if a non-root production defines a `::whitespace` member, it will now also apply to all children. - Previously, it would only apply to the production that defined the member, and not it's children (except if it was a token production). - -== 2022-02-09 - -* *BEHAVIOR CHANGE*: `dsl::newline` (and `dsl::eol` in the newline case) generate a token node with the `lexy::literal_token_kind`; - `lexy::newline_token_kind` and `lexy::eol_token_kind` have been removed. -* `dsl::eof` and `dsl::eol` are now branch rules: replace `dsl::until(dsl::eol)` by `dsl::until(dsl::newline).or_eof()`. -* Removed generic `dsl::operator/` (alternative): use `dsl::literal_set()` or `dsl::operator|` instead. -* Require a char class rule in `.limit()` of `dsl::delimited()`: instead of `dsl::eol` or `dsl::newline`, use `dsl::ascii::newline`. -* Require literal rules in `dsl::lookahead()`, `dsl::find()`, and `.limit()` of error recovery rules. -* Require literal rules in `.reserve()` and variants of `dsl::identifier`. -* `dsl::bom` now generates a `lexy::expected_literal` error instead of `lexy::expected_char_class`. - -== 2022-01-30 - -* *BEHAVIOR CHANGE*: the introduction of char class rules changes error messages and token kinds in some situations. -* Renamed `dsl::code_point.lit()` to `dsl::lit_cp` and moved to `dsl/literal.hpp`. -* Require char classes in `operator-` for tokens; removed `dsl::contains()` and `dsl::prefix()`. -* Require char classes in `dsl::delimited()` and `dsl::identifier()`. -* Renamed `.character_class()` of `dsl::error` to `.name()`. - -== 2021-12-08 - -`dsl::integer` now uses `lexy::digits_token_kind` instead of `lexy::error_token_kind` during recovery. - -== 2021-12-01 - -`dsl::bom` and `dsl::lit_b` now require `lexy::byte_encoding`. - -== 2021-11-30 - -Remove `lexy_ext/input_location.hpp`: use `lexy/input_location.hpp` instead, which has a different interface but more functionality. - -== 2021-11-23 - -* Added more pre-defined token kinds: for example, tokens created by `LEXY_LIT()` now have their own literal token kind. - This breaks code that does not use user-defined token kinds and does matching on `lexy::parse_tree`. -* `dsl::delimited()` now merges adjacent characters into a single `lexy::lexeme` that is passed to the sink. -* `lexy::token_production` now longer merges adjacent tokens, but `dsl::delimited()` merges character tokens. - -== 2021-10-13 - -* Terminator rules are no longer branch rules; this behavior was somewhat confusing. - If you need branch rules, you can manually write the equivalent rules. -* `dsl::integer()` now requires a token rule. This ensures the correct behavior in combination with whitespace skipping. -* *BEHAVIOR CHANGE*: branch parsing an identifier will now backtrack without raising an error if it can match an identifier, - but it is reserved. Previously, this would not backtrack and then raise an error (but trivially recover). - This behavior is consistent with `dsl::symbol()`. - -== 2021-10-07 - -* Removed branch functionality of token sequence (again). - It was already removed once as it was unimplementable due to automatic whitespace skipping, but then re-implemented later on. - But as it turns out, it is in fact unimplementable and the current implementation was completely broken. - Instead of `tok1 + tok2 >> rule1 | tok1 + tok3 >> rule2` use `tok1 >> (tok2 >> rule1 | tok3 >> rule2)`. -* Removed `dsl::encode()`. The rule was completely broken in combination with `dsl::capture()` and rules built on top like `dsl::identifier()`. -* *BEHAVIOR CHANGE*: error recovery now produces a new error token in the parse tree. - This ensures that the parse tree stays lossless even in the presence of errors. -* *Potential pitfall*: `dsl::recover()` and `dsl::find()` now always raise the recovery events. - If you're using them outside of `dsl::try_()`, this is not what you want, so don't do them - they're not meant for it. - -== 2021-08-22 - -`lexy::read_file_result` is no longer an input; you need to call `.buffer()` when passing it to a parse action. - -== 2021-08-17 - -Replaced `lexy_ext::dump_parse_tree()` by `lexy::visualize()`. - -== 2021-07-15 - -* Moved `lexy/match.hpp`, `lexy/parse.hpp`, and `lexy/validate.hpp` to `lexy/action/match.hpp`, `lexy/action/parse.hpp` and `lexy/action/validate.hpp`. -* Moved `lexy::parse_as_tree()` to new header `lexy/action/parse_as_tree.hpp`; `lexy::parse_tree` stayed in `lexy/parse_tree.hpp`. -* Renamed `lexy::parse_tree::builder::backtrack_production` to `cancel_production`, - and its `production_state` to `marker`. - -== 2021-07-01 - -* Moved callback adapters and composition into new header files, but still implicitly included by `callback.hpp`. -* Removed overload of `lexy::bind` that takes a sink; bind individual items in a separate production instead. -* Removed unneeded overloads of `lexy::as_sink` and changed the transcoding behavior: - It will now only use the pointer + size constructor if the character types match and no longer `reinterpret_cast`. - -== 2021-06-27 - -* Simplified and minimized interface of the input classes, removing e.g. iterators from them. -* Moved definition of `lexy::code_point` from `encoding.hpp` to new header `code_point.hpp`. - -== 2021-06-20 - -* Turned `dsl::else_` into a tag object that can only be used with `operator>>`, instead of a stand-alone rule. -* **BEHAVIOR CHANGE**: `dsl::peek[_not]()` and `dsl::lookahead()` are no longer no-ops when used outside a branch condition. - Instead, they will perform lookahead and raise an error if that fails. -* Removed `dsl::require/prevent(rule).error`; use `dsl::peek[_not](rule).error` instead. -* Improved and simplified interface for `dsl::context_flag` and `dsl::context_counter`: - instead of `.select()`/`.compare()`, you now use `.is_set()`/`.is()` as a branch condition, - and instead of `.require()`, you now use `dsl::must()` with `.is[_set]()`. -* Removed `dsl::context_lexeme`; use `dsl::context_identifier` instead. - -== 2021-06-18 - -* `lexy::fold[_inplace]` is now longer a callback, only a sink; - use `lexy::callback(lexy::fold(...))` to turn it into a callback if needed. -* Removed `dsl::opt_list()`; use `dsl::opt(dsl::list())` instead. -* *BEHAVIOR CHANGE*: `.opt_list()` of `dsl::terminator`/`dsl::brackets` now produces `lexy::nullopt` instead of an empty sink result if the list has no items. - If you're using pre-defined callbacks like `lexy::as_list`, `lexy::as_collection`, or `lexy::as_string`, it continues to work as expected. - If you're using `sink >> callback`, `callback` now requires one overload that takes `lexy::nullopt`. -* Removed `.while[_one]()` from `dsl::terminator`/`dsl::brackets`. - -== 2021-06-14 - -Choice (`operator|`) is no longer a branch rule if it would be an unconditional branch rule; -using an unconditional choice as a branch is almost surely a bug. - -== 2021-06-13 - -* Removed `dsl::label` and `dsl::id`; use a separate production instead. -* Removed `lexy::sink`; instead of `lexy::sink(fn)` use `lexy::fold_inplace({}, fn)`. -* *BEHAVIOR CHANGE*: `dsl::times`/`dsl::twice` no longer produce an array, but instead all values individually. - Use `lexy::fold` instead of a loop. - -== 2021-06-12 - -* Removed `lexy::null_input`. -* Downgraded `lexy/input/shell.hpp` to `lexy_ext/shell.hpp`, with the namespace change to `lexy_ext`. -* Removed `.capture()` from `dsl::code_point`; use `dsl::capture()` instead. -* *BEHAVIOR CHANGE*: Don't produce a tag value if no sign was present in `dsl::[minus/plus_]sign`. - If you use `lexy::as_integer` as callback, this doesn't affect you. -* *BEHAVIOR CHANGE*: Don't consume input in `dsl::prevent`. -* *BEHAVIOR CHANGE*: Produce only a single whitespace node in parse tree, instead of the individual token nodes. - Prohibited `dsl::p`/`dsl::recurse` inside the whitespace rule. - -== 2021-05-25 - -* Changed `dsl::[plus/minus_]sign` to produce `lexy::plus/minus_sign` instead of `+1`/`-1`. - Also changed callback `lexy::as_integer` to adapt. -* Removed `dsl::parse_state` and `dsl::parse_state_member`; use `lexy::bind()` with `lexy::parse_state` instead. -* Removed `dsl::value_*` rules; use `lexy::bind()` or `dsl::id`/`dsl::label` instead. - -== 2021-04-24 - -* The alternative rule `/` now tries to find the longest match instead of the first one. - If it was well-specified before, this doesn't change anything. -* Removed `dsl::switch_()`; use the new `dsl::symbol()` instead which is more efficient as well. -* Removed `.lit[_c]()` from `dsl::escape()`; use the new `.symbol()` instead. - -== 2021-03-29 - -* Restructure callback header files; an `#include ` might be necessary now. - -== 2021-03-29 - -* Support empty token nodes in the parse tree if they don't have an unknown kind. - In particular, the parse tree will now contain an EOF node at the end. -* Turn `lexy::unknown_token_kind` into a value (as opposed to the type it was before). - -== 2021-03-26 - -Renamed `lexy::raw_encoding` to `lexy::byte_encoding`. - -== 2021-03-23 - -* Changed the return type of `lexy::read_file()` (and `lexy_ext::read_file()`) to use a new `lexy::read_file_result` over `lexy::result`. -* Changed the return type of `lexy::validate()` and `lexy::parse_as_tree()` to a new `lexy::validate_result` type. -* Changed the return type of `lexy::parse()` to a new `lexy::parse_result` type. -* Removed `lexy::result`. -* An error callback that returns a non-void type must now be a sink. Use `lexy::collect(error_callback)` to create a sink that stores all results in the container. If the error callback returns void, no change is required. -* Removed `dsl::no_trailing_sep()`; `dsl::sep()` now has that behavior as well. -* `dsl::require()` and `dsl::prevent()` now recover from errors, which might lead to worse error messages in certain situations. - If they're used as intended -- to create a better error message if something didn't work out -- this shouldn't happen. - -== 2021-02-25 - -* Removed empty state from `lexy::result`. It was only added because it was useful internally, but this is no longer the case. -* Reverted optimization that merged multiple lexemes in the sink/tokens of `dsl::delimited()`. - Tokens are instead now automatically merged by the parse tree builder if direct children of a `lexy::token_production`. -* `dsl::switch_(rule).case_()` now requires a branch of the form `token >> rule`, previously it could take an arbitrary branch. - -== 2021-02-21 - -* Unified error interface: - ** `.error()` has become `.error` (e.g. for tokens, `dsl::switch()`). - ** `f(...)` has become `f(...).error` (e.g. for `dsl::require()`). - ** `ctx.require()` has become `ctx.require().error`. - ** `dsl::[partial_]combination()` now have `.missing_error` and `.duplicate_error` members. -* **BEHAVIOR CHANGE**: if `dsl::code_point_id` overflows, the tag is now `lexy::invalid_code_point` instead of `lexy::integer_overflow`. - -== 2021-02-20 - -* Replaced use of `lexy::_detail::string_view` by `const char*` in all user facing functions. - As a consequence, automatic type name now requires GCC > 8. -* Removed `lexy::make_error_location()`. It has been replaced by `lexy_ext::find_input_location()`. - -== 2021-02-17 - -Renamed `lexy::make_buffer` to `lexy::make_buffer_from_raw`. - -== 2021-02-04 - -Removed support for arbitrary rules as content of a `dsl::delimited()` rule, no only tokens are allowed. -Also removed support for an escape choice in the `dsl::delimited()` rule, it must be a branch now. - -As a related change, the sink will now be invoked with a `lexy::lexeme` that can span multiple occurrences of the content token, -not multiple times (one lexeme per token occurrence) as it was previously. -This means that a `dsl::quoted(dsl::code_point)` rule will now invoke the sink only once giving it a `lexy::lexeme` that spans the entire content of the string literal. -Previously it was invoked once per `dsl::code_point`. - -== 2021-01-11 - -Limited implicit conversion of `lexy::nullopt` to types that are like `std::optional` or pointers. -Replaced `lexy::dsl::nullopt` by `lexy::dsl::value_t` and `lexy::dsl::opt(rule)` by `rule | lexy::dsl::value_t` to keep the previous behavior of getting a default constructed object of type `T`. - -== 2021-01-10 - -* Replaced `operator[]` and `dsl::whitespaced()` by new `dsl::whitespace` rule. -Whitespace can now be parsed manually or automatically. -+ -To parse whitespace manually, replace `rule[ws]` by `rule + dsl::whitespace(rule)`, -or otherwise insert `dsl::whitespace(rule)` calls where appropriate. -See `examples/email.cpp` or `examples/xml.cpp` for an example of manual whitespace skipping. -+ -To parse whitespace automatically, define a `static constexpr auto whitespace` member in the root production of the grammar. -This rule is then skipped _after_ every token. -To temporarily disable automatic whitespace skipping inside one production, inherit from `lexy::token_production`. -See `examples/tutorial.cpp` or `examples/json.cpp` for an example of automatic whitespace skipping. - -* Removed support for choices in while, i.e. `dsl::while_(a | b | c)`. -This can be replaced by `dsl::loop(a | b | c | dsl::break_)`. - -== 2021-01-09 - -* Removed `.check()` from `dsl::context_flag` and `.check_eq/lt/gt` from `dsl::context_counter` due to implementation problems. -Use `.select()` and `.compare()` instead. - -* A sequence rule using `operator+` is now longer a branch. -Previously, it was a branch if it consisted of only tokens. -However, this was unimplementable in combination with automatic whitespace skipping. -+ -A branch condition that is a sequence is only required if you have something like `prefix + a >> rule_a | prefix + b >> rule_b`. -Use `prefix + (a >> rule_a | b >> rule_b)` instead. - -== 2021-01-08 - -Removed context sensitive parsing mechanism from `context.hpp` (`dsl::context_push()`, `_pop()` etc.). -Use `dsl::context_lexeme` instead: `.capture()` replaces `dsl::context_push()` and `.require()` replaces `dsl::context_pop()`. - -== 2021-01-03 - -* Removed callback from `lexy::as_list` and `lexy::as_collection`; they're now only sink. - `lexy::construct` can be used in most cases instead. -* Merged `::list` and `::value` callbacks from productions. - There are three cases: - ** A production has a `value` member only: this continues to work as before. - ** A production has a `list` member only: just rename it to `value`. It is treated as a sink automatically when required. - ** A production has a `list` and `value` member: - add a `value` member that uses `sink >> callback`, where `sink` was the previous `list` value and `callback` the previous `callback`. - This will use `sink` to construct the list then pass everything to `callback`. -* `lexy::result` now has an empty state. It is only used internally and never exposed to the user. - As a related change, the default constructor has been removed due to unclear semantics. - Use `lexy::result(lexy::result_error)` to restore its behavior of creating a default constructed error. - -== 2020-12-26 - -* Replaced `Pattern` concept with a new `Token` and `Branch` concept (See #10). -A `Branch` is a rule that can make branching decision (it is required by choices and can be used as branch condition). -A `Token` is an atomic parse unit; it is also a `Branch`. -+ -Most patterns (e.g. `LEXY_LIT`) are now tokens, which doesn't break anything. -Some patterns are now branches (e.g. `dsl::peek()`), which breaks in rules that now require tokens (e.g. `dsl::until()`). -The remaining patterns are now plain rules (e.g. `dsl::while_(condition >> then)`), which makes them unusable as branch conditions. -+ -The patterns that are now branches: -+ --- -** `dsl::error` -** `dsl::peek()` and `dsl::peek_not()` -** `condition >> then` was a pattern if `then` is a pattern, now it is always a branch --- -+ -The patterns that are now plain rules: -+ --- -** a sequence using `operator+` (it is still a token if all arguments are tokens, so it can be used as condition) -** a choice using `operator|`, even if all arguments are tokens (use `operator/` instead which is a token) -** `dsl::while_[one]()`, even if the argument is a token -** `dsl::times()` -** `dsl::if_()` --- -+ -The following rules previously required only patterns but now require tokens: -+ --- -** a minus using `operator-` (both arguments) -** `dsl::until()` -** `dsl::lookahead()` -** `dsl::escape()` (the escape character itself) and its `.capture()` -** digit separators -** automatic capturing of `dsl::delimited()` -** `lexy::make_error_location()` --- -+ -If you have a breaking change because you now use a non-token rule where a token was expected, use `dsl::token()`, -which turns an arbitrary rule into a token (just like `dsl::match()` turned a rule into a pattern). - -* Removed `dsl::match()`; use `dsl::token()` instead. - If you previously had `dsl::peek(dsl::match(rule)) >> then` you can now even use `dsl::peek(rule) >> then`, - as `dsl::peek[_not]()` have learned to support arbitrary rules. - -* Removed `dsl::try_(pattern)`. - If `pattern` is now a token, you can use `rule.error()` instead. - Otherwise, use `dsl::token(pattern).error()`. - -* Removed `.capture()` on `dsl::sep(pattern)` and `dsl::trailing_sep(pattern)`. - You can now use `dsl::sep(dsl::capture(pattern))`, - as `dsl::capture()` is now a branch and the separators have learned to support branches. - -* Removed `.zero()` and `.non_zero()` from `dsl::digit`. - Use `dsl::zero` instead of `dsl::digit.zero()`. - Use `dsl::digit - dsl::zero` (potentially with a nice error specified using `.error()`) instead of `dsl::digit.non_zero()`. - -* Removed `dsl::success`, as it is now longer needed internally. - It can be added back if needed. - -* *BEHAVIOR CHANGE*: As part of the branch changes, `dsl::peek()`, `dsl::peek_not()` and `dsl::lookahead()` are now no-ops if not used as branch condition. - For example, `prefix + dsl::peek(rule) + suffix` is equivalent to `prefix + suffix`. - In most cases, this is only a change in the error message as they don't consume characters. - Use `dsl::require()` and `dsl::prevent()` if the lookahead was intended. - -* *BEHAVIOR CHANGE*: Errors in whitespace are currently not reported. -For example, if you have `/* unterminated C comment int i;` and support space and C comments as whitespace, -this would previously raise an error about the unterminated C comment. -Right now, it will try to skip the C comment, fail, and then just be done with whitespace skipping. -The error for the unterminated C comment then manifests as `expected 'int', got '/*'`. -+ -This behavior is only temporary until a better solution for whitespace is implemented (see #10). - -== 2020-12-22 - -* Removed `dsl::build_list()` and `dsl::item()`. - They were mainly used to implement `dsl::list()`, and became unnecessary after an internal restructuring. -* Removed support for choices in lists, i.e. `dsl::list(a | b | c)`. - This can be added back if needed. -* Removed `dsl::operator!` due to implementation problems. - Existing uses of `dsl::peek(!rule)` can be replaced by `dsl::peek_not(rule)`; - existing uses of `!rule >> do_sth` can be replaced using `dsl::terminator()`. - diff --git a/assembler/ext/src/lexy/CMakeLists.txt b/assembler/ext/src/lexy/CMakeLists.txt deleted file mode 100644 index 5fb7e4bca7..0000000000 --- a/assembler/ext/src/lexy/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -# SPDX-License-Identifier: BSL-1.0 - -cmake_minimum_required(VERSION 3.8) -project(lexy VERSION 2022.05.0 LANGUAGES CXX) - -set(LEXY_USER_CONFIG_HEADER "" CACHE FILEPATH "The user config header for lexy.") -option(LEXY_FORCE_CPP17 "Whether or not lexy should use C++17 even if compiler supports C++20." ON) - -add_subdirectory(src) - -if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - cmake_minimum_required(VERSION 3.18) - option(LEXY_BUILD_BENCHMARKS "whether or not benchmarks should be built" OFF) - option(LEXY_BUILD_EXAMPLES "whether or not examples should be built" ON) - option(LEXY_BUILD_TESTS "whether or not tests should be built" ON) - option(LEXY_BUILD_DOCS "whether or not docs should be built" OFF) - option(LEXY_BUILD_PACKAGE "whether or not the package should be built" ON) - - if(LEXY_BUILD_PACKAGE) - set(package_files include/ src/ CMakeLists.txt LICENSE) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lexy-src.zip - COMMAND ${CMAKE_COMMAND} -E tar c ${CMAKE_CURRENT_BINARY_DIR}/lexy-src.zip --format=zip -- ${package_files} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${package_files}) - add_custom_target(lexy_package DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/lexy-src.zip) - endif() - - if(LEXY_BUILD_EXAMPLES) - add_subdirectory(examples) - endif() - if(LEXY_BUILD_BENCHMARKS) - add_subdirectory(benchmarks) - endif() - if(LEXY_BUILD_TESTS) - enable_testing() - add_subdirectory(tests) - endif() - if(LEXY_BUILD_DOCS) - add_subdirectory(docs EXCLUDE_FROM_ALL) - endif() -endif() - diff --git a/assembler/ext/src/lexy/LICENSE b/assembler/ext/src/lexy/LICENSE deleted file mode 100644 index 36b7cd93cd..0000000000 --- a/assembler/ext/src/lexy/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/assembler/ext/src/lexy/README.adoc b/assembler/ext/src/lexy/README.adoc deleted file mode 100644 index 6fe0bfa831..0000000000 --- a/assembler/ext/src/lexy/README.adoc +++ /dev/null @@ -1,173 +0,0 @@ -= lexy - -ifdef::env-github[] -image:https://img.shields.io/endpoint?url=https%3A%2F%2Fwww.jonathanmueller.dev%2Fproject%2Flexy%2Findex.json[Project Status,link=https://www.jonathanmueller.dev/project/] -image:https://github.com/foonathan/lexy/workflows/Main%20CI/badge.svg[Build Status] -image:https://img.shields.io/badge/try_it_online-blue[Playground,link=https://lexy.foonathan.net/playground] -endif::[] - -lexy is a parser combinator library for {cpp}17 and onwards. -It allows you to write a parser by specifying it in a convenient {cpp} DSL, -which gives you all the flexibility and control of a handwritten parser without any of the manual work. - -ifdef::env-github[] -*Documentation*: https://lexy.foonathan.net/[lexy.foonathan.net] -endif::[] - -.IPv4 address parser --- -ifndef::env-github[] -[.godbolt-example] -.+++{{< svg "icons/play.svg" >}}+++ -endif::[] -[source,cpp] ----- -namespace dsl = lexy::dsl; - -// Parse an IPv4 address into a `std::uint32_t`. -struct ipv4_address -{ - // What is being matched. - static constexpr auto rule = []{ - // Match a sequence of (decimal) digits and convert it into a std::uint8_t. - auto octet = dsl::integer; - - // Match four of them separated by periods. - return dsl::times<4>(octet, dsl::sep(dsl::period)) + dsl::eof; - }(); - - // How the matched output is being stored. - static constexpr auto value - = lexy::callback([](std::uint8_t a, std::uint8_t b, std::uint8_t c, std::uint8_t d) { - return (a << 24) | (b << 16) | (c << 8) | d; - }); -}; ----- --- - -== Features - -Full control:: - * *Describe the parser, not some abstract grammar*: - Unlike parser generators that use some table driven magic for parsing, lexy's grammar is just syntax sugar for a hand-written recursive descent parser. - The parsing algorithm does exactly what you've instructed it to do -- no more ambiguities or weird shift/reduce errors! - * *No implicit backtracking or lookahead*: - It will only backtrack when you say it should, and only lookahead when and how far you want it. - Don't worry about rules that have side-effects, they won't be executed unnecessarily thanks to the user-specified lookahead conditions. - https://lexy.foonathan.net/playground?example=peek[Try it online]. - * *Escape hatch for manual parsing*: - Sometimes you want to parse something that can't be expressed easily with lexy's facilities. - Don't worry, you can integrate a hand-written parser into the grammar at any point. - https://lexy.foonathan.net/playground/?example=scan[Try it online]. - * *Tracing*: - Figure out why the grammar isn't working the way you want it to. - https://lexy.foonathan.net/playground/?example=trace&mode=trace[Try it online]. - -Easily integrated:: - * *A pure {cpp} DSL*: - No need to use an external grammar file; embed the grammar directly in your {cpp} project using operator overloading and functions. - * *Bring your own data structures*: - You can directly store results into your own types and have full control over all heap allocations. - * *Fully `constexpr` parsing*: - You want to parse a string literal at compile-time? You can do so. - * *Minimal standard library dependencies*: - The core parsing library only depends on fundamental headers such as `` or ``; no big includes like `` or ``. - * *Header-only core library* (by necessity, not by choice -- it's `constexpr` after all). - -ifdef::env-github[Designed for text::] -ifndef::env-github[Designed for text (e.g. {{< github-example json >}}, {{< github-example xml >}}, {{< github-example email >}}) ::] - * *Unicode support*: parse UTF-8, UTF-16, or UTF-32, and access the Unicode character database to query char classes or perform case folding. - https://lexy.foonathan.net/playground?example=identifier-unicode[Try it online]. - * *Convenience*: - Built-in rules for parsing nested structures, quotes and escape sequences. - https://lexy.foonathan.net/playground?example=parenthesized[Try it online]. - * *Automatic whitespace skipping*: - No need to manually handle whitespace or comments. - https://lexy.foonathan.net/playground/?example=whitespace_comment[Try it online]. - -ifdef::env-github[Designed for programming languages::] -ifndef::env-github[Designed for programming languages (e.g. {{< github-example calculator >}}, {{< github-example shell >}})::] - * *Keyword and identifier parsing*: - Reserve a set of keywords that won't be matched as regular identifiers. - https://lexy.foonathan.net/playground/?example=reserved_identifier[Try it online]. - * *Operator parsing*: - Parse unary/binary operators with different precedences and associativity, including chained comparisons `a < b < c`. - https://lexy.foonathan.net/playground/?example=expr[Try it online]. - * *Automatic error recovery*: - Log an error, recover, and continue parsing! - https://lexy.foonathan.net/playground/?example=recover[Try it online]. - -ifdef::env-github[Designed for binary input::] -ifndef::env-github[Designed for binary input (e.g. {{< github-example protobuf >}})::] - * *Bytes*: Rules for parsing `N` bytes or Nbit big/little endian integer. - * *Bits*: Rules for parsing individual bit patterns. - * *Blobs*: Rules for parsing TLV formats. - -== FAQ - -Why should I use lexy over XYZ?:: - lexy is closest to other PEG parsers. - However, they usually do more implicit backtracking, which can hurt performance and you need to be very careful with rules that have side-effects. - This is not the case for lexy, where backtracking is controlled using branch conditions. - lexy also gives you a lot of control over error reporting, supports error recovery, special support for operator precedence parsing, and other advanced features. - - http://boost-spirit.com/home/[Boost.Spirit]::: - The main difference: it is not a Boost library. - Otherwise, it is just a different implementation with a different flavor. - Use lexy if you like lexy more. - https://github.com/taocpp/PEGTL[PEGTL]::: - PEGTL is very similar and was a big inspiration. - The biggest difference is that lexy uses an operator based DSL instead of inheriting from templated classes as PEGTL does; - depending on your preference this can be an advantage or disadvantage. - Hand-written Parsers::: - Writing a handwritten parser is more manual work and error prone. - lexy automates that away without having to sacrifice control. - You can use it to quickly prototype a parser and then slowly replace more and more with a handwritten parser over time; - mixing a hand-written parser and a lexy grammar works seamlessly. - -How bad are the compilation times?:: -They're not as bad as you might expect (in debug mode, that is). -+ -The example JSON parser compiles in about 2s on my machine. -If we remove all the lexy specific parts and just benchmark the time it takes for the compiler to process the datastructure (and stdlib includes), -that takes about 700ms. -If we validate JSON only instead of parsing it, so remove the data structures and keep only the lexy specific parts, we're looking at about 840ms. -+ -Keep in mind, that you can fully isolate lexy in a single translation unit that only needs to be touched when you change the parser. - -How bad are the {cpp} error messages if you mess something up?:: - They're certainly worse than the error message lexy gives you. - The big problem here is that the first line gives you the error, followed by dozens of template instantiations, which end at your `lexy::parse` call. - Besides providing an external tool to filter those error messages, there is nothing I can do about that. - -How fast is it?:: - Benchmarks are available in the `benchmarks/` directory. - A sample result of the JSON validator benchmark which compares the example JSON parser with various other implementations is available https://lexy.foonathan.net/benchmark_json/[here]. - -Why is it called lexy?:: - I previously had a tokenizer library called foonathan/lex. - I've tried adding a parser to it, but found that the line between pure tokenization and parsing has become increasingly blurred. - lexy is a re-imagination on of the parser I've added to foonathan/lex, and I've simply kept a similar name. - -ifdef::env-github[] -== Documentation - -The documentation, including tutorials, reference documentation, and an interactive playground can be found at https://lexy.foonathan.net/[lexy.foonathan.net]. - -A minimal `CMakeLists.txt` that uses lexy can look like this: - -.`CMakeLists.txt` -```cmake -project(lexy-example) - -include(FetchContent) -FetchContent_Declare(lexy URL https://lexy.foonathan.net/download/lexy-src.zip) -FetchContent_MakeAvailable(lexy) - -add_executable(lexy_example) -target_sources(lexy_example PRIVATE main.cpp) -target_link_libraries(lexy_example PRIVATE foonathan::lexy) -``` - -endif::[] - diff --git a/assembler/ext/src/lexy/benchmarks/CMakeLists.txt b/assembler/ext/src/lexy/benchmarks/CMakeLists.txt deleted file mode 100644 index f5b9c06df5..0000000000 --- a/assembler/ext/src/lexy/benchmarks/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -# SPDX-License-Identifier: BSL-1.0 - -# Fetch nanobench. -message(STATUS "Fetching nanobench") -include(FetchContent) -FetchContent_Declare(nanobench URL https://github.com/martinus/nanobench/archive/v4.3.0.zip) -FetchContent_MakeAvailable(nanobench) - -add_subdirectory(json) -add_subdirectory(file) - diff --git a/assembler/ext/src/lexy/benchmarks/file/CMakeLists.txt b/assembler/ext/src/lexy/benchmarks/file/CMakeLists.txt deleted file mode 100644 index f887ba154f..0000000000 --- a/assembler/ext/src/lexy/benchmarks/file/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -# SPDX-License-Identifier: BSL-1.0 - -# Benchmarking executable. -add_executable(lexy_benchmark_file) -target_sources(lexy_benchmark_file PRIVATE main.cpp) -target_link_libraries(lexy_benchmark_file PRIVATE foonathan::lexy::dev foonathan::lexy::file nanobench) -target_compile_definitions(lexy_benchmark_file PRIVATE LEXY_INCLUDE_DIR="${CMAKE_CURRENT_SOURCE_DIR}/../../include") -set_target_properties(lexy_benchmark_file PROPERTIES OUTPUT_NAME "file") - diff --git a/assembler/ext/src/lexy/benchmarks/file/main.cpp b/assembler/ext/src/lexy/benchmarks/file/main.cpp deleted file mode 100644 index 8085446c00..0000000000 --- a/assembler/ext/src/lexy/benchmarks/file/main.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#define ANKERL_NANOBENCH_IMPLEMENT -#include - -#include -#include -#include - -std::size_t use_buffer(const lexy::buffer<>& buffer) -{ - std::size_t sum = 0; - for (auto ptr = buffer.data(); ptr != buffer.data() + buffer.size(); ++ptr) - sum += std::size_t(*ptr); - - if (sum % 2 == 0) - return buffer.size(); - else - return buffer.size() + 1; -} - -std::size_t file_lexy(const char* path) -{ - auto result = lexy::read_file(path); - return use_buffer(result.buffer()); -} - -std::size_t file_cfile(const char* path) -{ - auto file = std::fopen(path, "rb"); - - std::fseek(file, 0, SEEK_END); - auto size = std::ftell(file); - std::fseek(file, 0, SEEK_SET); - - lexy::buffer<>::builder builder{std::size_t(size)}; - std::fread(builder.data(), 1, builder.size(), file); - std::fclose(file); - - // To get a fair comparison, we also need to use the copy. - auto make = lexy::make_buffer_from_raw; - auto buffer = make(builder.data(), builder.size()); - return use_buffer(buffer); -} - -std::size_t file_stream(const char* path) -{ - std::ifstream file(path, std::ios::binary | std::ios::ate); - auto size = file.tellg(); - file.seekg(0, std::ios::beg); - - lexy::buffer<>::builder builder{std::size_t(size)}; - file.read(builder.data(), size); - - // To get a fair comparison, we also need to use the copy. - auto make = lexy::make_buffer_from_raw; - auto buffer = make(builder.data(), builder.size()); - return use_buffer(buffer); -} - -constexpr auto bm_file_path = "bm-file.delete-me"; - -void write_file(std::size_t size) -{ - std::ofstream out(bm_file_path, std::ios::binary); - for (auto i = 0u; i != size / sizeof(i); ++i) - out.write(reinterpret_cast(&i), sizeof(i)); -} - -int main() -{ - ankerl::nanobench::Bench b; - - auto bench_data = [&](const char* title, std::size_t size, std::size_t iterations) { - b.minEpochIterations(iterations); - b.title(title).relative(true); - b.unit("byte").batch(size); - - write_file(size); - auto benchmark = [&](auto f) { return [f] { return f(bm_file_path); }; }; - - b.run("lexy", benchmark(file_lexy)); - - b.run("cfile", benchmark(file_cfile)); - b.run("stream", benchmark(file_stream)); - }; - - bench_data("128 B", 128, 10 * 1000); - bench_data("1 KiB", 1024, 10 * 1000); - bench_data("2 KiB", 2 * 1024, 10 * 1000); - bench_data("4 KiB", 4 * 1024, 10 * 1000); - - bench_data("8 KiB", 8 * 1024, 1000); - bench_data("16 KiB", 16 * 1024, 1000); - bench_data("32 KiB", 32 * 1024, 1000); - bench_data("64 KiB", 64 * 1024, 1000); - bench_data("128 KiB", 128 * 1024, 1000); - - bench_data("1 MiB", 1024 * 1024, 100); - - std::remove(bm_file_path); -} - diff --git a/assembler/ext/src/lexy/benchmarks/json/CMakeLists.txt b/assembler/ext/src/lexy/benchmarks/json/CMakeLists.txt deleted file mode 100644 index 891efd8b3c..0000000000 --- a/assembler/ext/src/lexy/benchmarks/json/CMakeLists.txt +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -# SPDX-License-Identifier: BSL-1.0 - -include(FetchContent) - -# Fetch benchmark data. -message(STATUS "Fetching json benchmark data") -function(fetch_data file url) - if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/data/${file}) - file(DOWNLOAD "${url}" "${CMAKE_CURRENT_BINARY_DIR}/data/${file}" STATUS status) - list(GET status 0 status_code) - list(GET status 1 status_string) - - if(NOT status_code EQUAL 0) - message(FATAL_ERROR "error downloading ${file}: ${status_string}") - endif() - endif() -endfunction() - -fetch_data(canada.json https://github.com/miloyip/nativejson-benchmark/raw/master/data/canada.json) -fetch_data(citm_catalog.json https://github.com/miloyip/nativejson-benchmark/raw/master/data/citm_catalog.json) -fetch_data(twitter.json https://raw.githubusercontent.com/miloyip/nativejson-benchmark/master/data/twitter.json) - -# Benchmarking executable. -add_executable(lexy_benchmark_json) -target_sources(lexy_benchmark_json PRIVATE main.cpp baseline.cpp lexy.cpp) -target_link_libraries(lexy_benchmark_json PRIVATE foonathan::lexy::dev foonathan::lexy::file nanobench) -target_compile_definitions(lexy_benchmark_json PRIVATE LEXY_BENCHMARK_DATA="${CMAKE_CURRENT_BINARY_DIR}/data/") -set_target_properties(lexy_benchmark_json PROPERTIES OUTPUT_NAME "json") - -# Compare with PEGTL's json parser. -message(STATUS "Fetching PEGTL") -FetchContent_Declare(pegtl URL https://github.com/taocpp/PEGTL/archive/main.zip) -if(NOT pegtl_POPULATED) - FetchContent_Populate(pegtl) - add_subdirectory(${pegtl_SOURCE_DIR} ${pegtl_BINARY_DIR} EXCLUDE_FROM_ALL) -endif() - -target_sources(lexy_benchmark_json PRIVATE pegtl.cpp) -target_link_libraries(lexy_benchmark_json PRIVATE taocpp::pegtl) - -# Compare with nlohmann/json. -message(STATUS "Fetching nlohmann/json") -FetchContent_Declare(nlohmann_json URL https://github.com/nlohmann/json/archive/develop.zip) -FetchContent_GetProperties(nlohmann_json) -if(NOT nlohmann_json_POPULATED) - FetchContent_Populate(nlohmann_json) -endif() - -target_sources(lexy_benchmark_json PRIVATE nlohmann.cpp) -target_include_directories(lexy_benchmark_json PRIVATE ${nlohmann_json_SOURCE_DIR}/include) - -# Compare with rapidjson. -message(STATUS "Fetching rapidjson") -FetchContent_Declare(rapidjson URL https://github.com/Tencent/rapidjson/archive/master.zip) -FetchContent_GetProperties(rapidjson) -if(NOT rapidjson_POPULATED) - FetchContent_Populate(rapidjson) -endif() - -target_sources(lexy_benchmark_json PRIVATE rapidjson.cpp) -target_include_directories(lexy_benchmark_json PRIVATE ${rapidjson_SOURCE_DIR}/include) - -# Compare with Boost.JSON. -find_package(Boost COMPONENTS json) -if (Boost_FOUND) - target_sources(lexy_benchmark_json PRIVATE boost.cpp) - target_link_libraries(lexy_benchmark_json PRIVATE Boost::json) - target_compile_definitions(lexy_benchmark_json PRIVATE LEXY_HAS_BOOST_JSON) -endif() - diff --git a/assembler/ext/src/lexy/benchmarks/json/baseline.cpp b/assembler/ext/src/lexy/benchmarks/json/baseline.cpp deleted file mode 100644 index 49b1350cfd..0000000000 --- a/assembler/ext/src/lexy/benchmarks/json/baseline.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include - -bool json_baseline(const lexy::buffer& input) -{ - // Just do something with the input. - std::size_t sum = 0; - for (auto ptr = input.data(); ptr != input.data() + input.size(); ++ptr) - sum += *ptr; - return sum % 11 == 0; -} - diff --git a/assembler/ext/src/lexy/benchmarks/json/boost.cpp b/assembler/ext/src/lexy/benchmarks/json/boost.cpp deleted file mode 100644 index 20095926f2..0000000000 --- a/assembler/ext/src/lexy/benchmarks/json/boost.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include -#include -#include - -using namespace boost::json; - -// Adapted from https://github.com/boostorg/json/blob/develop/example/validate.cpp -class null_parser -{ - struct handler - { - constexpr static std::size_t max_object_size = std::size_t(-1); - constexpr static std::size_t max_array_size = std::size_t(-1); - constexpr static std::size_t max_key_size = std::size_t(-1); - constexpr static std::size_t max_string_size = std::size_t(-1); - - bool on_document_begin(error_code&) - { - return true; - } - bool on_document_end(error_code&) - { - return true; - } - bool on_object_begin(error_code&) - { - return true; - } - bool on_object_end(std::size_t, error_code&) - { - return true; - } - bool on_array_begin(error_code&) - { - return true; - } - bool on_array_end(std::size_t, error_code&) - { - return true; - } - bool on_key_part(string_view, std::size_t, error_code&) - { - return true; - } - bool on_key(string_view, std::size_t, error_code&) - { - return true; - } - bool on_string_part(string_view, std::size_t, error_code&) - { - return true; - } - bool on_string(string_view, std::size_t, error_code&) - { - return true; - } - bool on_number_part(string_view, error_code&) - { - return true; - } - bool on_int64(std::int64_t, string_view, error_code&) - { - return true; - } - bool on_uint64(std::uint64_t, string_view, error_code&) - { - return true; - } - bool on_double(double, string_view, error_code&) - { - return true; - } - bool on_bool(bool, error_code&) - { - return true; - } - bool on_null(error_code&) - { - return true; - } - bool on_comment_part(string_view, error_code&) - { - return true; - } - bool on_comment(string_view, error_code&) - { - return true; - } - }; - - basic_parser p_; - -public: - null_parser() : p_(parse_options()) {} - - bool validate(const lexy::buffer& input) - { - error_code ec; - auto n - = p_.write_some(false, reinterpret_cast(input.data()), input.size(), ec); - if (!ec && n < input.size()) - ec = error::extra_data; - return !!ec; - } -}; - -bool json_boost(const lexy::buffer& input) -{ - return null_parser().validate(input); -} - diff --git a/assembler/ext/src/lexy/benchmarks/json/lexy.cpp b/assembler/ext/src/lexy/benchmarks/json/lexy.cpp deleted file mode 100644 index f5f2afac7f..0000000000 --- a/assembler/ext/src/lexy/benchmarks/json/lexy.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include -#include - -#define LEXY_TEST -#include "../../examples/json.cpp" - -bool json_lexy(const lexy::buffer& input) -{ - return lexy::validate(input, lexy::noop).is_success(); -} - diff --git a/assembler/ext/src/lexy/benchmarks/json/main.cpp b/assembler/ext/src/lexy/benchmarks/json/main.cpp deleted file mode 100644 index ef83e7f718..0000000000 --- a/assembler/ext/src/lexy/benchmarks/json/main.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#define ANKERL_NANOBENCH_IMPLEMENT -#include - -#include - -bool json_baseline(const lexy::buffer& input); -bool json_lexy(const lexy::buffer& input); -bool json_pegtl(const lexy::buffer& input); -bool json_nlohmann(const lexy::buffer& input); -bool json_rapid(const lexy::buffer& input); -bool json_boost(const lexy::buffer& input); - -auto get_data(const char* file_name) -{ - auto path = std::string(LEXY_BENCHMARK_DATA) + "/" + file_name; - auto result = lexy::read_file(path.c_str()); - if (!result) - throw std::runtime_error("unable to read data file"); - return LEXY_MOV(result).buffer(); -} - -const char* output_prefix() -{ - return R"(= JSON Validation Benchmark - -// This file is automatically generated by `lexy_benchmark_json`. -// DO NOT MODIFY. - -This benchmark measures the time it takes to *validate* JSON, i.e. to check whether it is well-formed. -Validation was chosen as opposed to parsing, as parsing speed depends on the JSON data structure as well. -Implementing an efficient JSON container is out of scope for lexy, so it would have a disadvantage over the specialized JSON libraries. - -The average validation times for each input are shown in the boxplots below. -Lower values are better. - -[pass] -++++ - -++++ - -)"; -} - -const char* output_template() -{ - return R"( -[pass] -++++ -
- -++++ - )"; -} - -const char* output_suffix() -{ - return R"( -.The implementations -`baseline`:: - This simply adds all input characters of the JSON document without performing actual validation. -`lexy`:: - A JSON validator using the lexy grammar from the example. -`pegtl`:: - A JSON validator using the https://github.com/taocpp/PEGTL[PEGTL] JSON grammar. -`nlohmann/json`:: - A JSON validator using https://github.com/nlohmann/json[JSON for Modern C++] implemented by `nlohmann::json::accept()`. -`rapidjson`:: - A JSON validator using https://github.com/Tencent/rapidjson[rapidjson] implemented using a SAX parser with the `rapidjson::BaseReaderHandler`. -`Boost.JSON`:: - A JSON validator using https://github.com/boostorg/json[Boost.JSON] implemented using a custom parse handler. - -.The inputs -`canada.json`:: - Contains lots of 2-element arrays holding floating-point coordinate pairs. - Taken from https://github.com/miloyip/nativejson-benchmark. -`citm_catalog.json`:: - Big JSON file with some variety. - Taken from https://github.com/miloyip/nativejson-benchmark. -`twitter.json`:: - Some data from twitter's API. - Taken from https://github.com/miloyip/nativejson-benchmark. - -.The Methodology -The input data is read using `lexy::read_file()`. -The resulting buffer is then passed to the various implementations using their memory inputs. -Benchmarking is done by https://nanobench.ankerl.com/[nanobench] on an AMD FX-6300. - )"; -} - -int main() -{ - std::ofstream out("benchmark_json.adoc"); - ankerl::nanobench::Bench b; - - auto bench_data = [&](const char* file) { - auto data = get_data(file); - - b.title(file).relative(true); - b.unit("byte").batch(data.size()); - b.minEpochIterations(10); - - b.run("baseline", [&] { return json_baseline(data); }); - b.run("lexy", [&] { return json_lexy(data); }); - b.run("pegtl", [&] { return json_pegtl(data); }); - b.run("nlohmann/json", [&] { return json_nlohmann(data); }); - b.run("rapidjson", [&] { return json_rapid(data); }); -#ifdef LEXY_HAS_BOOST_JSON - b.run("Boost.JSON", [&] { return json_boost(data); }); -#endif - - b.render(output_template(), out); - }; - - out << output_prefix(); - bench_data("canada.json"); - bench_data("citm_catalog.json"); - bench_data("twitter.json"); - out << output_suffix(); -} - diff --git a/assembler/ext/src/lexy/benchmarks/json/nlohmann.cpp b/assembler/ext/src/lexy/benchmarks/json/nlohmann.cpp deleted file mode 100644 index 49d4c16a31..0000000000 --- a/assembler/ext/src/lexy/benchmarks/json/nlohmann.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include -#include - -bool json_nlohmann(const lexy::buffer& input) -{ - return nlohmann::json::accept(input.data(), input.data() + input.size()); -} - diff --git a/assembler/ext/src/lexy/benchmarks/json/pegtl.cpp b/assembler/ext/src/lexy/benchmarks/json/pegtl.cpp deleted file mode 100644 index cf16365274..0000000000 --- a/assembler/ext/src/lexy/benchmarks/json/pegtl.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include - -#include -#include - -namespace pegtl = tao::pegtl; - -bool json_pegtl(const lexy::buffer& _input) -{ - using grammar = pegtl::seq; - - pegtl::memory_input input(reinterpret_cast(_input.data()), _input.size(), ""); - try - { - return pegtl::parse(input); - } - catch (const pegtl::parse_error&) - { - return false; - } -} - diff --git a/assembler/ext/src/lexy/benchmarks/json/rapidjson.cpp b/assembler/ext/src/lexy/benchmarks/json/rapidjson.cpp deleted file mode 100644 index 870fd2bbbc..0000000000 --- a/assembler/ext/src/lexy/benchmarks/json/rapidjson.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include -#include - -bool json_rapid(const lexy::buffer& input) -{ - rapidjson::MemoryStream stream(reinterpret_cast(input.data()), input.size()); - rapidjson::BaseReaderHandler<> handler; - - rapidjson::Reader reader; - return !reader.Parse(stream, handler).IsError(); -} - diff --git a/assembler/ext/src/lexy/docs/CMakeLists.txt b/assembler/ext/src/lexy/docs/CMakeLists.txt deleted file mode 100644 index 4afcdf71b7..0000000000 --- a/assembler/ext/src/lexy/docs/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -# SPDX-License-Identifier: BSL-1.0 - -find_program(HUGO_BINARY hugo) -if(NOT HUGO_BINARY) - message(WARNING "hugo not found, won't be able to generate documentation") -endif() - -add_custom_command(OUTPUT content/_index.adoc - COMMAND ${CMAKE_COMMAND} -E copy ../README.adoc content/_index.adoc - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../README.adoc) -add_custom_command(OUTPUT content/learn/changelog.adoc - COMMAND ${CMAKE_COMMAND} -E echo "---" > content/learn/changelog.adoc - COMMAND ${CMAKE_COMMAND} -E echo "title: Changelog" >> content/learn/changelog.adoc - COMMAND ${CMAKE_COMMAND} -E echo "---" >> content/learn/changelog.adoc - COMMAND ${CMAKE_COMMAND} -E cat ../CHANGELOG.adoc >> content/learn/changelog.adoc - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../CHANGELOG.adoc) - -set(resolver "${CMAKE_CURRENT_SOURCE_DIR}/../support/resolve-lexy-headers.py") -add_custom_command(OUTPUT assets/cpp/playground_headers.single.hpp - COMMAND ${resolver} assets/cpp/playground_headers.hpp assets/cpp/playground_headers.single.hpp - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS foonathan::lexy) - -add_custom_command(OUTPUT static/download - COMMAND ${CMAKE_COMMAND} -E make_directory static/download - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_custom_command(OUTPUT static/download/lexy-src.zip - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/../lexy-src.zip static/download/lexy-src.zip - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS lexy_package) - -set(generated_files content/_index.adoc content/learn/changelog.adoc assets/cpp/playground_headers.single.hpp static/download/lexy-src.zip) -add_custom_target(lexy_docs - COMMAND ${HUGO_BINARY} --minify - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${generated_files}) -add_custom_target(lexy_docs_serve - COMMAND ${HUGO_BINARY} serve - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - USES_TERMINAL - DEPENDS ${generated_files}) - diff --git a/assembler/ext/src/lexy/docs/archetypes/default.md b/assembler/ext/src/lexy/docs/archetypes/default.md deleted file mode 100644 index 00e77bd79b..0000000000 --- a/assembler/ext/src/lexy/docs/archetypes/default.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: "{{ replace .Name "-" " " | title }}" -date: {{ .Date }} -draft: true ---- - diff --git a/assembler/ext/src/lexy/docs/archetypes/dsl.adoc b/assembler/ext/src/lexy/docs/archetypes/dsl.adoc deleted file mode 100644 index faa5c0f6a5..0000000000 --- a/assembler/ext/src/lexy/docs/archetypes/dsl.adoc +++ /dev/null @@ -1,52 +0,0 @@ ---- -header: "lexy/dsl/XXX.hpp" -entities: - "lexy::dsl::XXX": XXX ---- -:toc: left - -[.lead] -One line description of the header. - -[#XXX] -== Rule `lexy::dsl::XXX` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto XXX; -} ----- - -[.lead] -`XXX` is a rule that does something. - -Requires:: - Any additional requirements not seen in the interface. -Matching:: - Describe what is being matched and consumed without producing values. - Use "match" to refer to an operation that can raise errors; - "try match" to refer to an operation that cannot raise errors. -Parsing:: - Describe what is being matched and consumed while producing values. - Use either "matching" or "parsing". -Branch parsing:: - Describe what differs when the rule is parsed as a branch. - Use only in combination with "parsing". -Errors:: - * `Tag`: when this error is raised and at what position. - When the error is raised can be omitted if there is only one error and it is obvious what can fail. - Say the rule fails if parsing does not continue after the error. - Say the rule recovers and describe what is being consumed otherwise. -Values:: - Describe all values that are produced. -Parse tree:: - If something special happens with the parse tree, mention it here. - -Anything else that does not fit the things above. - -{{% playground_example default "Some example" %}} - -NOTE: Any notes. - diff --git a/assembler/ext/src/lexy/docs/assets/cpp/godbolt_main.cpp b/assembler/ext/src/lexy/docs/assets/cpp/godbolt_main.cpp deleted file mode 100644 index fd1f059196..0000000000 --- a/assembler/ext/src/lexy/docs/assets/cpp/godbolt_main.cpp +++ /dev/null @@ -1,20 +0,0 @@ -//=== main function ===// -#include -#include -#include -#include - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - - lexy::parse_tree_for tree; - auto result - = lexy::parse_as_tree(tree, input, lexy_ext::report_error); - - lexy::visualize(stdout, tree, {lexy::visualize_fancy}); - - if (!result) - return 1; -} - diff --git a/assembler/ext/src/lexy/docs/assets/cpp/godbolt_prefix.cpp b/assembler/ext/src/lexy/docs/assets/cpp/godbolt_prefix.cpp deleted file mode 100644 index 3113bca168..0000000000 --- a/assembler/ext/src/lexy/docs/assets/cpp/godbolt_prefix.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#define LEXY_HAS_UNICODE_DATABASE 1 -#include - -namespace dsl = lexy::dsl; - -//=== grammar ===// diff --git a/assembler/ext/src/lexy/docs/assets/cpp/playground_headers.hpp b/assembler/ext/src/lexy/docs/assets/cpp/playground_headers.hpp deleted file mode 100644 index 87a756bff6..0000000000 --- a/assembler/ext/src/lexy/docs/assets/cpp/playground_headers.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#define LEXY_HAS_UNICODE_DATABASE 1 -#include -#include -#include -#include -#include -#include - diff --git a/assembler/ext/src/lexy/docs/assets/cpp/playground_main.cpp b/assembler/ext/src/lexy/docs/assets/cpp/playground_main.cpp deleted file mode 100644 index 8837d89614..0000000000 --- a/assembler/ext/src/lexy/docs/assets/cpp/playground_main.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef LEXY_TEST -# line 1 "playground.cpp" -#endif - -namespace -{ -struct print_quoted_iterator -{ - auto operator*() const noexcept - { - return *this; - } - auto operator++(int) const noexcept - { - return *this; - } - - print_quoted_iterator& operator=(char c) - { - if (c == '"') - std::fputs(R"(\")", stdout); - else if (c == '\\') - std::fputs(R"(\\)", stdout); - else - std::fputc(c, stdout); - return *this; - } -}; -} // namespace - -int main(int, char* argv[]) -{ - auto input = lexy_ext::compiler_explorer_input(); - - if (argv[1] == lexy::_detail::string_view("tree")) - { - lexy::parse_tree_for tree; - auto result - = lexy::parse_as_tree(tree, input, lexy_ext::report_error); - - std::puts("graph \"Parse Tree\" {"); - std::puts("bgcolor=transparent"); - for (auto [event, node] : tree.traverse()) - { - switch (event) - { - case lexy::traverse_event::enter: - std::printf( - "\"node-%p\" [label=\"%s\", tooltip=\"production\", shape=ellipse, style=bold];\n", - node.address(), node.kind().name()); - break; - - case lexy::traverse_event::exit: - // Now we can add all the connections. - for (auto child : node.children()) - std::printf("\"node-%p\" -- \"node-%p\";\n", node.address(), child.address()); - break; - - case lexy::traverse_event::leaf: - std::printf("\"node-%p\" [label=\"", node.address()); - if (node.lexeme().empty()) - { - std::printf("%s\"", node.kind().name()); - } - else - { - lexy::visualize_to(print_quoted_iterator{}, node.lexeme(), - {lexy::visualize_use_unicode | lexy::visualize_use_symbols - | lexy::visualize_space}); - std::puts("\", style=filled"); - } - - std::puts("shape=box"); - if (node.kind() == lexy::error_token_kind) - std::puts(", fontcolor=red"); - else if (node.kind() == lexy::whitespace_token_kind) - std::puts(", fontcolor=gray30"); - std::printf(", tooltip=\"%s\"", node.kind().name()); - std::puts("];"); - break; - } - } - std::puts("}"); - - if (result.is_success()) - return 0; - else if (result.is_recovered_error()) - return 1; - else if (result.is_fatal_error()) - return 2; - } - else if (argv[1] == lexy::_detail::string_view("trace")) - { - lexy::trace(stdout, input, {lexy::visualize_fancy}); - return 0; - } - else - { - std::fputs("invalid argument", stderr); - return 3; - } -} - diff --git a/assembler/ext/src/lexy/docs/assets/cpp/playground_prefix.cpp b/assembler/ext/src/lexy/docs/assets/cpp/playground_prefix.cpp deleted file mode 100644 index 7aaabccfe3..0000000000 --- a/assembler/ext/src/lexy/docs/assets/cpp/playground_prefix.cpp +++ /dev/null @@ -1,2 +0,0 @@ -namespace dsl = lexy::dsl; -#line 1 "grammar.cpp" diff --git a/assembler/ext/src/lexy/docs/assets/css/_base.scss b/assembler/ext/src/lexy/docs/assets/css/_base.scss deleted file mode 100644 index d34f6d3f58..0000000000 --- a/assembler/ext/src/lexy/docs/assets/css/_base.scss +++ /dev/null @@ -1,47 +0,0 @@ -:root { - --white: white; - --background-color: #fdfdfd; - --default-color: #101010; - --heading-color: #0A0A0A; - --link-color: #2A2A2A; - --gray-highlight-color: #aaaaaa; - - --highlight-color: #2861ce; - - @media (prefers-color-scheme: dark) { - --white: #202020; - --background-color: #222222; - --default-color: #efefef; - --heading-color: #f5f5f5; - --link-color: #d5d5d5; - --gray-highlight-color: #555555; - } -} - -$white: var(--white); -$background-color: var(--background-color); -$default-color: var(--default-color); -$heading-color: var(--heading-color); -$link-color: var(--link-color); -$highlight-color: var(--highlight-color); -$gray-highlight-color: var(--gray-highlight-color); - -$serif-font: serif; -$sans-font: sans-serif; -$code-font: Inconsolata,monospace,sans-serif; - -$footer-offset: 75px; - -%limited-width { - max-width: 1250px; - margin: 0 auto 0 auto; - padding: 0 10px 0 10px; -} - -%content-width { - @media (min-width: 800px) { - max-width: 900px; - padding: 0 10px 0 10px; - } -} - diff --git a/assembler/ext/src/lexy/docs/assets/css/playground.scss b/assembler/ext/src/lexy/docs/assets/css/playground.scss deleted file mode 100644 index 16ab8652ad..0000000000 --- a/assembler/ext/src/lexy/docs/assets/css/playground.scss +++ /dev/null @@ -1,96 +0,0 @@ -@import "base"; - -nav#menu div.menu-container { - max-width: initial; -} - -#playground { - padding: 1em; -} - -#toolbar { - display: flex; - justify-content: space-between; - align-items: baseline; - - margin-bottom: 1em; - - input[type="checkbox"] - { - vertical-align: middle; - } - select, button { - background-color: $white; - color: $default-color; - border: 1px solid $gray-highlight-color; - border-radius: 3px; - padding: 5px; - } - - #toolbar-godbolt { - img { - height: 1em; - } - } -} - -#editors { - display: flex; - flex-wrap: wrap; - margin-bottom: 5px; - - .editor-container { - flex: 1; - min-width: 30em; - height: 30em; - - border: 1px solid $gray-highlight-color; - margin: 5px; - } - .editor { - position: relative; - width: 100%; - height: 100%; - } - - .ace_editor { - background-color: $background-color; - color: $default-color; - } - .ace_gutter { - background-color: $white; - color: $default-color; - } - .ace_gutter-active-line { - background-color: $white; - color: $gray-highlight-color; - } -} - -#output { - display: flex; - flex-wrap: wrap; - margin-bottom: 5px; - - .output-container { - flex: 1; - min-width: 30em; - - border: 1px solid $gray-highlight-color; - padding: 2px 5px; - margin: 5px; - } - #output-text { - font-family: monospace; - white-space: pre-wrap; - } - #output-graph { - display: none; - - svg { - width: 100%; - background-color: #fdfdfd; - } - } -} - diff --git a/assembler/ext/src/lexy/docs/assets/css/style.scss b/assembler/ext/src/lexy/docs/assets/css/style.scss deleted file mode 100644 index ff34a791ea..0000000000 --- a/assembler/ext/src/lexy/docs/assets/css/style.scss +++ /dev/null @@ -1,527 +0,0 @@ -@import "base"; - -//=== general style ===// -html { - position: relative; - min-height: 100%; - margin: 0; - padding: 0; - -} -body { - font-family: $serif-font; - font-size: 18px; - color: $default-color; - background-color: $background-color; - width: 100%; - padding: 0; - margin: 0; -} - -main { - @extend %limited-width; - margin-bottom: $footer-offset; - display: flex; - justify-content: center; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - font-family: $sans-font; - font-weight: bold; - line-height: 1.15em; - color: $heading-color; - margin: 0 0 0.4em 0; - hyphens: auto; -} -h1 { - font-size: 2em; -} -h2 { - font-size: 1.75em; -} -h3 { - font-size: 1.5em; -} -h4 { - font-size: 1.25em; -} -h5 { - font-size: 1.15em; -} -h6 { - font-size: 1.1em; -} - -a, a svg, button svg { - color: $link-color; - transition: color ease 0.3s; -} -a:hover, a svg:hover, button svg:hover { - color: $highlight-color; -} -a:focus, a svg:focus, button svg:focus { - outline: none; -} - -br { - margin: 1em; -} - -article { - @extend %content-width; - flex: 1; - min-width: 0; -} -article p, -article ul, -article ol, -article dl, -article td { - hyphens: auto; - text-align: justify; -} - -//=== menu ===// -nav#menu { - width: 100%; - padding: 0px; - - background-color: $white; - border-bottom: 2px solid $highlight-color; - - font-family: $sans-font; - font-size: 1.3em; - - div.menu-container { - @extend %limited-width; - display: flex; - - ul { - display: flex; - flex-direction: row; - align-items: center; - - padding: 0px; - - list-style: none; - - li { - a { - text-decoration: none; - - svg { - height: 1em; - } - } - a.active { - border-width: 0 0 2px; - border-style: solid; - border-color: $highlight-color; - } - } - } - ul#home { - padding-left: 0px; - padding-right: 10px; - - .title { - font-weight: bold; - } - } - ul#main { - margin-left: auto; - li { - padding-left: 20px; - } - } - @media (max-width: 600px) { - ul#main { - flex-direction: column; - align-items: flex-end; - margin: 5px 10px 0 auto; - } - } - } -} - -//=== footer ===// -footer#page-footer { - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 2em; - - display: flex; - justify-content: space-between; - - font-size: .8em; - font-weight: 200; - line-height: 1em; - border-top: 1px solid #ccc; - - section { - padding-left: 1em; - padding-right: 1em; - padding-top: .5em; - width: 100%; - } - .copyright { - text-align: left; - } - .patreon { - text-align: center; - } - .poweredby { - text-align: right; - } - - @media (max-width: 450px) { - flex-direction: column; - align-items: flex-start; - section { - text-align: initial !important; - width: initial; - } - } -} - -//=== TOC ===// -aside.toc { - display: none; -} - -@media (min-width: 1100px) { - aside.toc { - display: initial; - - position: sticky; - top: 0em; - min-width: 200px; - max-width: 350px; - padding-right: 1em; - align-self: flex-start; - hyphens: auto; - - header { - margin-top: 1em; - font-weight: bold; - } - - ul { - list-style: none; - padding: 0; - ul { - padding-left: 1em; - padding-bottom: .2em; - } - li { - padding-bottom: .2em; - } - } - a { - text-decoration: none; - } - } -} - -//=== body ===// -article { - svg { - height: 1em; - position: relative; - top: 2px; - padding-right: 3px; - } - p svg:not(:first-child) { - padding-left: .25em; - } - - header { - margin-top: 1em; - margin-bottom: 1em; - - nav { - display: flex; - flex-wrap: wrap; - - a { - text-decoration: none; - padding-right: 7px; - } - - form.search { - @media(min-width: 700px) { - margin-left: auto; - } - - input[type=search] { - padding: 2px; - width: 250px; - } - input[type=search]:focus { - border-color: $highlight-color; - outline: solid $highlight-color 1px; - } - button[type=submit] { - margin-left: -25px; - border: none; - background: initial; - } - } - } - } - - .lead p { - font-weight: 500; - font-size: 1.1em; - } - - .admonitionblock { - margin-bottom: 1em; - - td.icon { - font-weight: bold; - } - td.content { - div:first-child p { - margin-top: 0; - } - div:last-child p { - margin-bottom: 0; - } - } - - @media (max-width: 600px) { - tr { - display: block; - float: left; - padding-left: .5em; - padding-right: .5em; - - td { - display: block; - } - } - } - @media (min-width: 600px) { - td.icon { - width: 75px; - text-align: center; - border-right: 1px solid $gray-highlight-color; - } - td.content { - padding-left: .5em; - } - } - } - - .exampleblock { - margin-top: 1em; - margin-bottom: 1em; - - .title { - font-style: italic; - } - } - - a.github-example { - text-decoration: none; - svg { - height: .8em; - position: relative; - top: 2px; - } - } - - // the try it online link - .playground-example .title, .godbolt-example .title { - position: relative; - a { - position: absolute; - top: 7px; - right: 7px; - - svg { - height: 1em; - } - } - } - - details { - margin-bottom: 1em; - summary { - font-style: italic; - } - } - - // list - ul, ol { - p { - margin: .2em; - } - } - // no margin if it has a title - div ul:not(:first-child), div ol:not(:first-child) { - margin-top: 0; - } - - // definition list - dl { - dt { - margin-top: .5em; - font-weight: bold; - } - dd p, dd div:only-child ul { - margin: 0; - padding: 0; - } - } - // no margin if it has a title - div dl:not(:first-child) { - margin-top: 0; - } - - // table - table.tableblock { - background: $white; - margin: 0 auto; - border-collapse: collapse; - td, th { - border: 1px solid $gray-highlight-color; - padding: 5px; - - text-align: left; - p { - margin: 0; - } - } - } - - // sidebar - div.sidebarblock { - border: 1px solid $gray-highlight-color; - padding: .75em; - margin: 1em; - - p { - margin: 0; - } - } - - // inline code and code blocks - code { - font-family: $code-font; - } - // code blocks - pre { - margin-top: 0; - overflow: auto; - padding: 10px; - background: $white; - border: 1px solid $gray-highlight-color; - line-height: 1.1; - } - - // callouts - .colist { - margin-top: -.5em; - - ol { - counter-reset: list; - - li { - counter-increment: list; - padding-left: 1em; - } - ::marker { - content: "(" counter(list) ")"; - font-weight: bold; - } - } - - p { - margin: 0; - } - } -} - -// code highlight -.highlight, .ace_editor { - // comment - .tok-c, .tok-cm, .tok-cp, .tok-c1, .tok-cs { - color: #999988; - font-style: italic; - font-weight: initial; - } - - // keyword - .tok-k, .tok-kc, .tok-kd, .tok-kp, .tok-kr, .tok-kt, - .ace_storage, .ace_keyword, { - color: #445588; - font-style: initial; - font-weight: bold; - } - // operator, punctuator - .tok-o, .tok-p, - .ace_keyword.ace_operator, .ace_paren, .ace_punctuation { - color: #ff0000; - font-style: initial; - font-weight: initial; - } - - // DSL entity - .ace_dsl { - pointer-events: auto; - } - - // number - .tok-m, .tok-mf, .tok-mh, .tok-mi, .tok-mo, - .ace_constant { - color: #FF8000; - font-style: initial; - font-weight: initial; - } - // string - .tok-s, .tok-sb, .tok-sc, .tok-sd, .tok-s2, .tok-s3, - .tok-sh, .tok-si, .tok-sx, .tok-sr, .tok-s1, .tok-ss, .tok-se, - .ace_string { - color: #008000; - font-style: initial; - font-weight: initial; - } - // preprocessor - .tok-cp, .tok-cpf { - color: #008000; - font-style: initial; - font-weight: bold; - } - - // error - .tok-err, - .ace_invalid { - color: #ff0000; - font-style: initial; - font-weight: initial; - } - - // hack to allow asterisk: - // we don't style strong in a special way, and manually add back the asterisk - strong { - font-weight: initial; - } - strong:not(:empty)::before { - content: "*"; - color: #ff0000; - } - strong:not(:empty)::after { - content: "*"; - color: #ff0000; - } -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/argv_input.cpp b/assembler/ext/src/lexy/docs/assets/examples/argv_input.cpp deleted file mode 100644 index c69fdaec37..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/argv_input.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include - -#include -#include -#include - -struct production -{ - static constexpr auto rule = LEXY_LIT("Hi"); -}; - -//{ -int main(int argc, char* argv[]) -{ - // Create the input. - lexy::argv_input input(argc, argv); - - // Use the input. - if (!lexy::match(input)) - { - std::puts("Error!\n"); - return 1; - } -} -//} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/argv_input.input b/assembler/ext/src/lexy/docs/assets/examples/argv_input.input deleted file mode 100644 index fbb565f2ea..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/argv_input.input +++ /dev/null @@ -1 +0,0 @@ -ARGV:Hi diff --git a/assembler/ext/src/lexy/docs/assets/examples/argv_iterator.cpp b/assembler/ext/src/lexy/docs/assets/examples/argv_iterator.cpp deleted file mode 100644 index 17e1ff7a5b..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/argv_iterator.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -//{ -int main(int argc, char* argv[]) -{ - auto begin = lexy::argv_begin(argc, argv); - auto end = lexy::argv_end(argc, argv); - - for (auto cur = begin; cur != end; ++cur) - { - if (*cur == '\0') - std::puts("\\0"); - else - std::printf("%c", *cur); - } - std::puts("\\0"); // last null terminator not included in the range -} -//} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/argv_iterator.input b/assembler/ext/src/lexy/docs/assets/examples/argv_iterator.input deleted file mode 100644 index cf014b86ec..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/argv_iterator.input +++ /dev/null @@ -1 +0,0 @@ -ARGV:first second third diff --git a/assembler/ext/src/lexy/docs/assets/examples/as_list-allocator.cpp b/assembler/ext/src/lexy/docs/assets/examples/as_list-allocator.cpp deleted file mode 100644 index a69d2adaf3..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/as_list-allocator.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct state -{ - std::allocator allocator; // The allocator that should be used. - // Potentially other members here. -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto integer = dsl::integer; - return dsl::list(integer, dsl::sep(dsl::comma)); - }(); - - static constexpr auto value - // Pass the allocator to the sink. - = lexy::as_list>.allocator(&state::allocator); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, state(), lexy_ext::report_error); - if (!result) - return 1; - - std::printf("numbers: "); - for (auto i : result.value()) - std::printf("%d ", i); - std::putchar('\n'); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/as_list.cpp b/assembler/ext/src/lexy/docs/assets/examples/as_list.cpp deleted file mode 100644 index 5b2665bd96..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/as_list.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto integer = dsl::integer; - return dsl::list(integer, dsl::sep(dsl::comma)); - }(); - - static constexpr auto value = lexy::as_list>; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("numbers: "); - for (auto i : result.value()) - std::printf("%d ", i); - std::putchar('\n'); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/as_list.input b/assembler/ext/src/lexy/docs/assets/examples/as_list.input deleted file mode 100644 index 2739d724db..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/as_list.input +++ /dev/null @@ -1 +0,0 @@ -1, 2, 3 diff --git a/assembler/ext/src/lexy/docs/assets/examples/bind-constant.cpp b/assembler/ext/src/lexy/docs/assets/examples/bind-constant.cpp deleted file mode 100644 index 833eaab26c..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/bind-constant.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include - -//{ -constexpr auto my_callback - = lexy::callback([](int factor, int i) { return factor * i; }, - [](int factor, int a, int b) { return factor * (a + b); }); - -// Bind all arguments. -constexpr auto bound = lexy::bind(my_callback, 2, 11); -//} - -int main() -{ - std::printf("zero arguments: %d\n", bound()); // 2 * 11 - std::printf("one argument: %d\n", bound(42)); // 2 * 11 -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/bind-fallback.cpp b/assembler/ext/src/lexy/docs/assets/examples/bind-fallback.cpp deleted file mode 100644 index 2f688e73f9..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/bind-fallback.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct decimal -{ - int integer; - std::string fraction; -}; - -struct production -{ - struct fraction - { - static constexpr auto rule = dsl::capture(dsl::digits<>); - static constexpr auto value = lexy::as_string; - }; - - static constexpr auto rule = [] { - auto integer = dsl::integer; - - return integer + dsl::opt(dsl::period >> dsl::p); - }(); - - static constexpr auto value = lexy::bind(lexy::construct, - // If the second argument is lexy::nullopt, - // produce a zero instead. - lexy::_1, lexy::_2 or "0"); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("The value is: %d.%s\n", result.value().integer, result.value().fraction.c_str()); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/bind-fallback.input b/assembler/ext/src/lexy/docs/assets/examples/bind-fallback.input deleted file mode 100644 index d81cc0710e..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/bind-fallback.input +++ /dev/null @@ -1 +0,0 @@ -42 diff --git a/assembler/ext/src/lexy/docs/assets/examples/bind-parse_state.cpp b/assembler/ext/src/lexy/docs/assets/examples/bind-parse_state.cpp deleted file mode 100644 index d2cb8bcd51..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/bind-parse_state.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct entry -{ - std::string name; - int a, b; -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto integer = dsl::integer; - return dsl::twice(integer, dsl::sep(dsl::comma)); - }(); - - // Construct the entry where the name is taken from the parse state. - static constexpr auto value - = lexy::bind(lexy::construct, lexy::parse_state, lexy::values); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, "foo", lexy_ext::report_error); - if (!result) - return 1; - - std::printf("%s: %d, %d\n", result.value().name.c_str(), result.value().a, result.value().b); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/bind-parse_state.input b/assembler/ext/src/lexy/docs/assets/examples/bind-parse_state.input deleted file mode 100644 index 2fe09c6cf0..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/bind-parse_state.input +++ /dev/null @@ -1 +0,0 @@ -11, 42 diff --git a/assembler/ext/src/lexy/docs/assets/examples/bind-reorder-map.cpp b/assembler/ext/src/lexy/docs/assets/examples/bind-reorder-map.cpp deleted file mode 100644 index ceda26242e..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/bind-reorder-map.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -//{ -constexpr auto my_callback = lexy::callback([](int a, int b) { return a - b; }); - -// Swap the arguments... -constexpr auto bound = lexy::bind(my_callback, lexy::_2, - // ... and double the (old) first one. - lexy::_1.map([](int i) { return 2 * i; })); -//} - -int main() -{ - std::printf("result: %d\n", bound(11, 42)); // 42 - 22 -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/bind-values.cpp b/assembler/ext/src/lexy/docs/assets/examples/bind-values.cpp deleted file mode 100644 index f6f21795f4..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/bind-values.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include - -//{ -constexpr auto my_callback - = lexy::callback([](int factor, int i) { return factor * i; }, - [](int factor, int a, int b) { return factor * (a + b); }); - -// Bind the first parameter and forward the rest unchanged. -constexpr auto bound = lexy::bind(my_callback, 2, lexy::values); -//} - -int main() -{ - std::printf("one argument: %d\n", bound(11)); // 2 * 11 - std::printf("two arguments: %d\n", bound(11, 42)); // 2 * (11 + 42) -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/bind_sink-parse_state.cpp b/assembler/ext/src/lexy/docs/assets/examples/bind_sink-parse_state.cpp deleted file mode 100644 index b7b908bc87..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/bind_sink-parse_state.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct state -{ - std::allocator allocator; // The allocator that should be used. - // Potentially other members here. -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto integer = dsl::integer; - return dsl::list(integer, dsl::sep(dsl::comma)); - }(); - - static constexpr auto value - // Pass the allocator to the sink. - // Note: this is the same as the `.allocator(&state::allocator)`. - = lexy::bind_sink(lexy::as_list>, - lexy::parse_state.map(&state::allocator)); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, state(), lexy_ext::report_error); - if (!result) - return 1; - - std::printf("numbers: "); - for (auto i : result.value()) - std::printf("%d ", i); - std::putchar('\n'); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/bits.cpp b/assembler/ext/src/lexy/docs/assets/examples/bits.cpp deleted file mode 100644 index edbc182ec1..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/bits.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct code_point -{ - static constexpr auto rule = [] { - // 10xxxxxx - auto continuation = dsl::bits(dsl::bit::_1, dsl::bit::_0, dsl::bit::any<6>); - - // 0xxxxxxx - auto ascii = dsl::bits(dsl::bit::_0, dsl::bit::any<7>); - // 110xxxxx - auto lead_two = dsl::bits(dsl::bit::_1, dsl::bit::_1, dsl::bit::_0, dsl::bit::any<5>); - // 1110xxxx - auto lead_three - = dsl::bits(dsl::bit::_1, dsl::bit::_1, dsl::bit::_1, dsl::bit::_0, dsl::bit::any<4>); - // 11110xxx - auto lead_four = dsl::bits(dsl::bit::_1, dsl::bit::_1, dsl::bit::_1, dsl::bit::_1, - dsl::bit::_0, dsl::bit::any<3>); - - return ascii | lead_two >> continuation | lead_three >> dsl::twice(continuation) - | lead_four >> dsl::times<3>(continuation); - }(); -}; -//} - -struct production -{ - static constexpr auto rule = dsl::p + dsl::eof; -}; - -int main() -{ - unsigned char bytes[] = {0xE2, 0x82, 0xAC}; - auto input = lexy::string_input(bytes, sizeof(bytes)); - - auto result = lexy::validate(input, lexy_ext::report_error); - return result ? 0 : 1; -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/bom.cpp b/assembler/ext/src/lexy/docs/assets/examples/bom.cpp deleted file mode 100644 index 12a78c8907..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/bom.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - static constexpr auto rule = [] { - auto bom = dsl::bom; - return dsl::opt(bom) + LEXY_LIT("Hello!") + dsl::eof; - }(); -}; -//} - -int main() -{ - const unsigned char data[] = {0xEF, 0xBB, 0xBF, 'H', 'e', 'l', 'l', 'o', '!', '\0'}; - auto input = lexy::zstring_input(data); - auto result = lexy::validate(input, lexy_ext::report_error); - return result ? 0 : 1; -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/buffer.cpp b/assembler/ext/src/lexy/docs/assets/examples/buffer.cpp deleted file mode 100644 index 4bf3b29964..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/buffer.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -#include -#include -#include - -struct production -{ - static constexpr auto rule = LEXY_LIT("Hi"); -}; - -//{ -int main() -{ - // Create a buffered input. - auto input = [] { - lexy::buffer::builder builder(2); - builder.data()[0] = 'H'; - builder.data()[1] = 'i'; - return std::move(builder).finish(); - }(); - - // Use the input. - if (!lexy::match(input)) - { - std::puts("Error!\n"); - return 1; - } -} -//} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/callback-fold.cpp b/assembler/ext/src/lexy/docs/assets/examples/callback-fold.cpp deleted file mode 100644 index 5a5cdacd46..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/callback-fold.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -#include -#include - -//{ -constexpr auto my_callback = lexy::callback(lexy::fold(0, std::plus{})); -//} - -int main() -{ - std::printf("sum: %d\n", my_callback(1, 2, 3)); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/callback.cpp b/assembler/ext/src/lexy/docs/assets/examples/callback.cpp deleted file mode 100644 index df8b963473..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/callback.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include - -//{ -constexpr auto my_callback - // The return type is int. - = lexy::callback([](int i) { return 2 * i; }, // - [](int a, int b) { return a + b; }); -//} - -int main() -{ - std::printf("one argument: %d\n", my_callback(11)); - std::printf("two arguments: %d\n", my_callback(11, 42)); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/capture.cpp b/assembler/ext/src/lexy/docs/assets/examples/capture.cpp deleted file mode 100644 index 8b84f6128a..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/capture.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -// The type of a lexy::lexeme depends on the input. -using lexeme = lexy_ext::compiler_explorer_lexeme; - -struct production -{ - static constexpr auto rule = dsl::capture(dsl::code_point); - - // Same as `lexy::as_string`. - static constexpr auto value = lexy::callback( - [](lexeme lex) { return std::string(lex.begin(), lex.end()); }); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("Codepoint: %s (%zu code units)\n", result.value().c_str(), result.value().size()); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/capture.input b/assembler/ext/src/lexy/docs/assets/examples/capture.input deleted file mode 100644 index be761e039d..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/capture.input +++ /dev/null @@ -1 +0,0 @@ -ü diff --git a/assembler/ext/src/lexy/docs/assets/examples/code_point_id.cpp b/assembler/ext/src/lexy/docs/assets/examples/code_point_id.cpp deleted file mode 100644 index 1d6bdc8aa7..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/code_point_id.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - static constexpr auto rule = [] { - return LEXY_LIT("\\u") >> dsl::code_point_id<4> // \uXXXX - | LEXY_LIT("\\U") >> dsl::code_point_id<8>; // \uXXXXXXXX - }(); - - // Encode the resulting code point as UTF-8. - static constexpr auto value = lexy::as_string; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("The code point is: %s\n", result.value().c_str()); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/code_point_id.input b/assembler/ext/src/lexy/docs/assets/examples/code_point_id.input deleted file mode 100644 index 146bd5583a..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/code_point_id.input +++ /dev/null @@ -1 +0,0 @@ -\U0001F600 diff --git a/assembler/ext/src/lexy/docs/assets/examples/color.cpp b/assembler/ext/src/lexy/docs/assets/examples/color.cpp deleted file mode 100644 index 5fa454df8a..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/color.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include -#include -#include -#include - -struct Color -{ - std::uint8_t r, g, b; -}; - -namespace grammar -{ -namespace dsl = lexy::dsl; - -struct channel -{ - static constexpr auto rule = dsl::integer(dsl::n_digits<2, dsl::hex>); - static constexpr auto value = lexy::forward; -}; - -struct color -{ - static constexpr auto rule = dsl::hash_sign + dsl::times<3>(dsl::p); - static constexpr auto value = lexy::construct; -}; -} // namespace grammar - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); // special input for CompilerExplorer examples - auto result = lexy::parse(input, lexy_ext::report_error); - if (result.has_value()) - { - auto color = result.value(); - std::printf("#%02x%02x%02x\n", color.r, color.g, color.b); - } - - return result ? 0 : 1; -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/color.input b/assembler/ext/src/lexy/docs/assets/examples/color.input deleted file mode 100644 index 1020614199..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/color.input +++ /dev/null @@ -1 +0,0 @@ -#FF00FF diff --git a/assembler/ext/src/lexy/docs/assets/examples/compose-callback.cpp b/assembler/ext/src/lexy/docs/assets/examples/compose-callback.cpp deleted file mode 100644 index 41fbf9b862..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/compose-callback.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include - -//{ -constexpr auto my_strlen - // Construct a string, then return its size. - = lexy::as_string | lexy::callback(&std::string::size); -//} - -int main() -{ - std::printf("length: %zu\n", my_strlen("Hello")); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/compose-sink.cpp b/assembler/ext/src/lexy/docs/assets/examples/compose-sink.cpp deleted file mode 100644 index c0d611a97e..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/compose-sink.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct entry -{ - std::string name; - std::vector numbers; -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto integer = dsl::integer; - return dsl::square_bracketed.list(integer, dsl::sep(dsl::comma)); - }(); - - static constexpr auto value - // Collect all the numbers in a vector, then turn the result into an entry. - = lexy::as_list> >> lexy::callback([](std::vector&& vec) { - return entry{"foo", std::move(vec)}; - }); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("%s: ", result.value().name.c_str()); - for (auto i : result.value().numbers) - std::printf("%d ", i); - std::putchar('\n'); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/compose-sink.input b/assembler/ext/src/lexy/docs/assets/examples/compose-sink.input deleted file mode 100644 index b5d8bb58d9..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/compose-sink.input +++ /dev/null @@ -1 +0,0 @@ -[1, 2, 3] diff --git a/assembler/ext/src/lexy/docs/assets/examples/concat.cpp b/assembler/ext/src/lexy/docs/assets/examples/concat.cpp deleted file mode 100644 index 5025d5fc48..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/concat.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct list -{ - static constexpr auto rule = [] { - auto integer = dsl::integer; - return dsl::list(integer, dsl::sep(dsl::comma)); - }(); - - static constexpr auto value = lexy::as_list>; -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto rule = dsl::list(dsl::p, dsl::sep(dsl::newline)); - static constexpr auto value = lexy::concat>; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("numbers: "); - for (auto i : result.value()) - std::printf("%d ", i); - std::putchar('\n'); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/concat.input b/assembler/ext/src/lexy/docs/assets/examples/concat.input deleted file mode 100644 index 154eeeeff7..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/concat.input +++ /dev/null @@ -1,3 +0,0 @@ -1, 2, 3 -4, 5, 6 -7, 8, 9 diff --git a/assembler/ext/src/lexy/docs/assets/examples/fold.cpp b/assembler/ext/src/lexy/docs/assets/examples/fold.cpp deleted file mode 100644 index 50c7093499..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/fold.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - // An item is a point (x, y) - auto integer = dsl::integer; - auto item = dsl::parenthesized(dsl::twice(integer, dsl::sep(dsl::comma))); - - return dsl::list(item, dsl::sep(dsl::comma)); - }(); - - // Sum the x components of the points. - static constexpr auto value - = lexy::fold(0, [](int current, int x, int) { return current + x; }); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("The value is: %d\n", result.value()); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/fold.input b/assembler/ext/src/lexy/docs/assets/examples/fold.input deleted file mode 100644 index 5692001e27..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/fold.input +++ /dev/null @@ -1 +0,0 @@ -(1, 1), (11, -5), (8, 0) diff --git a/assembler/ext/src/lexy/docs/assets/examples/fold_inplace.cpp b/assembler/ext/src/lexy/docs/assets/examples/fold_inplace.cpp deleted file mode 100644 index 98b93fea5d..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/fold_inplace.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto integer = dsl::integer; - - return dsl::list(integer, dsl::sep(dsl::comma)); - }(); - - // Construct a `std::deque` in reverse order. - static constexpr auto value - = lexy::fold_inplace>(std::initializer_list{}, - [](auto& deque, int i) { deque.push_front(i); }); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("numbers: "); - for (auto i : result.value()) - std::printf("%d ", i); - std::putchar('\n'); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/fold_inplace.input b/assembler/ext/src/lexy/docs/assets/examples/fold_inplace.input deleted file mode 100644 index 2739d724db..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/fold_inplace.input +++ /dev/null @@ -1 +0,0 @@ -1, 2, 3 diff --git a/assembler/ext/src/lexy/docs/assets/examples/identifier_case_folded.cpp b/assembler/ext/src/lexy/docs/assets/examples/identifier_case_folded.cpp deleted file mode 100644 index 36f985240f..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/identifier_case_folded.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - static constexpr auto rule = dsl::identifier(dsl::ascii::alpha); - - static constexpr auto value - = lexy::as_string.case_folding(dsl::ascii::case_folding); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("Codepoint: %s (%zu code units)\n", result.value().c_str(), result.value().size()); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/identifier_case_folded.input b/assembler/ext/src/lexy/docs/assets/examples/identifier_case_folded.input deleted file mode 100644 index 860858b2e4..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/identifier_case_folded.input +++ /dev/null @@ -1 +0,0 @@ -HeLlO diff --git a/assembler/ext/src/lexy/docs/assets/examples/integer.cpp b/assembler/ext/src/lexy/docs/assets/examples/integer.cpp deleted file mode 100644 index 71d2c8921b..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/integer.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - static constexpr auto rule = [] { - auto digits = dsl::digits<>.sep(dsl::digit_sep_tick).no_leading_zero(); - return dsl::integer(digits); - }(); - - static constexpr auto value = lexy::as_integer; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result.has_value()) - return 1; - - std::printf("The value is: %d\n", result.value()); - return result ? 0 : 1; -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/integer.input b/assembler/ext/src/lexy/docs/assets/examples/integer.input deleted file mode 100644 index 3a80be880f..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/integer.input +++ /dev/null @@ -1 +0,0 @@ -4'294'967'295 diff --git a/assembler/ext/src/lexy/docs/assets/examples/list.cpp b/assembler/ext/src/lexy/docs/assets/examples/list.cpp deleted file mode 100644 index 2364d9af73..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/list.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - static constexpr auto rule = [] { - auto item = dsl::capture(dsl::ascii::alpha); - return dsl::list(item); - }(); - - // Same as `lexy::as_string`. - static constexpr auto value - = lexy::fold_inplace("", [](std::string& result, auto lexeme) { - result.append(lexeme.begin(), lexeme.end()); - }); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result.has_value()) - return 1; - - std::printf("The list is: %s\n", result.value().c_str()); - return result ? 0 : 1; -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/list.input b/assembler/ext/src/lexy/docs/assets/examples/list.input deleted file mode 100644 index 8baef1b4ab..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/list.input +++ /dev/null @@ -1 +0,0 @@ -abc diff --git a/assembler/ext/src/lexy/docs/assets/examples/list_sep.cpp b/assembler/ext/src/lexy/docs/assets/examples/list_sep.cpp deleted file mode 100644 index 6940d6a622..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/list_sep.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - static constexpr auto rule = [] { - auto item = dsl::capture(dsl::ascii::alpha); - auto sep = dsl::sep(dsl::comma); - return dsl::list(item, sep); - }(); - - static constexpr auto value = lexy::as_string; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result.has_value()) - return 1; - - std::printf("The list is: %s\n", result.value().c_str()); - return result ? 0 : 1; -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/list_sep.input b/assembler/ext/src/lexy/docs/assets/examples/list_sep.input deleted file mode 100644 index b8529f5a2b..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/list_sep.input +++ /dev/null @@ -1 +0,0 @@ -a,b,c, diff --git a/assembler/ext/src/lexy/docs/assets/examples/lookahead.cpp b/assembler/ext/src/lexy/docs/assets/examples/lookahead.cpp deleted file mode 100644 index 1c3cde761a..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/lookahead.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct flag -{ - std::optional key; - std::string value; -}; - -struct production -{ - struct flag_key - { - static constexpr auto rule = dsl::identifier(dsl::ascii::alpha); - static constexpr auto value = lexy::as_string; - }; - - struct flag_value - { - static constexpr auto rule = dsl::identifier(dsl::ascii::alnum); - static constexpr auto value = lexy::as_string; - }; - - static constexpr auto whitespace = dsl::ascii::blank; // no newline - - static constexpr auto rule = [] { - // key = value - auto key_value = dsl::p + dsl::lit_c<'='> + dsl::p; - // no key, just value - auto value = dsl::nullopt + dsl::p; - - // We have a key if we're having an equal sign before the newline. - auto key_condition = dsl::lookahead(dsl::lit_c<'='>, dsl::newline); - return (key_condition >> key_value | dsl::else_ >> value) + dsl::eol; - }(); - - static constexpr auto value = lexy::construct; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - auto [key, value] = result.value(); - if (key) - std::printf("The value of '%s' is: %s", key.value().c_str(), value.c_str()); - else - std::printf("The value: %s", value.c_str()); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/lookahead.input b/assembler/ext/src/lexy/docs/assets/examples/lookahead.input deleted file mode 100644 index c8cf145ff6..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/lookahead.input +++ /dev/null @@ -1 +0,0 @@ -// INPUT:foo=42 diff --git a/assembler/ext/src/lexy/docs/assets/examples/make_buffer.cpp b/assembler/ext/src/lexy/docs/assets/examples/make_buffer.cpp deleted file mode 100644 index 622ff2e3e1..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/make_buffer.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include -#include -#include - -struct production -{ - static constexpr auto rule = LEXY_LIT("Hi"); -}; - -struct file_span -{ - const void* memory; - std::size_t size; -}; - -file_span map_file(const char* /* path */) -{ - // fake something - static constexpr unsigned char memory[] = {'H', 0x00, 'i', 0x00}; - return {memory, 4}; -} - -//{ -int main() -{ - // Map a file into memory. - auto span = map_file("input.txt"); - - // Treat the file as little endian UTF-16. - constexpr auto make_utf16_le - = lexy::make_buffer_from_raw; - auto input = make_utf16_le(span.memory, span.size); - - // Use the input. - if (!lexy::match(input)) - { - std::puts("Error!\n"); - return 1; - } -} -//} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/member.cpp b/assembler/ext/src/lexy/docs/assets/examples/member.cpp deleted file mode 100644 index 589480974e..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/member.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct point -{ - int x, y; -}; - -struct production -{ - static constexpr auto rule = [] { - auto value = dsl::integer; - - // Parse an integer into the x/y member of point. - auto x_coord = (dsl::member<& point::x> = value); - auto y_coord = (dsl::member<& point::y> = value); - - return x_coord + dsl::comma + y_coord; - }(); - - // `lexy::as_aggregate` accepts the `lexy::member` + value pairs. - static constexpr auto value = lexy::as_aggregate; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("The value is: (%d, %d)\n", result.value().x, result.value().y); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/member.input b/assembler/ext/src/lexy/docs/assets/examples/member.input deleted file mode 100644 index ed2d77c5c5..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/member.input +++ /dev/null @@ -1 +0,0 @@ -42,11 diff --git a/assembler/ext/src/lexy/docs/assets/examples/new.cpp b/assembler/ext/src/lexy/docs/assets/examples/new.cpp deleted file mode 100644 index c67d5306ee..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/new.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct point -{ - int x, y; -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto integer = dsl::integer; - return dsl::twice(integer, dsl::sep(dsl::comma)); - }(); - static constexpr auto value = lexy::new_>; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("The value is: (%d, %d)\n", result.value()->x, result.value()->y); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/new.input b/assembler/ext/src/lexy/docs/assets/examples/new.input deleted file mode 100644 index 2fe09c6cf0..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/new.input +++ /dev/null @@ -1 +0,0 @@ -11, 42 diff --git a/assembler/ext/src/lexy/docs/assets/examples/noop.cpp b/assembler/ext/src/lexy/docs/assets/examples/noop.cpp deleted file mode 100644 index dcbe463565..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/noop.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -struct production -{ - static constexpr auto rule = dsl::integer; - static constexpr auto value = lexy::forward; -}; - -//{ -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - - // Parse the production, but ignore all errors. - auto result = lexy::parse(input, lexy::noop); - if (!result) - // Note that parsing can still fail. - return 1; - - std::printf("The value is: %d\n", result.value()); -} -//} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/op-basic.cpp b/assembler/ext/src/lexy/docs/assets/examples/op-basic.cpp deleted file mode 100644 index 3d2afd8aa0..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/op-basic.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production : lexy::expression_production -{ - static constexpr auto atom = dsl::integer; - - struct operation : dsl::infix_op_left - { - static constexpr auto op = dsl::op(dsl::lit_c<'+'>); - using operand = dsl::atom; - }; - - static constexpr auto value - = lexy::callback([](int value) { return value; }, - [](int lhs, lexy::op, int rhs) { return lhs + rhs; }); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("Result: %d\n", result.value()); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/op-basic.input b/assembler/ext/src/lexy/docs/assets/examples/op-basic.input deleted file mode 100644 index 19f5084127..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/op-basic.input +++ /dev/null @@ -1 +0,0 @@ -1+2 diff --git a/assembler/ext/src/lexy/docs/assets/examples/op-choice.cpp b/assembler/ext/src/lexy/docs/assets/examples/op-choice.cpp deleted file mode 100644 index e2ad742f91..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/op-choice.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -constexpr auto op_plus = dsl::op(dsl::lit_c<'+'>); -constexpr auto op_minus = dsl::op(dsl::lit_c<'-'>); - -struct production : lexy::expression_production -{ - static constexpr auto atom = dsl::integer; - - struct operation : dsl::infix_op_left - { - static constexpr auto op = op_plus / op_minus; - using operand = dsl::atom; - }; - - static constexpr auto value - = lexy::callback([](int value) { return value; }, - [](int lhs, lexy::op, int rhs) { return lhs + rhs; }, - [](int lhs, lexy::op, int rhs) { return lhs - rhs; }); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("Result: %d\n", result.value()); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/op-choice.input b/assembler/ext/src/lexy/docs/assets/examples/op-choice.input deleted file mode 100644 index c893212a1c..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/op-choice.input +++ /dev/null @@ -1 +0,0 @@ -1-2 diff --git a/assembler/ext/src/lexy/docs/assets/examples/op-custom.cpp b/assembler/ext/src/lexy/docs/assets/examples/op-custom.cpp deleted file mode 100644 index cd169f4e08..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/op-custom.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct plus -{ - const LEXY_CHAR8_T* pos; - - constexpr plus(const LEXY_CHAR8_T* pos) : pos(pos) {} -}; - -struct production : lexy::expression_production -{ - static constexpr auto atom = dsl::integer; - - struct operation : dsl::infix_op_left - { - static constexpr auto op = dsl::op(dsl::lit_c<'+'>); - using operand = dsl::atom; - }; - - static constexpr auto value = lexy::callback([](int value) { return value; }, - [](int lhs, plus op, int rhs) { - LEXY_PRECONDITION(*op.pos == '+'); - return lhs + rhs; - }); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("Result: %d\n", result.value()); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/op-custom.input b/assembler/ext/src/lexy/docs/assets/examples/op-custom.input deleted file mode 100644 index 19f5084127..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/op-custom.input +++ /dev/null @@ -1 +0,0 @@ -1+2 diff --git a/assembler/ext/src/lexy/docs/assets/examples/opt.cpp b/assembler/ext/src/lexy/docs/assets/examples/opt.cpp deleted file mode 100644 index e8fb7ede9a..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/opt.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct decimal -{ - int integer; - std::optional fraction; -}; - -struct production -{ - struct fraction - { - static constexpr auto rule = dsl::capture(dsl::digits<>); - static constexpr auto value = lexy::as_string; - }; - - static constexpr auto rule = [] { - auto integer = dsl::integer; - - return integer + dsl::opt(dsl::period >> dsl::p); - }(); - - static constexpr auto value = lexy::construct; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("The value is: %d.%s\n", result.value().integer, - result.value().fraction.value_or("0").c_str()); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/opt.input b/assembler/ext/src/lexy/docs/assets/examples/opt.input deleted file mode 100644 index 6324d401a0..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/opt.input +++ /dev/null @@ -1 +0,0 @@ -3.14 diff --git a/assembler/ext/src/lexy/docs/assets/examples/point.cpp b/assembler/ext/src/lexy/docs/assets/examples/point.cpp deleted file mode 100644 index 9aab8cbfad..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/point.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct point -{ - int x, y; -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto integer = dsl::integer; - return dsl::twice(integer, dsl::sep(dsl::comma)); - }(); - static constexpr auto value = lexy::construct; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("The value is: (%d, %d)\n", result.value().x, result.value().y); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/point.input b/assembler/ext/src/lexy/docs/assets/examples/point.input deleted file mode 100644 index 2fe09c6cf0..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/point.input +++ /dev/null @@ -1 +0,0 @@ -11, 42 diff --git a/assembler/ext/src/lexy/docs/assets/examples/quoted_escape.cpp b/assembler/ext/src/lexy/docs/assets/examples/quoted_escape.cpp deleted file mode 100644 index 46489986ef..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/quoted_escape.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - // A mapping of the simple escape sequences to their replacement values. - static constexpr auto escaped_symbols = lexy::symbol_table // - .map<'"'>('"') - .map<'\\'>('\\') - .map<'/'>('/') - .map<'b'>('\b') - .map<'f'>('\f') - .map<'n'>('\n') - .map<'r'>('\r') - .map<'t'>('\t'); - - static constexpr auto rule = [] { - // Arbitrary code points that aren't control characters. - auto c = -dsl::ascii::control; - - // Escape sequences start with a backlash. - // They either map one of the symbols, - // or a Unicode code point of the form uXXXX. - auto escape = dsl::backslash_escape // - .symbol() - .rule(dsl::lit_c<'u'> >> dsl::code_point_id<4>); - return dsl::quoted(c, escape); - }(); - - // Need to specify a target encoding to handle the code point. - static constexpr auto value = lexy::as_string; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("The string is: %s\n", result.value().c_str()); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/quoted_escape.input b/assembler/ext/src/lexy/docs/assets/examples/quoted_escape.input deleted file mode 100644 index 84d66a0939..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/quoted_escape.input +++ /dev/null @@ -1 +0,0 @@ -"Hello\nWorld\u0021" diff --git a/assembler/ext/src/lexy/docs/assets/examples/range_input.cpp b/assembler/ext/src/lexy/docs/assets/examples/range_input.cpp deleted file mode 100644 index 6e975fdef4..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/range_input.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - -#include -#include -#include - -struct production -{ - static constexpr auto rule = LEXY_LIT("Hi"); -}; - -//{ -int main() -{ - std::list list{u'H', u'i'}; - - // Create the input, deducing the encoding. - auto input = lexy::range_input(list.begin(), list.end()); - - // Use the input. - if (!lexy::match(input)) - { - std::puts("Error!\n"); - return 1; - } -} -//} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/scan.cpp b/assembler/ext/src/lexy/docs/assets/examples/scan.cpp deleted file mode 100644 index 9f02863590..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/scan.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct control_production -{ - // Allow ASCII whitespace. - static constexpr auto whitespace = dsl::ascii::space; -}; - -int main() -{ - // Construct a scanner for the input. - auto input = lexy_ext::compiler_explorer_input(); - auto scanner = lexy::scan(input, lexy_ext::report_error); - - // Parse two integers separated by comma. - auto x = scanner.integer(dsl::digits<>); - scanner.parse(dsl::comma); - auto y = scanner.integer(dsl::digits<>); - - std::printf("%d, %d", x.value_or(-1), y.value_or(-1)); -} -//} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/scan.input b/assembler/ext/src/lexy/docs/assets/examples/scan.input deleted file mode 100644 index 2fe09c6cf0..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/scan.input +++ /dev/null @@ -1 +0,0 @@ -11, 42 diff --git a/assembler/ext/src/lexy/docs/assets/examples/sign.cpp b/assembler/ext/src/lexy/docs/assets/examples/sign.cpp deleted file mode 100644 index bcbc801e32..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/sign.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - // Sign followed by a decimal integer. - static constexpr auto rule = dsl::sign + dsl::integer; - static constexpr auto value = lexy::as_integer; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result.has_value()) - return 1; - - std::printf("The value is: %d\n", result.value()); - return result ? 0 : 1; -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/sign.input b/assembler/ext/src/lexy/docs/assets/examples/sign.input deleted file mode 100644 index 3a437cdbc6..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/sign.input +++ /dev/null @@ -1 +0,0 @@ --123 diff --git a/assembler/ext/src/lexy/docs/assets/examples/string_input.cpp b/assembler/ext/src/lexy/docs/assets/examples/string_input.cpp deleted file mode 100644 index 5000e1495a..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/string_input.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include - -#include -#include -#include - -struct production -{ - static constexpr auto rule = LEXY_LIT("Hi"); -}; - -//{ -int main() -{ - unsigned char array[] = {'H', 'i'}; - - // Create the input, deducing the encoding. - auto input = lexy::string_input(array, array + 2); - - // Use the input. - if (!lexy::match(input)) - { - std::puts("Error!\n"); - return 1; - } -} -//} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/symbol.cpp b/assembler/ext/src/lexy/docs/assets/examples/symbol.cpp deleted file mode 100644 index dd06330dc2..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/symbol.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - // Map names of the entities to their replacement value. - static constexpr auto entities = lexy::symbol_table - .map('"') - .map('&') - .map('\'') - .map('<') - .map('>'); - - static constexpr auto rule = [] { - auto name = dsl::identifier(dsl::ascii::alpha); - auto reference = dsl::symbol(name); - return dsl::lit_c<'&'> >> reference + dsl::lit_c<';'>; - }(); - - static constexpr auto value = lexy::forward; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("The replacement is: '%c'\n", result.value()); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/symbol.input b/assembler/ext/src/lexy/docs/assets/examples/symbol.input deleted file mode 100644 index dd3d9a7f04..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/symbol.input +++ /dev/null @@ -1 +0,0 @@ -< diff --git a/assembler/ext/src/lexy/docs/assets/examples/times_isep.cpp b/assembler/ext/src/lexy/docs/assets/examples/times_isep.cpp deleted file mode 100644 index 5d682a6e95..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/times_isep.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct three_ints -{ - static constexpr auto rule = [] { - auto item = dsl::integer; - auto sep = dsl::ignore_trailing_sep(dsl::comma); - return dsl::times<3>(item, sep) + dsl::eof; - }(); - - static constexpr auto value - = lexy::callback([](int a, int b, int c) { return a + b + c; }); -}; - -struct production -{ - static constexpr auto rule = dsl::p + dsl::comma + dsl::p; - static constexpr auto value = lexy::callback([](int a, int b) { return a + b; }); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("The sum is: %d\n", result.value()); -} diff --git a/assembler/ext/src/lexy/docs/assets/examples/times_isep.input b/assembler/ext/src/lexy/docs/assets/examples/times_isep.input deleted file mode 100644 index 7222c1f589..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/times_isep.input +++ /dev/null @@ -1 +0,0 @@ -1,2,3,4,5,6 diff --git a/assembler/ext/src/lexy/docs/assets/examples/times_tsep.cpp b/assembler/ext/src/lexy/docs/assets/examples/times_tsep.cpp deleted file mode 100644 index 5af54670b2..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/times_tsep.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct production -{ - static constexpr auto rule = [] { - auto item = dsl::integer; - auto sep = dsl::trailing_sep(dsl::comma); - return dsl::times<3>(item, sep); - }(); - - static constexpr auto value - = lexy::callback([](int a, int b, int c) { return a + b + c; }); -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("The sum is: %d\n", result.value()); -} diff --git a/assembler/ext/src/lexy/docs/assets/examples/times_tsep.input b/assembler/ext/src/lexy/docs/assets/examples/times_tsep.input deleted file mode 100644 index 1f1d063a21..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/times_tsep.input +++ /dev/null @@ -1 +0,0 @@ -1,2,3, diff --git a/assembler/ext/src/lexy/docs/assets/examples/token_kind_map.cpp b/assembler/ext/src/lexy/docs/assets/examples/token_kind_map.cpp deleted file mode 100644 index 60c12c3007..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/token_kind_map.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -struct name -{ - static constexpr auto rule - // One or more alpha numeric characters, underscores or hyphens. - = dsl::identifier(dsl::ascii::alnum / dsl::lit_c<'_'> / dsl::lit_c<'-'>); -}; - -struct production -{ - // Allow arbitrary spaces between individual tokens. - // Note that this includes the individual characters of the name. - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto greeting = LEXY_LIT("Hello"); - return greeting + dsl::p + dsl::exclamation_mark + dsl::eof; - }(); -}; - -//{ -enum class my_token_kind -{ - greeting, - exclamation_mark, -}; - -template <> -constexpr auto lexy::token_kind_map_for - // Start with the empty map. - = lexy::token_kind_map - // Map the greeting token. - .map(LEXY_LIT("Hello")) - // Map the exclamation token. - .map(dsl::exclamation_mark); -//} - -const char* token_kind_name(my_token_kind kind) -{ - switch (kind) - { - case my_token_kind::greeting: - return "greeting"; - case my_token_kind::exclamation_mark: - return "exclamation_mark"; - } - - return ""; -} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - - // Need to specify the token kind we want here. - lexy::parse_tree_for tree; - auto result = lexy::parse_as_tree(tree, input, lexy_ext::report_error); - - lexy::visualize(stdout, tree, {lexy::visualize_fancy}); - - if (!result) - return 1; -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/token_kind_map.input b/assembler/ext/src/lexy/docs/assets/examples/token_kind_map.input deleted file mode 100644 index 980a0d5f19..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/token_kind_map.input +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/assembler/ext/src/lexy/docs/assets/examples/true_false.cpp b/assembler/ext/src/lexy/docs/assets/examples/true_false.cpp deleted file mode 100644 index 5cbebfced0..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/true_false.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct boolean -{ - struct true_ - { - static constexpr auto rule = LEXY_LIT("true"); - // Produce the value `true`. - static constexpr auto value = lexy::constant(true); - }; - struct false_ - { - static constexpr auto rule = LEXY_LIT("false"); - // Produce the value `false`. - static constexpr auto value = lexy::constant(false); - }; - - static constexpr auto rule = dsl::p | dsl::p; - // Both rules produce a boolean value, just forward that one. - static constexpr auto value = lexy::forward; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result) - return 1; - - std::printf("The value is: %d\n", static_cast(result.value())); -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/true_false.input b/assembler/ext/src/lexy/docs/assets/examples/true_false.input deleted file mode 100644 index 27ba77ddaf..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/true_false.input +++ /dev/null @@ -1 +0,0 @@ -true diff --git a/assembler/ext/src/lexy/docs/assets/examples/try.cpp b/assembler/ext/src/lexy/docs/assets/examples/try.cpp deleted file mode 100644 index 8cf32268bc..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/try.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -//{ -struct version -{ - std::optional major, minor, patch; -}; - -struct production -{ - static constexpr auto rule = [] { - // If we don't have an integer, recover by producing nullopt. - auto number = dsl::try_(dsl::integer, dsl::nullopt); - auto dot = dsl::try_(dsl::period); - return number + dot + number + dot + number; - }(); - - static constexpr auto value = lexy::construct; -}; -//} - -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result.has_value()) - return 1; - - auto [major, minor, patch] = result.value(); - std::printf("The value is: %d.%d.%d\n", major.value_or(0), minor.value_or(0), - patch.value_or(0)); - return result ? 0 : 1; -} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/try.input b/assembler/ext/src/lexy/docs/assets/examples/try.input deleted file mode 100644 index d3827e75a5..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/try.input +++ /dev/null @@ -1 +0,0 @@ -1.0 diff --git a/assembler/ext/src/lexy/docs/assets/examples/visualize.cpp b/assembler/ext/src/lexy/docs/assets/examples/visualize.cpp deleted file mode 100644 index 85d915becb..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/visualize.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include -#include -#include - -namespace dsl = lexy::dsl; - -struct name -{ - static constexpr auto rule - // One or more alpha numeric characters, underscores or hyphens. - = dsl::identifier(dsl::ascii::alnum / dsl::lit_c<'_'> / dsl::lit_c<'-'>); -}; - -struct production -{ - // Allow arbitrary spaces between individual tokens. - // Note that this includes the individual characters of the name. - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto greeting = LEXY_LIT("Hello"); - return greeting + dsl::p + dsl::exclamation_mark + dsl::eof; - }(); -}; - -//{ -int main() -{ - auto input = lexy_ext::compiler_explorer_input(); - - lexy::parse_tree_for tree; - auto result = lexy::parse_as_tree(tree, input, lexy_ext::report_error); - - lexy::visualize(stdout, tree, {lexy::visualize_fancy}); - - if (!result) - return 1; -} -//} - diff --git a/assembler/ext/src/lexy/docs/assets/examples/visualize.input b/assembler/ext/src/lexy/docs/assets/examples/visualize.input deleted file mode 100644 index 980a0d5f19..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/visualize.input +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/assembler/ext/src/lexy/docs/assets/examples/zstring_input.cpp b/assembler/ext/src/lexy/docs/assets/examples/zstring_input.cpp deleted file mode 100644 index db01d3ec6a..0000000000 --- a/assembler/ext/src/lexy/docs/assets/examples/zstring_input.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include - -#include -#include -#include - -struct production -{ - static constexpr auto rule = LEXY_LIT("Hi"); -}; - -//{ -int main() -{ - // Create the input, deducing the encoding. - auto input = lexy::zstring_input("Hi"); - - // Use the input. - if (!lexy::match(input)) - { - std::puts("Error!\n"); - return 1; - } -} -//} - diff --git a/assembler/ext/src/lexy/docs/assets/icons/arrow-right.svg b/assembler/ext/src/lexy/docs/assets/icons/arrow-right.svg deleted file mode 100644 index 604b62c918..0000000000 --- a/assembler/ext/src/lexy/docs/assets/icons/arrow-right.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assembler/ext/src/lexy/docs/assets/icons/beta.svg b/assembler/ext/src/lexy/docs/assets/icons/beta.svg deleted file mode 100644 index 187b573816..0000000000 --- a/assembler/ext/src/lexy/docs/assets/icons/beta.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assembler/ext/src/lexy/docs/assets/icons/bug.svg b/assembler/ext/src/lexy/docs/assets/icons/bug.svg deleted file mode 100644 index c7af7072b6..0000000000 --- a/assembler/ext/src/lexy/docs/assets/icons/bug.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assembler/ext/src/lexy/docs/assets/icons/calender.svg b/assembler/ext/src/lexy/docs/assets/icons/calender.svg deleted file mode 100644 index 1cf76ae998..0000000000 --- a/assembler/ext/src/lexy/docs/assets/icons/calender.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assembler/ext/src/lexy/docs/assets/icons/download.svg b/assembler/ext/src/lexy/docs/assets/icons/download.svg deleted file mode 100644 index 09cdf88c71..0000000000 --- a/assembler/ext/src/lexy/docs/assets/icons/download.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assembler/ext/src/lexy/docs/assets/icons/edit.svg b/assembler/ext/src/lexy/docs/assets/icons/edit.svg deleted file mode 100644 index e757323be3..0000000000 --- a/assembler/ext/src/lexy/docs/assets/icons/edit.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assembler/ext/src/lexy/docs/assets/icons/github.svg b/assembler/ext/src/lexy/docs/assets/icons/github.svg deleted file mode 100644 index 7870c06dc2..0000000000 --- a/assembler/ext/src/lexy/docs/assets/icons/github.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assembler/ext/src/lexy/docs/assets/icons/license.svg b/assembler/ext/src/lexy/docs/assets/icons/license.svg deleted file mode 100644 index 9691616754..0000000000 --- a/assembler/ext/src/lexy/docs/assets/icons/license.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assembler/ext/src/lexy/docs/assets/icons/play.svg b/assembler/ext/src/lexy/docs/assets/icons/play.svg deleted file mode 100644 index bcd81f7a6d..0000000000 --- a/assembler/ext/src/lexy/docs/assets/icons/play.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assembler/ext/src/lexy/docs/assets/js/playground.js b/assembler/ext/src/lexy/docs/assets/js/playground.js deleted file mode 100644 index f620f95e56..0000000000 --- a/assembler/ext/src/lexy/docs/assets/js/playground.js +++ /dev/null @@ -1,180 +0,0 @@ -const api = "https://godbolt.org/api/"; -const compiler_id = "clang_trunk"; -const lexy_id = { id: 'lexy', version: 'trunk' }; - -async function fetch_local_file(url) -{ - const response = await fetch(url); - if (!response.ok) - return ""; - return await response.text(); -} - -function json_stringify(object) -{ - // I can't use JSON.stringify directly, as the resulting JSON is base64 encoded. - // This can't deal with Unicode code points, so I need to escape them in the JSON representation first. - // Code taken (and fixed) from: https://stackoverflow.com/a/31652607. - var json = JSON.stringify(object); - json = json.replace(/[\u0080-\uFFFF]/g, function(c) { - return "\\u" + ("0000" + c.charCodeAt(0).toString(16)).substr(-4) - }); - return json; -} - -export function list_of_productions(source) -{ - var result = []; - - const regex = /(struct|class) ([a-zA-Z0-9_]+)/g; - var match = undefined; - while (match = regex.exec(source)) - result.push(match[2]); - - return result; -} - -export async function preprocess_source(target, source, production) -{ - /* - {{ $playground_headers := resources.Get "cpp/playground_headers.single.hpp" }} - {{ $playground_prefix := resources.Get "cpp/playground_prefix.cpp" }} - {{ $playground_main := resources.Get "cpp/playground_main.cpp" }} - {{ $godbolt_prefix := resources.Get "cpp/godbolt_prefix.cpp" }} - {{ $godbolt_main := resources.Get "cpp/godbolt_main.cpp" }} - */ - - if (target == 'playground') - { - const header = await fetch_local_file('{{ $playground_headers.RelPermalink }}'); - const macros = `#define LEXY_PLAYGROUND_PRODUCTION ${production}`; - const prefix = await fetch_local_file('{{ $playground_prefix.RelPermalink }}'); - const main = await fetch_local_file('{{ $playground_main.RelPermalink }}'); - - return header + '\n' + macros + '\n' + prefix + '\n' + source + '\n' + main; - } - else - { - const macros = `#define LEXY_PLAYGROUND_PRODUCTION ${production}`; - const prefix = await fetch_local_file('{{ $godbolt_prefix.RelPermalink }}'); - const main = await fetch_local_file('{{ $godbolt_main.RelPermalink }}'); - - return macros + '\n' + prefix + source + '\n' + main; - } -} - -export async function compile_and_run(source, input, mode) -{ - var body = {}; - body.source = source; - - body.options = {}; - body.options.userArguments = "-fno-color-diagnostics -std=c++20"; - body.options.executeParameters = { args: [mode], stdin: input }; - body.options.compilerOptions = { executorRequest: true }; - body.options.filters = { execute: true }; - body.options.tools = []; - body.options.libraries = [ lexy_id ]; - - body.lang = "c++"; - - const response = await fetch(`${api}/compiler/${compiler_id}/compile`, { - method: "POST", - headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, - body: json_stringify(body) - }); - if (!response.ok) - return { success: false, message: `Compiler Explorer error: ${response.status} - ${response.statusText}` }; - - const result = await response.json(); - - if (result.didExecute) - { - if (result.code == 3) - { - var message = result.stderr.map(x => x.text).join("\n"); - return { success: false, message: message }; - } - else - { - var stdout = result.stdout.map(x => x.text).join("\n"); - var stderr = result.stderr.map(x => x.text).join("\n"); - return { success: true, stdout: stdout, stderr: stderr, code: result.code }; - } - } - else - { - var message = result.buildResult.stderr.map(x => x.text).join("\n"); - return { success: false, message: message }; - } -} - -function get_godbolt_clientstate(source, input) -{ - var session = {}; - session.id = 1; - session.language = "c++"; - session.source = source; - session.compilers = []; - - var compiler = {}; - compiler.id = compiler_id; - compiler.libs = [ lexy_id ]; - compiler.options = "-std=c++20"; - session.executors = [{ compiler: compiler, stdin: input, stdinVisible: true }]; - - return { sessions: [session] }; -} - -export async function get_godbolt_permalink(source, input) -{ - const state = get_godbolt_clientstate(source, input); - const response = await fetch(api + "shortener", { - method: "POST", - headers: { "Content-Type": "application/json", "Accept": "application/json" }, - body: json_stringify(state) - }); - if (!response.ok) - return get_godbolt_url(source, input); - return (await response.json()).url; -} - -export function get_godbolt_url(source, input) -{ - const state = get_godbolt_clientstate(source, input); - const state_str = json_stringify(state); - return "https://godbolt.org/clientstate/" + encodeURIComponent(btoa(state_str)); -} - -export async function load_example(url) -{ - const source_regex = /\/\/ INPUT:(.*)\n/; - const source = await fetch_local_file(url); - - const grammar = source.replace(source_regex, ''); - const input = (source_regex.exec(source)?.[1] ?? "").replaceAll("\\n", "\n"); - - return { grammar: grammar.trim(), input: input, production: "production" }; -} - -export async function load_godbolt_url(id) -{ - const response = await fetch(api + "shortlinkinfo/" + id); - if (!response.ok) - return { grammar: "", input: "", production: "" }; - const result = await response.json(); - - const session = result.sessions[0]; - const source = session.source; - const input = session.executors[0].stdin; - - const production_regex = /#define LEXY_PLAYGROUND_PRODUCTION ([a-zA-Z_0-9]+)/; - const production = production_regex.exec(source)[1]; - - const grammar_regex = /\/\/=== grammar ===\/\/([^]*)\/\/=== main function ===\/\//; - let grammar = grammar_regex.exec(source)[1]; - grammar = grammar.trim(); - - return { grammar: grammar, input: input, production: production }; -} - diff --git a/assembler/ext/src/lexy/docs/assets/jsconfig.json b/assembler/ext/src/lexy/docs/assets/jsconfig.json deleted file mode 100644 index 377218ccba..0000000000 --- a/assembler/ext/src/lexy/docs/assets/jsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "paths": { - "*": [ - "*" - ] - } - } -} \ No newline at end of file diff --git a/assembler/ext/src/lexy/docs/assets/playground/any.cpp b/assembler/ext/src/lexy/docs/assets/playground/any.cpp deleted file mode 100644 index 1a3bb096c9..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/any.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// INPUT:Literally anything you want. -struct production -{ - static constexpr auto rule = dsl::any; -}; - diff --git a/assembler/ext/src/lexy/docs/assets/playground/case_folding.cpp b/assembler/ext/src/lexy/docs/assets/playground/case_folding.cpp deleted file mode 100644 index e9a0742ba5..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/case_folding.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:HeLlO wOrLd! -struct production -{ - static constexpr auto rule = dsl::ascii::case_folding(LEXY_LIT("hello world!")); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/char_class_intersection.cpp b/assembler/ext/src/lexy/docs/assets/playground/char_class_intersection.cpp deleted file mode 100644 index e098b4470f..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/char_class_intersection.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// INPUT:" " -struct production -{ - static constexpr auto rule // - = dsl::quoted(dsl::ascii::space & dsl::ascii::print); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/char_class_macro.cpp b/assembler/ext/src/lexy/docs/assets/playground/char_class_macro.cpp deleted file mode 100644 index ee79f56a46..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/char_class_macro.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// INPUT:atom -struct production -{ - static constexpr auto atext - = LEXY_CHAR_CLASS("atext", - dsl::ascii::alpha / dsl::ascii::digit / LEXY_LIT("!") / LEXY_LIT("#") - / LEXY_LIT("$") / LEXY_LIT("%") / LEXY_LIT("&") / LEXY_LIT("'") - / LEXY_LIT("*") / LEXY_LIT("+") / LEXY_LIT("-") / LEXY_LIT("/") - / LEXY_LIT("=") / LEXY_LIT("?") / LEXY_LIT("^") / LEXY_LIT("_") - / LEXY_LIT("`") / LEXY_LIT("{") / LEXY_LIT("|") / LEXY_LIT("}")); - - static constexpr auto rule = dsl::identifier(atext); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/char_class_minus.cpp b/assembler/ext/src/lexy/docs/assets/playground/char_class_minus.cpp deleted file mode 100644 index 7f0b502c2e..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/char_class_minus.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// INPUT:ABX -struct production -{ - static constexpr auto rule // - = dsl::identifier(dsl::ascii::upper - dsl::lit_c<'X'>); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/char_class_union.cpp b/assembler/ext/src/lexy/docs/assets/playground/char_class_union.cpp deleted file mode 100644 index ee8e079de7..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/char_class_union.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// INPUT:H123 -struct production -{ - static constexpr auto rule // - = dsl::identifier(dsl::ascii::upper / dsl::ascii::digit); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/choice.cpp b/assembler/ext/src/lexy/docs/assets/playground/choice.cpp deleted file mode 100644 index 775aca3902..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/choice.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:Hello -struct production -{ - static constexpr auto rule = LEXY_LIT("Hello") | LEXY_LIT("Hi"); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/choice_bad.cpp b/assembler/ext/src/lexy/docs/assets/playground/choice_bad.cpp deleted file mode 100644 index 4cd86d845b..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/choice_bad.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:ab -struct production -{ - static constexpr auto rule = LEXY_LIT("a") | LEXY_LIT("ab"); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/choice_branch.cpp b/assembler/ext/src/lexy/docs/assets/playground/choice_branch.cpp deleted file mode 100644 index 51d71fd6a5..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/choice_branch.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// INPUT:ab -struct production -{ - static constexpr auto rule = LEXY_LIT("a") >> LEXY_LIT("bc") // a, then bc - | LEXY_LIT("a") >> LEXY_LIT("b") // a, then b - | LEXY_LIT("bc") | LEXY_LIT("b"); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/choice_else.cpp b/assembler/ext/src/lexy/docs/assets/playground/choice_else.cpp deleted file mode 100644 index ca2d547c65..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/choice_else.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// INPUT:Hallo -struct production -{ - static constexpr auto rule - // Input should be empty if greeting isn't known. - = LEXY_LIT("Hello") | LEXY_LIT("Hi") | dsl::else_ >> dsl::eof; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/choice_error.cpp b/assembler/ext/src/lexy/docs/assets/playground/choice_error.cpp deleted file mode 100644 index cb2b56fbc6..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/choice_error.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// INPUT:Hallo -struct production -{ - struct unknown_greeting - { - static constexpr auto name = "unknown greeting"; - }; - - static constexpr auto rule - // Generate a custom error for an unknown greeting. - = LEXY_LIT("Hello") | LEXY_LIT("Hi") | dsl::error; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/choice_error_range.cpp b/assembler/ext/src/lexy/docs/assets/playground/choice_error_range.cpp deleted file mode 100644 index 68218fd6f9..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/choice_error_range.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// INPUT:Hallo -struct production -{ - struct unknown_greeting - { - static constexpr auto name = "unknown greeting"; - }; - - static constexpr auto rule - // Generate a custom error for an unknown greeting. - = LEXY_LIT("Hello") | LEXY_LIT("Hi") - | dsl::error(dsl::while_(dsl::ascii::alpha)); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/choice_production.cpp b/assembler/ext/src/lexy/docs/assets/playground/choice_production.cpp deleted file mode 100644 index 759793148f..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/choice_production.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// INPUT:type Id = Integer; -constexpr auto id = dsl::identifier(dsl::ascii::alpha); -constexpr auto kw_function = LEXY_KEYWORD("function", id); -constexpr auto kw_type = LEXY_KEYWORD("type", id); - -struct function_decl -{ - static constexpr auto rule = [] { - auto arguments = dsl::parenthesized(LEXY_LIT("...")); - auto body = dsl::curly_bracketed(LEXY_LIT("...")); - - return kw_function >> id + arguments + body; - }(); -}; - -struct type_decl -{ - static constexpr auto rule // - = kw_type >> id + dsl::lit_c<'='> + id + dsl::semicolon; -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto rule = dsl::p | dsl::p; -}; - diff --git a/assembler/ext/src/lexy/docs/assets/playground/code_point.cpp b/assembler/ext/src/lexy/docs/assets/playground/code_point.cpp deleted file mode 100644 index 329937e821..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/code_point.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:a -struct production -{ - static constexpr auto rule = dsl::code_point + dsl::eof; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/code_point_if.cpp b/assembler/ext/src/lexy/docs/assets/playground/code_point_if.cpp deleted file mode 100644 index 029c0c7e07..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/code_point_if.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// INPUT:a -struct production -{ - struct even - { - constexpr bool operator()(lexy::code_point cp) - { - return cp.value() % 2 == 0; - } - }; - - static constexpr auto rule = dsl::code_point.if_() + dsl::eof; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/color.cpp b/assembler/ext/src/lexy/docs/assets/playground/color.cpp deleted file mode 100644 index a71dfa6866..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/color.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// INPUT:#FF00FF -struct channel -{ - static constexpr auto rule = dsl::n_digits<2, dsl::hex>; -}; - -struct color -{ - static constexpr auto rule = dsl::hash_sign + dsl::times<3>(dsl::p) + dsl::eof; -}; - -using production = color; diff --git a/assembler/ext/src/lexy/docs/assets/playground/color_function.cpp b/assembler/ext/src/lexy/docs/assets/playground/color_function.cpp deleted file mode 100644 index bfb9b3426f..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/color_function.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// INPUT:rgb(255,0,255) -struct channel_hex -{ - static constexpr auto rule = dsl::integer(dsl::n_digits<2, dsl::hex>); -}; - -struct channel_dec -{ - static constexpr auto rule = dsl::integer; -}; - -struct color -{ - static constexpr auto rule = [] { - auto hex_color = dsl::hash_sign >> dsl::times<3>(dsl::p); - - auto dec_channels = dsl::times<3>(dsl::p, dsl::sep(dsl::comma)); - auto fnc_color = LEXY_LIT("rgb") >> dsl::parenthesized(dec_channels); - - return hex_color | fnc_color; - }(); -}; - -using production = color; diff --git a/assembler/ext/src/lexy/docs/assets/playground/combination.cpp b/assembler/ext/src/lexy/docs/assets/playground/combination.cpp deleted file mode 100644 index 390ab08a9b..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/combination.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// INPUT:cab -struct production -{ - static constexpr auto rule - = dsl::combination(dsl::lit_c<'a'>, dsl::lit_c<'b'>, dsl::lit_c<'c'>); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/context_counter.cpp b/assembler/ext/src/lexy/docs/assets/playground/context_counter.cpp deleted file mode 100644 index 7a5284664f..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/context_counter.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// INPUT:aaabb -struct production -{ - struct mismatch - {}; - - static constexpr auto rule = [] { - // Declare a counter - it is not created yet! - auto counter = dsl::context_counter; - - // Parse a sequence of 'a' and add the number to it. - auto a = counter.push(dsl::while_(dsl::lit_c<'a'>)); - // Parse a sequence of 'b' and subtract the number from it. - auto b = counter.pop(dsl::while_(dsl::lit_c<'b'>)); - - // Create the counter initialized to zero, - // parse the two, and require its back to zero. - return counter.create() + a + b + dsl::must(counter.is_zero()).error; - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/context_flag.cpp b/assembler/ext/src/lexy/docs/assets/playground/context_flag.cpp deleted file mode 100644 index 7d5cc5462c..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/context_flag.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// INPUT:cccbab -struct production -{ - struct expected_a_before_b - { - static constexpr auto name = "expected a before b"; - }; - - static constexpr auto rule = [] { - // Declare a flag - it is not created yet! - auto flag = dsl::context_flag; - - // Parsing a sets the flag to true. - auto a = dsl::lit_c<'a'> >> flag.set(); - // Parsing b requires that the flag has been set already. - auto b = dsl::lit_c<'b'> >> dsl::must(flag.is_reset()).error; - // Parsing c doesn't care about the flag. - auto c = dsl::lit_c<'c'>; - - // Create the flag initialized to false. - // Then parse a|b|c in a loop. - return flag.create() + dsl::loop(a | b | c | dsl::break_); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/context_identifier.cpp b/assembler/ext/src/lexy/docs/assets/playground/context_identifier.cpp deleted file mode 100644 index 8c2198a7bd..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/context_identifier.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// INPUT:Hello,Hallo -struct production -{ - static constexpr auto rule = [] { - // Declare an identifier variable - it is not created yet! - auto word = dsl::identifier(dsl::ascii::alpha); - auto word_var = dsl::context_identifier(word); - - // Parse a word and capture it in the variable. - auto first_word = word_var.capture(); - // Parse another word and compare it agains the variable. - auto second_word = word_var.rematch(); - - // Create the empty variable, then parse the two words. - return word_var.create() + first_word + dsl::lit_c<','> + second_word; - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/cpp_comment.cpp b/assembler/ext/src/lexy/docs/assets/playground/cpp_comment.cpp deleted file mode 100644 index e42fa0080a..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/cpp_comment.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:// This is a comment. -struct production -{ - static constexpr auto rule = LEXY_LIT("//") + dsl::until(dsl::newline).or_eof(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/default.cpp b/assembler/ext/src/lexy/docs/assets/playground/default.cpp deleted file mode 100644 index 58c210ff75..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/default.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// INPUT:Hello World! -struct name -{ - static constexpr auto rule - // One or more alpha numeric characters, underscores or hyphens. - = dsl::identifier(dsl::unicode::alnum / dsl::lit_c<'_'> / dsl::lit_c<'-'>); -}; - -struct production -{ - // Allow arbitrary spaces between individual tokens. - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto greeting = LEXY_LIT("Hello"); - return greeting + dsl::p + dsl::exclamation_mark + dsl::eof; - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/digit.cpp b/assembler/ext/src/lexy/docs/assets/playground/digit.cpp deleted file mode 100644 index 686e0ab91e..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/digit.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:A -struct production -{ - static constexpr auto rule = dsl::digit + dsl::eof; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/digits.cpp b/assembler/ext/src/lexy/docs/assets/playground/digits.cpp deleted file mode 100644 index 8e055bd540..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/digits.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// INPUT:4'294'967'295 -struct production -{ - static constexpr auto rule - = dsl::digits<>.sep(dsl::digit_sep_tick).no_leading_zero() + dsl::eof; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/do_while.cpp b/assembler/ext/src/lexy/docs/assets/playground/do_while.cpp deleted file mode 100644 index ad4c8ba122..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/do_while.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// INPUT:Hello World -struct production -{ - static constexpr auto rule = [] { - auto word = dsl::while_one(dsl::ascii::alpha); - return dsl::do_while(word, dsl::ascii::space); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/eof.cpp b/assembler/ext/src/lexy/docs/assets/playground/eof.cpp deleted file mode 100644 index 00f60442f1..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/eof.cpp +++ /dev/null @@ -1,5 +0,0 @@ -struct production -{ - static constexpr auto rule = dsl::eof; -}; - diff --git a/assembler/ext/src/lexy/docs/assets/playground/eol.cpp b/assembler/ext/src/lexy/docs/assets/playground/eol.cpp deleted file mode 100644 index d5ee8e5ddc..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/eol.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// INPUT:Hello -struct production -{ - static constexpr auto rule = LEXY_LIT("Hello") + dsl::eol; -}; - diff --git a/assembler/ext/src/lexy/docs/assets/playground/equal_counts.cpp b/assembler/ext/src/lexy/docs/assets/playground/equal_counts.cpp deleted file mode 100644 index 50b2efa441..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/equal_counts.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// INPUT:aaabbcccc -struct production -{ - static constexpr auto rule = [] { - // Parse 'a's and count them. - auto ac = dsl::context_counter; - auto a = ac.create() + ac.push(dsl::while_(dsl::lit_c<'a'>)); - - // Parse 'b's and count them. - auto bc = dsl::context_counter; - auto b = bc.create() + bc.push(dsl::while_(dsl::lit_c<'b'>)); - - // Parse 'c's and count them. - auto cc = dsl::context_counter; - auto c = cc.create() + cc.push(dsl::while_(dsl::lit_c<'c'>)); - - // Check that they're equal. - auto check = dsl::equal_counts(ac, bc, cc); - - return a + b + c + check; - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/exhausted_choice.cpp b/assembler/ext/src/lexy/docs/assets/playground/exhausted_choice.cpp deleted file mode 100644 index 6b1cd3d062..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/exhausted_choice.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:Hey -struct production -{ - static constexpr auto rule = LEXY_LIT("Hello") | LEXY_LIT("Hi"); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/expected_char_class.cpp b/assembler/ext/src/lexy/docs/assets/playground/expected_char_class.cpp deleted file mode 100644 index de3be5d436..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/expected_char_class.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:8 -struct production -{ - static constexpr auto rule = dsl::digit; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/expected_literal.cpp b/assembler/ext/src/lexy/docs/assets/playground/expected_literal.cpp deleted file mode 100644 index a08ed18946..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/expected_literal.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:Hello Warld! -struct production -{ - static constexpr auto rule = LEXY_LIT("Hello World!"); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/expr.cpp b/assembler/ext/src/lexy/docs/assets/playground/expr.cpp deleted file mode 100644 index 12a5b82da5..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/expr.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// INPUT:3*2+-1 -struct production : lexy::expression_production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto atom = dsl::integer; - - struct prefix : dsl::prefix_op - { - static constexpr auto op = dsl::op(dsl::lit_c<'-'>); - using operand = dsl::atom; - }; - - struct product : dsl::infix_op_left - { - static constexpr auto op = dsl::op(dsl::lit_c<'*'>) / dsl::op(dsl::lit_c<'/'>); - using operand = prefix; - }; - - struct sum : dsl::infix_op_left - { - static constexpr auto op = dsl::op(dsl::lit_c<'+'>) / dsl::op(dsl::lit_c<'-'>); - using operand = product; - }; - - using operation = sum; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/expr_groups.cpp b/assembler/ext/src/lexy/docs/assets/playground/expr_groups.cpp deleted file mode 100644 index 827f31faaa..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/expr_groups.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// INPUT:1+2|3 -struct production : lexy::expression_production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto atom = dsl::integer; - - struct math : dsl::infix_op_left - { - static constexpr auto op = dsl::op(dsl::lit_c<'+'>) / dsl::op(dsl::lit_c<'-'>); - using operand = dsl::atom; - }; - - struct bits : dsl::infix_op_left - { - static constexpr auto op = dsl::op(dsl::lit_c<'|'>) / dsl::op(dsl::lit_c<'&'>); - using operand = dsl::atom; - }; - - // Either a math or a bit operator, but not mixing. - using operation = dsl::groups; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/find.cpp b/assembler/ext/src/lexy/docs/assets/playground/find.cpp deleted file mode 100644 index 138b8d28df..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/find.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// INPUT:type Id = ;\nfunction foo(...) {\n ...\n}\n -constexpr auto id = dsl::identifier(dsl::ascii::alpha); -constexpr auto kw_function = LEXY_KEYWORD("function", id); -constexpr auto kw_type = LEXY_KEYWORD("type", id); - -struct function_decl -{ - static constexpr auto rule = [] { - auto arguments = dsl::parenthesized(LEXY_LIT("...")); - auto body = dsl::curly_bracketed(LEXY_LIT("...")); - - return kw_function >> id + arguments + body; - }(); -}; - -struct type_decl -{ - static constexpr auto rule // - = kw_type >> id + dsl::lit_c<'='> + id + dsl::semicolon; -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto rule = [] { - auto decl = dsl::p | dsl::p; - - // We recover from any errors by skipping until the next decl. - auto decl_recover = dsl::find(kw_function, kw_type); - auto try_decl = dsl::try_(decl, decl_recover); - - return dsl::list(try_decl); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/identifier-unicode.cpp b/assembler/ext/src/lexy/docs/assets/playground/identifier-unicode.cpp deleted file mode 100644 index 19499a7742..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/identifier-unicode.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// INPUT:ïdéntiför_123 -struct production -{ - static constexpr auto rule - = dsl::identifier(dsl::unicode::xid_start_underscore, // want '_' as well - dsl::unicode::xid_continue); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/identifier.cpp b/assembler/ext/src/lexy/docs/assets/playground/identifier.cpp deleted file mode 100644 index 635939b11e..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/identifier.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// INPUT:identifier_123 -struct production -{ - static constexpr auto rule = [] { - auto head = dsl::ascii::alpha_underscore; - auto tail = dsl::ascii::alpha_digit_underscore; - return dsl::identifier(head, tail); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/if.cpp b/assembler/ext/src/lexy/docs/assets/playground/if.cpp deleted file mode 100644 index d6a4add07d..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/if.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// INPUT:3.14 -struct production -{ - static constexpr auto rule = [] { - auto integer = dsl::digits<>.no_leading_zero(); - auto fraction = dsl::digits<>; - - return integer + dsl::if_(dsl::period >> fraction); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/infix_op_left.cpp b/assembler/ext/src/lexy/docs/assets/playground/infix_op_left.cpp deleted file mode 100644 index 0f2736db75..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/infix_op_left.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// INPUT:1+2+3 -struct production : lexy::expression_production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto atom = dsl::integer; - - struct operation : dsl::infix_op_left - { - static constexpr auto op = dsl::op(dsl::lit_c<'+'>); - using operand = dsl::atom; - }; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/infix_op_list.cpp b/assembler/ext/src/lexy/docs/assets/playground/infix_op_list.cpp deleted file mode 100644 index de4b1bcb4d..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/infix_op_list.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// INPUT:1+2+3 -struct production : lexy::expression_production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto atom = dsl::integer; - - struct operation : dsl::infix_op_list - { - static constexpr auto op = dsl::op(dsl::lit_c<'+'>); - using operand = dsl::atom; - }; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/infix_op_right.cpp b/assembler/ext/src/lexy/docs/assets/playground/infix_op_right.cpp deleted file mode 100644 index 2b936ee392..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/infix_op_right.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// INPUT:1**2**3 -struct production : lexy::expression_production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto atom = dsl::integer; - - struct operation : dsl::infix_op_right - { - static constexpr auto op = dsl::op(LEXY_LIT("**")); - using operand = dsl::atom; - }; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/infix_op_single.cpp b/assembler/ext/src/lexy/docs/assets/playground/infix_op_single.cpp deleted file mode 100644 index 7fddd4ebdf..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/infix_op_single.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// INPUT:1<2<3 -struct production : lexy::expression_production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto atom = dsl::integer; - - struct operation : dsl::infix_op_single - { - static constexpr auto op = dsl::op(dsl::lit_c<'<'>); - using operand = dsl::atom; - }; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/inline.cpp b/assembler/ext/src/lexy/docs/assets/playground/inline.cpp deleted file mode 100644 index 055f929194..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/inline.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// INPUT:Hello World! -struct name -{ - static constexpr auto rule - // One or more alpha numeric characters, underscores or hyphens. - = dsl::identifier(dsl::unicode::alnum / dsl::lit_c<'_'> / dsl::lit_c<'-'>); -}; - -struct production -{ - // Allow arbitrary spaces between individual tokens. - // Note that this includes the individual characters of the name. - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto greeting = LEXY_LIT("Hello"); - return greeting + dsl::inline_ + dsl::exclamation_mark + dsl::eof; - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/keyword.cpp b/assembler/ext/src/lexy/docs/assets/playground/keyword.cpp deleted file mode 100644 index ca886b3fa1..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/keyword.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// INPUT:integer -struct production -{ - static constexpr auto rule = [] { - // Define the general identifier syntax. - auto head = dsl::ascii::alpha_underscore; - auto tail = dsl::ascii::alpha_digit_underscore; - auto id = dsl::identifier(head, tail); - - // Parse a keyword. - return LEXY_KEYWORD("int", id); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/lit.cpp b/assembler/ext/src/lexy/docs/assets/playground/lit.cpp deleted file mode 100644 index 335f528df3..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/lit.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:Hello World! -struct production -{ - static constexpr auto rule = LEXY_LIT("Hello World!"); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/lit_ascii.cpp b/assembler/ext/src/lexy/docs/assets/playground/lit_ascii.cpp deleted file mode 100644 index cc7d3a207f..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/lit_ascii.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// INPUT:Hello World! -struct production -{ - // The character type doesn't matter if it only contains ASCII characters. - // The literal is encoded in UTF-16 whereas the (playground) input - // is encoded in UTF-8, but as its only ASCII characters, - // lexy will transcode for you. - static constexpr auto rule = LEXY_LIT(u"Hello World!"); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/lit_cp.cpp b/assembler/ext/src/lexy/docs/assets/playground/lit_cp.cpp deleted file mode 100644 index fb00e294ce..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/lit_cp.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:🙂 -struct production -{ - static constexpr auto rule = dsl::lit_cp<0x1F642> + dsl::eof; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/lit_utf8.cpp b/assembler/ext/src/lexy/docs/assets/playground/lit_utf8.cpp deleted file mode 100644 index d730d01941..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/lit_utf8.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// INPUT:ä -struct production -{ - // The string literal contains UTF-8 text, - // which means the input needs to be UTF-8 encoded as well. - // - // WARNING: This will only match if both agree on a normalization for 'ä'! - static constexpr auto rule = LEXY_LIT(u8"ä"); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/literal_set.cpp b/assembler/ext/src/lexy/docs/assets/playground/literal_set.cpp deleted file mode 100644 index 8a4fe8cf49..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/literal_set.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// INPUT:abc -struct production -{ - static constexpr auto rule // - = dsl::literal_set(LEXY_LIT("a"), LEXY_LIT("abc"), LEXY_LIT("bc")); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/loop.cpp b/assembler/ext/src/lexy/docs/assets/playground/loop.cpp deleted file mode 100644 index 02c4526a10..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/loop.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// INPUT:type Id = Int;\nfunction foo(...) {\n ...\n}\n -constexpr auto id = dsl::identifier(dsl::ascii::alpha); -constexpr auto kw_function = LEXY_KEYWORD("function", id); -constexpr auto kw_type = LEXY_KEYWORD("type", id); - -struct function_decl -{ - static constexpr auto rule = [] { - auto arguments = dsl::parenthesized(LEXY_LIT("...")); - auto body = dsl::curly_bracketed(LEXY_LIT("...")); - - return kw_function >> id + arguments + body; - }(); -}; - -struct type_decl -{ - static constexpr auto rule // - = kw_type >> id + dsl::lit_c<'='> + id + dsl::semicolon; -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto rule - // Note: a real implementation couldn't use loop(). - // If the decls produce values, list() has to be used instead. - = dsl::loop(dsl::p | dsl::p | dsl::break_); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/manual_whitespace.cpp b/assembler/ext/src/lexy/docs/assets/playground/manual_whitespace.cpp deleted file mode 100644 index b32372c6f1..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/manual_whitespace.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// INPUT:Hello\nWorld !\n -struct production -{ - static constexpr auto rule = [] { - auto ws = dsl::whitespace(dsl::ascii::space); - return LEXY_LIT("Hello") + ws + LEXY_LIT("World") // - + ws + dsl::exclamation_mark + ws + dsl::eof; - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/minus_sign.cpp b/assembler/ext/src/lexy/docs/assets/playground/minus_sign.cpp deleted file mode 100644 index 4c630786ea..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/minus_sign.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// INPUT:-123 -struct production -{ - static constexpr auto rule - // Minus sign followed by a decimal integer. - = dsl::minus_sign + dsl::integer; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/must.cpp b/assembler/ext/src/lexy/docs/assets/playground/must.cpp deleted file mode 100644 index a5cd3206e1..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/must.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// INPUT:echo World -struct production -{ - struct expected_sep - { - static constexpr auto name = "expected separator"; - }; - - static constexpr auto rule = [] { - // A separator is either blank or \ + newline. - // If a separator is not present, raise the specific error. - auto blank = dsl::ascii::blank; - auto escaped_nl = dsl::backslash >> dsl::newline; - auto sep = dsl::must(blank | escaped_nl).error; - - return LEXY_LIT("echo") + sep - + dsl::identifier(dsl::ascii::alnum) - // Allow an optional separator before EOL. - + dsl::if_(sep) + dsl::eol; - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/n_digits.cpp b/assembler/ext/src/lexy/docs/assets/playground/n_digits.cpp deleted file mode 100644 index 015198e020..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/n_digits.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:\xABCDEF -struct production -{ - static constexpr auto rule = LEXY_LIT("\\x") + dsl::n_digits<2, dsl::hex>; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/newline.cpp b/assembler/ext/src/lexy/docs/assets/playground/newline.cpp deleted file mode 100644 index fa56efa736..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/newline.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// INPUT:Hello\n -struct production -{ - static constexpr auto rule = LEXY_LIT("Hello") + dsl::newline; -}; - diff --git a/assembler/ext/src/lexy/docs/assets/playground/no_trailing.cpp b/assembler/ext/src/lexy/docs/assets/playground/no_trailing.cpp deleted file mode 100644 index 8010c14a8d..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/no_trailing.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// INPUT:Hello World! -struct production -{ - static constexpr auto rule = LEXY_LIT("Hello") + dsl::eof; -}; - diff --git a/assembler/ext/src/lexy/docs/assets/playground/no_whitespace.cpp b/assembler/ext/src/lexy/docs/assets/playground/no_whitespace.cpp deleted file mode 100644 index 4f1076d3e7..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/no_whitespace.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// INPUT:Hello\nWorld ! -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto rule // - = dsl::no_whitespace(LEXY_LIT("Hello") + LEXY_LIT("World")) // - + dsl::exclamation_mark + dsl::eof; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/not_followed_by.cpp b/assembler/ext/src/lexy/docs/assets/playground/not_followed_by.cpp deleted file mode 100644 index 8a39e44d54..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/not_followed_by.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// INPUT:== -struct production -{ - static constexpr auto rule - // = but then not another = - = dsl::not_followed_by(dsl::lit_c<'='>, dsl::lit_c<'='>); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/one_of.cpp b/assembler/ext/src/lexy/docs/assets/playground/one_of.cpp deleted file mode 100644 index 507e5232d4..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/one_of.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:B -struct production -{ - static constexpr auto rule = LEXY_ASCII_ONE_OF("CDEFGB"); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/parenthesized.cpp b/assembler/ext/src/lexy/docs/assets/playground/parenthesized.cpp deleted file mode 100644 index bb48c98b90..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/parenthesized.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// INPUT:(abc,12,abc123,123) -struct production -{ - static constexpr auto rule = [] { - auto item = LEXY_LIT("abc") | LEXY_LIT("123"); - - return dsl::parenthesized.list(item, dsl::sep(dsl::comma)); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/partial_combination.cpp b/assembler/ext/src/lexy/docs/assets/playground/partial_combination.cpp deleted file mode 100644 index b26a85f1ff..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/partial_combination.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// INPUT:ca -struct production -{ - static constexpr auto rule - = dsl::partial_combination(dsl::lit_c<'a'>, dsl::lit_c<'b'>, dsl::lit_c<'c'>); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/peek.cpp b/assembler/ext/src/lexy/docs/assets/playground/peek.cpp deleted file mode 100644 index 046d0beda0..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/peek.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// INPUT:-11 -struct production -{ - static constexpr auto rule = [] { - // Number with optional minus sign. - auto number = dsl::minus_sign + dsl::digits<>; - - // Only parse a number if we have a minus or digit. - auto condition = dsl::peek(dsl::lit_c<'-'> / dsl::digit<>); - return dsl::if_(condition >> number); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/peek_not.cpp b/assembler/ext/src/lexy/docs/assets/playground/peek_not.cpp deleted file mode 100644 index 14021ff712..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/peek_not.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// INPUT:Hello World \n -struct production -{ - struct trailing_spaces - { - static constexpr auto name = "trailing spaces"; - }; - - static constexpr auto rule - = LEXY_LIT("Hello World") - + dsl::peek_not(dsl::ascii::space).error + dsl::eof; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/plus_sign.cpp b/assembler/ext/src/lexy/docs/assets/playground/plus_sign.cpp deleted file mode 100644 index 1399760c96..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/plus_sign.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// INPUT:+123 -struct production -{ - static constexpr auto rule - // Plus sign followed by a decimal integer. - = dsl::plus_sign + dsl::integer; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/position.cpp b/assembler/ext/src/lexy/docs/assets/playground/position.cpp deleted file mode 100644 index 1d069f61bf..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/position.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// INPUT:function foo(...)\n{\n ...\n} -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto id = dsl::identifier(dsl::ascii::alpha); - auto kw_function = LEXY_KEYWORD("function", id); - - auto arguments = dsl::parenthesized(LEXY_LIT("...")); - auto body = dsl::curly_bracketed(LEXY_LIT("...")); - - // The position of a function is the first character of the name. - return kw_function + dsl::position + id + arguments + body; - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/postfix_op.cpp b/assembler/ext/src/lexy/docs/assets/playground/postfix_op.cpp deleted file mode 100644 index dfd42347ba..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/postfix_op.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// INPUT:1++++ -struct production : lexy::expression_production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto atom = dsl::integer; - - struct operation : dsl::postfix_op - { - static constexpr auto op = dsl::op(LEXY_LIT("++")); - using operand = dsl::atom; - }; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/prefix_op.cpp b/assembler/ext/src/lexy/docs/assets/playground/prefix_op.cpp deleted file mode 100644 index 7fd4dd92f5..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/prefix_op.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// INPUT:--1 -struct production : lexy::expression_production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto atom = dsl::integer; - - struct operation : dsl::prefix_op - { - static constexpr auto op = dsl::op(dsl::lit_c<'-'>); - using operand = dsl::atom; - }; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/quoted.cpp b/assembler/ext/src/lexy/docs/assets/playground/quoted.cpp deleted file mode 100644 index 14115571b4..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/quoted.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// INPUT:"Hello World!" -struct production -{ - static constexpr auto rule = [] { - // Arbitrary code points that aren't control characters. - auto c = -dsl::ascii::control; - - return dsl::quoted(c); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/quoted_error.cpp b/assembler/ext/src/lexy/docs/assets/playground/quoted_error.cpp deleted file mode 100644 index 146d16b6be..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/quoted_error.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// INPUT:"Hello\nWorld" -struct production -{ - struct invalid_character - { - static constexpr auto name = "invalid character"; - }; - - static constexpr auto rule = [] { - // Arbitrary code points that aren't control characters. - auto c = (-dsl::ascii::control).error; - - return dsl::quoted(c); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/quoted_limit.cpp b/assembler/ext/src/lexy/docs/assets/playground/quoted_limit.cpp deleted file mode 100644 index 23300fdcb8..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/quoted_limit.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// INPUT:"Hello World!\n -struct production -{ - static constexpr auto rule = [] { - // Arbitrary code points that aren't control characters. - auto c = -dsl::ascii::control; - - // If we have a newline inside our string, we're missing the closing ". - auto quoted = dsl::quoted.limit(dsl::ascii::newline); - return quoted(c); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/quoted_token.cpp b/assembler/ext/src/lexy/docs/assets/playground/quoted_token.cpp deleted file mode 100644 index cf0a1f708c..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/quoted_token.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// INPUT: " Hello World! " ; -struct quoted : lexy::token_production -{ - static constexpr auto rule = [] { - // Arbitrary code points that aren't control characters. - auto c = -dsl::ascii::control; - - return dsl::quoted(c); - }(); -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto rule = dsl::p + dsl::semicolon; -}; - diff --git a/assembler/ext/src/lexy/docs/assets/playground/recover.cpp b/assembler/ext/src/lexy/docs/assets/playground/recover.cpp deleted file mode 100644 index 93b92c22e7..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/recover.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// INPUT:type Id = ;\nfunction foo(...) {\n ...\n}\n -constexpr auto id = dsl::identifier(dsl::ascii::alpha); -constexpr auto kw_function = LEXY_KEYWORD("function", id); -constexpr auto kw_type = LEXY_KEYWORD("type", id); - -struct function_decl -{ - static constexpr auto rule = [] { - auto arguments = dsl::parenthesized(LEXY_LIT("...")); - auto body = dsl::curly_bracketed(LEXY_LIT("...")); - - return kw_function >> id + arguments + body; - }(); -}; - -struct type_decl -{ - static constexpr auto rule // - = kw_type >> id + dsl::lit_c<'='> + id + dsl::semicolon; -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto rule = [] { - auto decl = dsl::p | dsl::p; - - // We recover from any errors by continuing with the next declaration. - auto decl_recover = dsl::recover(dsl::p, dsl::p); - auto try_decl = dsl::try_(decl, decl_recover); - - return dsl::list(try_decl); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/recurse.cpp b/assembler/ext/src/lexy/docs/assets/playground/recurse.cpp deleted file mode 100644 index 450adb234e..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/recurse.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// INPUT:(((atom))) -struct production -{ - static constexpr auto rule - // Either we parse ourselves surrounded by expressions, or an atom. - = dsl::parenthesized(dsl::recurse) | LEXY_LIT("atom"); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/recurse_limit.cpp b/assembler/ext/src/lexy/docs/assets/playground/recurse_limit.cpp deleted file mode 100644 index 10340dc693..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/recurse_limit.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// INPUT:((((atom)))) -struct production -{ - // We define a (tiny) maximum recursion depth. - // This prevents unbounded recursion which can cause a stack overflow. - static constexpr auto max_recursion_depth = 3; - - static constexpr auto rule - // Either we parse ourselves surrounded by expressions, or an atom. - = dsl::parenthesized(dsl::recurse) | LEXY_LIT("atom"); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/repeat.cpp b/assembler/ext/src/lexy/docs/assets/playground/repeat.cpp deleted file mode 100644 index 8dfe74abfd..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/repeat.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// INPUT:3aaa -struct production -{ - static constexpr auto rule - // The number of 'a's is determined by the integer value. - = dsl::repeat(dsl::integer)(dsl::lit_c<'a'>); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/reserved_identifier.cpp b/assembler/ext/src/lexy/docs/assets/playground/reserved_identifier.cpp deleted file mode 100644 index 6319da90b9..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/reserved_identifier.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// INPUT:reserved__id -struct production -{ - static constexpr auto rule = [] { - // Define the general identifier syntax. - auto head = dsl::ascii::alpha_underscore; - auto tail = dsl::ascii::alpha_digit_underscore; - auto id = dsl::identifier(head, tail); - - // Define some keywords. - auto kw_int = LEXY_KEYWORD("int", id); - auto kw_struct = LEXY_KEYWORD("struct", id); - // ... - - // Parse an identifier - return id - // ... that is not a keyword, - .reserve(kw_int, kw_struct) - // ... doesn't start with an underscore, - .reserve_prefix(dsl::lit_c<'_'>) - // ... or contains a double underscore. - .reserve_containing(LEXY_LIT("__")); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/reserved_identifier_case_folding.cpp b/assembler/ext/src/lexy/docs/assets/playground/reserved_identifier_case_folding.cpp deleted file mode 100644 index ab00c47223..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/reserved_identifier_case_folding.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// INPUT:sTrUcT -struct production -{ - static constexpr auto rule = [] { - // Define the general identifier syntax. - auto head = dsl::ascii::alpha_underscore; - auto tail = dsl::ascii::alpha_digit_underscore; - auto id = dsl::identifier(head, tail); - - // Define some case insensitive keywords. - auto kw_int = dsl::ascii::case_folding(LEXY_KEYWORD("int", id)); - auto kw_struct = dsl::ascii::case_folding(LEXY_KEYWORD("struct", id)); - // ... - - // Parse an identifier that is not a keyword. - return id.reserve(kw_int, kw_struct); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/return.cpp b/assembler/ext/src/lexy/docs/assets/playground/return.cpp deleted file mode 100644 index 9758fc40a4..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/return.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// INPUT:
-struct production -{ - static constexpr auto rule = [] { - auto tag_name = dsl::identifier(dsl::ascii::alpha); - - // If we're having tag name followed by a `/`, - // it is an empty element without content. - // Immediately return in that case. - auto if_empty = dsl::if_(dsl::lit_c<'/'> >> dsl::return_); - auto open_tag = dsl::angle_bracketed(tag_name + if_empty); - auto close_tag = dsl::angle_bracketed(dsl::lit_c<'/'> + tag_name); - - // Placeholder content. - auto content = LEXY_LIT("content"); - - return open_tag + content + close_tag; - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/scan-recovery.cpp b/assembler/ext/src/lexy/docs/assets/playground/scan-recovery.cpp deleted file mode 100644 index ce4363f4df..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/scan-recovery.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// INPUT:"123abc" -struct production : lexy::scan_production -{ - template - static constexpr scan_result scan(lexy::rule_scanner& scanner) - { - // Parse the initial quote. - scanner.parse(dsl::lit_c<'"'>); - if (!scanner) - return lexy::scan_failed; - - // Parse an integer. - lexy::scan_result integer; - scanner.parse(integer, dsl::integer); - if (!scanner) - return lexy::scan_failed; - - // Parse the closing quote. - scanner.parse(dsl::lit_c<'"'>); - if (!scanner) - { - // Recover by discarding everything until a closing quote is found. - auto recovery = scanner.error_recovery(); - while (!scanner.branch(dsl::lit_c<'"'>)) - { - if (!scanner.discard(dsl::ascii::character)) - { - // We've failed to recover. - LEXY_MOV(recovery).cancel(); - return lexy::scan_failed; - } - } - LEXY_MOV(recovery).finish(); - } - - return integer.value(); - } -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/scan.cpp b/assembler/ext/src/lexy/docs/assets/playground/scan.cpp deleted file mode 100644 index d8803d5dc9..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/scan.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// INPUT:r##"Hello "# World!"## -struct production -// We produce a UTF-8 lexeme (i.e. a string view) of the contents. -: lexy::scan_production>, - lexy::token_production -{ - struct unterminated - { - static constexpr auto name = "unterminated raw string literal"; - }; - - template - static constexpr scan_result scan(lexy::rule_scanner& scanner) - { - auto open_hash_count = 0; - - // Parse the opening delimiter. - scanner.parse(dsl::lit_c<'r'>); - while (scanner.branch(dsl::lit_c<'#'>)) - ++open_hash_count; - scanner.parse(dsl::lit_c<'"'>); - if (!scanner) - return lexy::scan_failed; - - // Parse the contents of the string. - auto content_begin = scanner.position(); - for (auto closing_hash_count = -1; closing_hash_count != open_hash_count;) - { - // Handle the next character. - if (scanner.branch(dsl::lit_c<'"'>)) - { - // We have a quote, count the next hashes. - closing_hash_count = 0; - } - else if (scanner.branch(dsl::lit_c<'#'>)) - { - // Count a hash if necessary. - if (closing_hash_count != -1) - ++closing_hash_count; - } - else if (scanner.is_at_eof()) - { - // Report an error for an unterminated literal. - scanner.fatal_error(unterminated{}, scanner.begin(), scanner.position()); - return lexy::scan_failed; - } - else - { - // Parse any other code point, and invalidate hash count. - scanner.parse(dsl::code_point); - closing_hash_count = -1; - } - - // Check for any errors we might have gotten. - if (!scanner) - return lexy::scan_failed; - } - auto content_end = scanner.position(); - - return lexy::buffer_lexeme(content_begin, content_end); - } -}; - diff --git a/assembler/ext/src/lexy/docs/assets/playground/terminator.cpp b/assembler/ext/src/lexy/docs/assets/playground/terminator.cpp deleted file mode 100644 index f6180775c0..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/terminator.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// INPUT:statement; -struct production -{ - static constexpr auto rule = [] { - auto terminator = dsl::terminator(dsl::semicolon); - return terminator(LEXY_LIT("statement")); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/terminator_list.cpp b/assembler/ext/src/lexy/docs/assets/playground/terminator_list.cpp deleted file mode 100644 index 4169eb4932..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/terminator_list.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// INPUT:abc,12,abc123,123. -struct production -{ - static constexpr auto rule = [] { - auto item = LEXY_LIT("abc") | LEXY_LIT("123"); - - auto terminator = dsl::terminator(dsl::period); - return terminator.list(item, dsl::sep(dsl::comma)); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/terminator_opt.cpp b/assembler/ext/src/lexy/docs/assets/playground/terminator_opt.cpp deleted file mode 100644 index b4c4d40253..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/terminator_opt.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// INPUT:; -struct production -{ - static constexpr auto rule = [] { - auto terminator = dsl::terminator(dsl::semicolon); - return terminator.opt(LEXY_LIT("statement")); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/terminator_recovery.cpp b/assembler/ext/src/lexy/docs/assets/playground/terminator_recovery.cpp deleted file mode 100644 index 0b432e76fa..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/terminator_recovery.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// INPUT:{\n foo();\n error1;\n bar();\n error2\n foo();\n error3\n} -struct statement -{ - static constexpr auto rule = [] { - // A statement is terminated by a semicolon. - // Error recovery fails when we've reached the } of the scope. - auto terminator = dsl::terminator(dsl::semicolon).limit(dsl::lit_c<'}'>); - return terminator.opt(LEXY_LIT("foo()") | LEXY_LIT("bar()")); - }(); -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - - // Just a list of statements surrounded by {}. - static constexpr auto rule = dsl::curly_bracketed.list(dsl::p); -}; - diff --git a/assembler/ext/src/lexy/docs/assets/playground/terminator_try.cpp b/assembler/ext/src/lexy/docs/assets/playground/terminator_try.cpp deleted file mode 100644 index a7fba53f94..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/terminator_try.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// INPUT:state; -struct production -{ - static constexpr auto rule = [] { - auto terminator = dsl::terminator(dsl::semicolon); - return terminator.try_(LEXY_LIT("statement")); - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/trace.cpp b/assembler/ext/src/lexy/docs/assets/playground/trace.cpp deleted file mode 100644 index a7c0967712..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/trace.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// INPUT:Hello abx! -struct name -{ - static constexpr auto rule = dsl::identifier(dsl::ascii::alpha); -}; - -struct alphabet -{ - static constexpr auto rule - // Just something stupid, so we can see a backtrack. - = dsl::peek(LEXY_LIT("abc")) >> LEXY_LIT("abcdefg"); -}; - -struct number -{ - static constexpr auto rule = dsl::identifier(dsl::ascii::digit); -}; - -struct object -{ - struct unexpected - { - static constexpr auto name = "unexpected"; - }; - - static constexpr auto rule - = dsl::p | dsl::p | dsl::p - // Issue an error, but recover. - | dsl::try_(dsl::error); -}; - -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - - static constexpr auto rule = [] { - auto greeting = LEXY_LIT("Hello"); - return greeting + LEXY_DEBUG("finished greeting") // - + dsl::p + dsl::exclamation_mark; - }(); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/while.cpp b/assembler/ext/src/lexy/docs/assets/playground/while.cpp deleted file mode 100644 index c4004a19fe..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/while.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:Hello -struct production -{ - static constexpr auto rule = dsl::while_(dsl::ascii::alpha); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/while_bad.cpp b/assembler/ext/src/lexy/docs/assets/playground/while_bad.cpp deleted file mode 100644 index 43d7204d05..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/while_bad.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:aaa -struct production -{ - static constexpr auto rule = dsl::while_(dsl::lit_c<'a'>) + dsl::lit_c<'a'>; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/while_one.cpp b/assembler/ext/src/lexy/docs/assets/playground/while_one.cpp deleted file mode 100644 index 36194c2c3c..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/while_one.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:Hello -struct production -{ - static constexpr auto rule = dsl::while_one(dsl::ascii::alpha); -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/whitespace.cpp b/assembler/ext/src/lexy/docs/assets/playground/whitespace.cpp deleted file mode 100644 index 1f8c665ee4..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/whitespace.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// INPUT:Hello\nWorld ! -struct production -{ - static constexpr auto whitespace = dsl::ascii::space; - static constexpr auto rule // - = LEXY_LIT("Hello") + LEXY_LIT("World") // - + dsl::exclamation_mark + dsl::eof; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/whitespace_comment.cpp b/assembler/ext/src/lexy/docs/assets/playground/whitespace_comment.cpp deleted file mode 100644 index 7873737686..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/whitespace_comment.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// INPUT:Hello /* C comment */\nWorld ! -struct production -{ - // Note that an unterminated C comment will raise an error. - static constexpr auto whitespace - = dsl::ascii::space | LEXY_LIT("/*") >> dsl::until(LEXY_LIT("*/")); - - static constexpr auto rule // - = LEXY_LIT("Hello") + LEXY_LIT("World") + dsl::exclamation_mark; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/whitespace_determination.cpp b/assembler/ext/src/lexy/docs/assets/playground/whitespace_determination.cpp deleted file mode 100644 index 122f280863..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/whitespace_determination.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// INPUT:+(+inner+normal+)+,+(-inner-override-)-,+(innertoken)+,+(_inner_token_whitespace)_+.+ -// An inner production that does not override the whitespace. -struct inner_normal -{ - // After every token in this rule, the whitespace is '+', - // as determined by its root production `production`. - static constexpr auto rule // - = dsl::parenthesized(LEXY_LIT("inner") + LEXY_LIT("normal")); -}; - -// An inner production that overrides the current whitespace definition. -struct inner_override -{ - static constexpr auto whitespace = dsl::lit_c<'-'>; - - // After every token in this rule, the whitespace is '-', - // as determined by the `whitespace` member of the current production. - static constexpr auto rule // - = dsl::parenthesized(LEXY_LIT("inner") + LEXY_LIT("override")); -}; - -// A token production that does not have inner whitespace. -struct inner_token : lexy::token_production -{ - struct inner_inner - { - // No whitespace is skipped here, as its root production is `inner_token`, - // which does not have a `whitespace` member. - static constexpr auto rule = LEXY_LIT("inner") + LEXY_LIT("token"); - }; - - // No whitespace is skipped here, as the current production inherits from - // `lexy::token_production`. - static constexpr auto rule = dsl::parenthesized(dsl::p); -}; - -// A token production that does have inner whitespace, but different one. -struct inner_token_whitespace : lexy::token_production -{ - struct inner_inner - { - // After every token in this rule, the whitespace is '_', - // as determined by its root production `inner_token_whitespace`. - static constexpr auto rule // - = LEXY_LIT("inner") + LEXY_LIT("token") + LEXY_LIT("whitespace"); - }; - - static constexpr auto whitespace = dsl::lit_c<'_'>; - - static constexpr auto rule = dsl::parenthesized(dsl::p); -}; - -// The root production defines whitespace. -struct production -{ - static constexpr auto whitespace = dsl::lit_c<'+'>; - - // After every token in this rule, the whitespace is '+', - // as determined by the `whitespace` member of the current production. - // Whitespace is also skipped after the two token productions. - static constexpr auto rule - = dsl::p + dsl::comma + dsl::p + dsl::comma - + dsl::p + dsl::comma + dsl::p // - + dsl::period + dsl::eof; -}; diff --git a/assembler/ext/src/lexy/docs/assets/playground/zero.cpp b/assembler/ext/src/lexy/docs/assets/playground/zero.cpp deleted file mode 100644 index fb3bd0f8d6..0000000000 --- a/assembler/ext/src/lexy/docs/assets/playground/zero.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// INPUT:0 -struct production -{ - static constexpr auto rule = dsl::zero + dsl::eof; -}; diff --git a/assembler/ext/src/lexy/docs/benchmark_json.adoc b/assembler/ext/src/lexy/docs/benchmark_json.adoc deleted file mode 100644 index a45d1432e7..0000000000 --- a/assembler/ext/src/lexy/docs/benchmark_json.adoc +++ /dev/null @@ -1,165 +0,0 @@ -= JSON Validation Benchmark - -// This file is automatically generated by `lexy_benchmark_json`. -// DO NOT MODIFY. - -This benchmark measures the time it takes to *validate* JSON, i.e. to check whether it is well-formed. -Validation was chosen as opposed to parsing, as parsing speed depends on the JSON data structure as well. -Implementing an efficient JSON container is out of scope for lexy, so it would have a disadvantage over the specialized JSON libraries. - -The average validation times for each input are shown in the boxplots below. -Lower values are better. - -[pass] -++++ - -++++ - - -[pass] -++++ -
- -++++ - -[pass] -++++ -
- -++++ - -[pass] -++++ -
- -++++ - -.The implementations -`baseline`:: - This simply adds all input characters of the JSON document without performing actual validation. -`lexy`:: - A JSON validator using the lexy grammar from the example. -`pegtl`:: - A JSON validator using the https://github.com/taocpp/PEGTL[PEGTL] JSON grammar. -`nlohmann/json`:: - A JSON validator using https://github.com/nlohmann/json[JSON for Modern C++] implemented by `nlohmann::json::accept()`. -`rapidjson`:: - A JSON validator using https://github.com/Tencent/rapidjson[rapidjson] implemented using a SAX parser with the `rapidjson::BaseReaderHandler`. -`Boost.JSON`:: - A JSON validator using https://github.com/boostorg/json[Boost.JSON] implemented using a custom parse handler. - -.The inputs -`canada.json`:: - Contains lots of 2-element arrays holding floating-point coordinate pairs. - Taken from https://github.com/miloyip/nativejson-benchmark. -`citm_catalog.json`:: - Big JSON file with some variety. - Taken from https://github.com/miloyip/nativejson-benchmark. -`twitter.json`:: - Some data from twitter's API. - Taken from https://github.com/miloyip/nativejson-benchmark. - -.The Methodology -The input data is read using `lexy::read_file()`. -The resulting buffer is then passed to the various implementations using their memory inputs. -Benchmarking is done by https://nanobench.ankerl.com/[nanobench] on an AMD FX-6300. - \ No newline at end of file diff --git a/assembler/ext/src/lexy/docs/config.toml b/assembler/ext/src/lexy/docs/config.toml deleted file mode 100644 index a063a4b5f3..0000000000 --- a/assembler/ext/src/lexy/docs/config.toml +++ /dev/null @@ -1,21 +0,0 @@ -title = "lexy" -baseURL = "https://lexy.foonathan.net/" -languageCode = "en-us" -copyright = "2020-2022 Jonathan Müller and lexy contributors" - -disableKinds = ["RSS", "taxonomy", "taxonomyTerm"] - -[markup.tableOfContents] -endLevel = 3 -[markup.asciidocExt.attributes] -source-highlighter = "pygments" - -[security.exec] -allow = ['^asciidoctor$'] - -[params] -tagline = "C++ parsing DSL" -github = "https://github.com/foonathan/lexy" -github_src_prefix = "https://github.com/foonathan/lexy/blob/main" -github_edit_prefix = "https://github.com/foonathan/lexy/edit/main" - diff --git a/assembler/ext/src/lexy/docs/content/benchmark_json.adoc b/assembler/ext/src/lexy/docs/content/benchmark_json.adoc deleted file mode 100644 index 9299091414..0000000000 --- a/assembler/ext/src/lexy/docs/content/benchmark_json.adoc +++ /dev/null @@ -1,165 +0,0 @@ -= JSON Validation Benchmark - -// This file is automatically generated by `lexy_benchmark_json`. -// DO NOT MODIFY. - -This benchmark measures the time it takes to *validate* JSON, i.e. to check whether it is well-formed. -Validation was chosen as opposed to parsing, as parsing speed depends on the JSON data structure as well. -Implementing an efficient JSON container is out of scope for lexy, so it would have a disadvantage over the specialized JSON libraries. - -The average validation times for each input are shown in the boxplots below. -Lower values are better. - -[pass] -++++ - -++++ - - -[pass] -++++ -
- -++++ - -[pass] -++++ -
- -++++ - -[pass] -++++ -
- -++++ - -.The implementations -`baseline`:: - This simply adds all input characters of the JSON document without performing actual validation. -`lexy`:: - A JSON validator using the lexy grammar from the example. -`pegtl`:: - A JSON validator using the https://github.com/taocpp/PEGTL[PEGTL] JSON grammar. -`nlohmann/json`:: - A JSON validator using https://github.com/nlohmann/json[JSON for Modern C++] implemented by `nlohmann::json::accept()`. -`rapidjson`:: - A JSON validator using https://github.com/Tencent/rapidjson[rapidjson] implemented using a SAX parser with the `rapidjson::BaseReaderHandler`. -`Boost.JSON`:: - A JSON validator using https://github.com/boostorg/json[Boost.JSON] implemented using a custom parse handler. - -.The inputs -`canada.json`:: - Contains lots of 2-element arrays holding floating-point coordinate pairs. - Taken from https://github.com/miloyip/nativejson-benchmark. -`citm_catalog.json`:: - Big JSON file with some variety. - Taken from https://github.com/miloyip/nativejson-benchmark. -`twitter.json`:: - Some data from twitter's API. - Taken from https://github.com/miloyip/nativejson-benchmark. - -.The Methodology -The input data is read using `lexy::read_file()`. -The resulting buffer is then passed to the various implementations using their memory inputs. -Benchmarking is done by https://nanobench.ankerl.com/[nanobench] on an AMD FX-6300. - \ No newline at end of file diff --git a/assembler/ext/src/lexy/docs/content/download/_index.adoc b/assembler/ext/src/lexy/docs/content/download/_index.adoc deleted file mode 100644 index 07945c15d3..0000000000 --- a/assembler/ext/src/lexy/docs/content/download/_index.adoc +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Download -layout: single -menu: - main: - name: "Download" - weight: 4 ---- - -For build instructions, read link:{{< ref "learn/build" >}}[the tutorial]. - -{{% download_list %}} - diff --git a/assembler/ext/src/lexy/docs/content/learn/_index.adoc b/assembler/ext/src/lexy/docs/content/learn/_index.adoc deleted file mode 100644 index 525469ee1c..0000000000 --- a/assembler/ext/src/lexy/docs/content/learn/_index.adoc +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: single -title: Learn -menu: - main: - name: "Learn" - weight: 1 ---- - -New to lexy? Start here. - -## Getting started - -1. link:{{< ref "learn/build" >}}[Building lexy and integrating it in your own projects] -2. link:{{< ref "learn/warmup" >}}[Warming up -- the first parser] -3. link:{{< ref "learn/branching" >}}[Branching, backtracking and making decisions -- lexy is not declarative] -4. link:{{< ref "learn/walkthrough" >}}[Walkthrough -- parser for custom package format] - -## Development - -* link:{{< ref "learn/changelog" >}}[Changelog] -* link:{{< ref "learn/versioning" >}}[Versioning and compatibility policy] - -## Need more help? - -Please look at https://github.com/foonathan/lexy/discussions/categories/q-a[previous questions] or https://github.com/foonathan/lexy/discussions/new[ask a new one]. - diff --git a/assembler/ext/src/lexy/docs/content/learn/branching.adoc b/assembler/ext/src/lexy/docs/content/learn/branching.adoc deleted file mode 100644 index fe341a157a..0000000000 --- a/assembler/ext/src/lexy/docs/content/learn/branching.adoc +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: Branching, backtracking and making decisions — lexy is not declarative ---- -:toc: left - -While lexy's DSL can look similar to formal grammars such as EBNF or regex, it is not actually comparable. -Traditional grammars describe _what_ valid input looks like, lexy's DSL describes _how_ input is parsed. -That way, you have full control over all backtracking that happens during parsing. - -== lexy is not declarative - -To illustrate the difference, consider the regex `a|ab`, which matches `a` or `ab`. -Writing the same rule in lexy using the {{% docref "LEXY_LIT" %}} primitive rule and the {{% docref choice %}} combinator, results in this: - -{{% playground-example choice_bad "Attempt to match `a` or `ab`" %}} - -However, as you will see when you try the example on the playground, it never actually matches `ab`, only `a`! - -The reason for this is simple: in lexy, choice `lhs | rhs` is essentially syntax sugar for code like this: - -```cpp -if (match(lhs)) - consume(lhs); -else if (match(rhs)) - consume(rhs); -else - error(); -``` - -In other words, choice attempts to match each rule in the order they were specified in. -As `a` matches on `ab`, it will always take the first branch without considering `ab`. -The correct way to write it would thus be `LEXY_LIT("ab") | LEXY_LIT("a")`. - -**** -Alternatively, in this particular case of matching one of multiple literals, -you can also use {{% docref "lexy::dsl::literal_set" %}}. -This rule tries to find the longest literal that matches. -**** - -Likewise, translating the regex `a*a`, which matches arbitrary many `a`s and then one additional one (i.e. `a`, `aa`, `aaa`, ...), using {{% docref "lexy::dsl::while_" %}} directly, doesn't work either: - -{{% playground-example while_bad "Attempt to match `a*a`" %}} - -Again, `while_()` does what it says in the name: it attempts to match the rule as often as possible and only stops matching when that isn't possible anymore. -However, this means the last `dsl::lit_c<'a'>` can never succeed. - -```cpp -while (match('a')) - consume('a'); -match_and_consume('a'); // can never succeed -``` - -This behavior is a good thing, as it gives you full control over the parsing algorithm. -While a naive regex engine might need to resort to backtracking to match `a*a`, lexy will only backtrack if you've instructed it to. - -The DSL is just syntax sugar for a hand-written parser. - -== Decisions are made using branches - -Both {{% docref choice %}} and {{% docref "lexy::dsl::while_" %}} need to make a decision during parsing (which alternative to parse/should I parse another iteration?). -A simple way to make a decision is to just guess one, see what happens, and backtrack when it didn't work out. -However, lexy does not do implicit backtracking. - -Instead, all rules that make decision require {{% branch-rule %}}s: -special rules where it can be easily checked whether or not they match at an input. -Those include: - -* {{% token-rule %}}s such as {{% docref "lexy::dsl::lit" %}}, {{% docref "lexy::dsl::ascii::alpha" %}}, {{% docref "lexy::dsl::digits" %}} (i.e. one token lookahead) -* branch conditions such as {{% docref "lexy::dsl::peek" %}}, {{% docref "lexy::dsl::else_" %}} -* the branch combinator {{% docref "lexy::dsl::operator>>" %}} - -So the choice above `LEXY_LIT("ab") | LEXY_LIT("a")` compiled because both alternatives are literal rules, which can be efficiently checked. -However, if we were to match between more complex alternatives, we need to manually specify how lexy should make a decision. - -Let's extend our previous color parser to also allow the function call syntax `rgb(255,0,255)`: - -```cpp -struct channel_hex { … }; <1> - -struct channel_dec -{ - static constexpr auto rule = dsl::integer; <2> -}; - -struct color -{ - static constexpr auto rule = []{ - auto hex_color = dsl::hash_sign + dsl::times<3>(dsl::p); <3> - - auto dec_channels = dsl::times<3>(dsl::p, dsl::sep(dsl::comma)); <4> - auto fnc_color = LEXY_LIT("rgb") + dsl::parenthesized(dec_channels); <5> - - return hex_color | fnc_color; <6> - }(); -}; -``` -<1> We've renamed the old `channel` to `channel_hex`. -<2> A decimal channel just parses an integer, the default matcher for {{% docref "lexy::dsl::integer" %}} is {{% docref "lexy::dsl::digits" %}}, which defaults to decimal. -<3> The hex rule, as before. -<4> We want three decimal channels, but separated by comma, which is specified in the second argument to {{% docref "lexy::dsl::times" %}}. -<5> We want to parse `rgb` followed by the parenthesized decimal channels, which can be easily done using {{% docref "lexy::dsl::parenthesized" %}}. -<6> We want to match either a hex color or a function call color, but this doesn't compile. - -This code doesn't compile, because the alternatives of a choice aren't branch rules: -lexy has no idea how it should make a decision between them. -As such, we need to manually tell it by using the branch combinator {{% docref "lexy::dsl::operator>>" %}}: -its left-hand side is an existing branch rule, and the right-hand side an arbitrary rule. -The result is a branch rule that will use the LHS to make a decision about whether the branch is taken. - -In our case, we want to match a hex color when we see a hash sign, and a function call color when we see the literal `rgb`: - -{{% playground-example color_function "Parse a hex color or function call color" %}} - -Note that in a lucky coincidence of operator precedence, the syntax `condition1 >> rule1a + rule 1b | condition2 >> rule2a + rule2b | ...` has exactly the semantics we want here. - -Also note that once a decision to take a branch has been made using the branch condition, lexy will never backtrack again -- even if the branch later fails. -For example, consider a call to `dsl::while_(LEXY_LIT("a") >> LEXY_LIT("b") + LEXY_LIT("c"))`. -We've instructed lexy to try another iteration when it sees an `a`: it doesn't matter what comes after it. - -[source] ----- -abcabcabd -^ start, try to match the condition - -abcabcabd --^ condition matched, we take the branch - -abcabcabd ----^ branch matched, try to match condition of the next iteration - -abcabcabd -----^ condition matched, we take the branch - -abcabcabd -------^ branch matched, try to match condition of the next iteration - -abcabcabd --------^ condition matched, we take the branch - -abcabcabd ---------^ error: expected `c` not `d`, however we no longer bracktrack! ----- - -== Convenience rules to get automatic branch conditions - -Specifying a branch condition every time lexy needs to make a decision, can be pretty annoying. -Luckily, there are many situations where that isn't necessary: - -* {{% docref "lexy::dsl::p" %}} is a branch condition if the rule of the production is a branch. - In that case, it is convenient to specify a condition in the rule of a production. - link:/playground?example=choice_production[Try it online]. -* {{% docref "lexy::dsl::else_" %}} is a branch condition that is always taken. - As such, if you have a choice between `N` alternatives, you only need to provide conditions for `N - 1`, and can use `else_ >>` for the last one. - However, it needs to be the last alternative listed in the choice, as branches are tried in order! -* {{% docref "lexy::dsl::list" %}} parses a list of things and just like {{% docref "lexy::dsl::while_" %}} requires a branch condition. - However, when you're parsing a list of things with a mandatory separator like a comma between them, it doesn't actually require one: - after parsing the mandatory first item, if the next thing is a separator, lexy knows that it needs to parse another item. -* Often, a list of things is surrounded and/or terminated by some specific token. - For example, arguments in a function call are surrounded by parenthesis, so we can decide whether we want another argument by checking whether we've reached the closing parenthesis. - In lexy, this can be accomplished by specifying your own {{% docref "lexy::dsl::brackets" %}} or {{% docref "lexy::dsl::terminator" %}}, - or using existing one like {{% docref "lexy::dsl::parenthesized" %}}. - As a bonus, you get really sophisticated error recovery for free. - link:/playground?example=parenthesized[Try it online]. -* {{% docref "lexy::dsl::delimited" %}} parses a string literal surrounded by the given delimiters. - It automatically takes care of checking the closing delimiter for you. - -Of course, sometimes you need to specify your own branch condition and there isn't a single token you can use to make a decision. -Then you can use backtracking using {{% docref "lexy::dsl::peek" %}} or {{% docref "lexy::dsl::lookahead" %}}, -which look at the next input and decide about taking a branch without consuming anything. - -{{% playground-example peek "Peek ahead to see whether we have a number" %}} - diff --git a/assembler/ext/src/lexy/docs/content/learn/build.adoc b/assembler/ext/src/lexy/docs/content/learn/build.adoc deleted file mode 100644 index b407c0b8c1..0000000000 --- a/assembler/ext/src/lexy/docs/content/learn/build.adoc +++ /dev/null @@ -1,154 +0,0 @@ ---- -title: Building lexy and integrating it in your own projects ---- -:toc: left -:toclevels: 1 - -The library uses CMake (3.8 or higher) as its build system. -It requires a compiler that supports {cpp}17, but works best with {cpp}20. -It is tested with GCC 7 and higher, clang 6 and higher, the latest MSVC and clang-cl. -Other compilers may work as well. - -== Basic integration - -The recommended way to integrate lexy is using https://cmake.org/cmake/help/latest/module/FetchContent.html[`FetchContent`]. -This will automatically download the library and make it available in your CMake project. - -```cmake -include(FetchContent) -FetchContent_Declare(lexy URL https://lexy.foonathan.net/download/lexy-src.zip) -FetchContent_MakeAvailable(lexy) -``` - -lexy will detect when it is used via `FetchContent` (or `add_subdirectory`) and automatically disable project infrastructure like tests or examples. -It exposes the following targets: - -`foonathan::lexy::core` (header-only):: - lexy's core library; it is required. - It is an `INTERFACE` target that sets the required include path and {cpp} standard flags. -`foonathan::lexy::file` (library):: - Link to this library if you want to use {{% docref "lexy::read_file" %}} and other file I/O functions. -`foonathan::lexy::unicode` (header-only):: - Link to this library if you want to use advanced Unicode rules that require the Unicode character database. -`foonathan::lexy::ext` (header-only):: - Link to this library if you want to use the extension headers in `lexy_ext/`. -`foonathan::lexy` (library):: - Umbrella target that links to all other targets. - -A minimal `CMakeLists.txt` that uses lexy can look like this: - -.`CMakeLists.txt` -```cmake -project(lexy-example) - -include(FetchContent) -FetchContent_Declare(lexy URL https://lexy.foonathan.net/download/lexy-src.zip) -FetchContent_MakeAvailable(lexy) - -add_executable(lexy_example) -target_sources(lexy_example PRIVATE main.cpp) -target_link_libraries(lexy_example PRIVATE foonathan::lexy) -``` - -== Configuration - -lexy can be customized by two CMake flags set at build time: - -`LEXY_FORCE_CPP17`:: - If this option is `ON`, linking against `foonathan::lexy::core` (and transitively also `foonathan::lexy`) sets the flag to enable {cpp}17 for all compilers. - If this option is `OFF`, linking enables {cpp}20 for compilers that support it and {cpp}17 otherwise. - It is `OFF` by default. -`LEXY_USER_CONFIG_HEADER`:: - This setting defines the file path to the user config header file (see below). - -All other configuration happens via the user config header, which is a user-written file that can be used to override many of the automatic compiler detections. -If `LEXY_USER_CONFIG_HEADER` is set, it will use the specified header; otherwise, looks for a header file named `lexy_user_config.hpp` somewhere in the include search path. -This header is then automatically included by lexy and can define macros to customize lexy. -Those are: - -`LEXY_ENCODING_OF_CHAR`:: - The encoding that lexy will deduce for `char` strings. - By default, it is {{% docref "lexy::default_encoding" %}}, which means any 8bit encoding. - It can be overridden to {{% docref "lexy::ascii_encoding" %}} or {{% docref "lexy::utf8_encoding" %}}. -`LEXY_ENABLE_ASSERT`:: - Whether or not internal assertions and precondition checks are enabled. - By default, they are enabled unless `NDEBUG` is defined. -`LEXY_HAS_NTTP`:: - Whether or not the compiler supports {cpp}20's generalized non-type template parameters. -`LEXY_HAS_CONSTEVAL`:: - Whether or not the compiler supports `consteval`. -`LEXY_HAS_CHAR8_t`:: - Whether or not the compiler supports `char8_t`. -`LEXY_IS_LITTLE_ENDIAN`:: - Whether or not the native endianness is little endian. -`LEXY_FORCE_INLINE`:: - The compiler specific attribute to force inlining. -`LEXY_EMPTY_MEMBER`:: - The compiler specific attribute for `[[no_unique_address]]`. - -== Development build - -To contribute to lexy, you don't want to use it as a subdirectory as that disables most targets. -Instead, clone the project normally and use CMake directly (i.e. `cmake -S /path/to/lexy -B /path/to/build`). -This requires at least CMake 3.18. - -=== Development target - -The special target `foonathan::lexy::dev` can be used instead of `foonathan::lexy::core`. -It will enable the relevant compiler warnings inside the lexy headers. -Link against it in any examples or tests. - -NOTE: It is not part of the umbrella target `foonathan::lexy`. - -=== Examples - -Examples are only available if `LEXY_BUILD_EXAMPLES` is `ON` (the default). -Each example has its own target, e.g. `lexy_example_calculator`. - -=== Tests - -Tests are only available if `LEXY_BUILD_TESTS` is `ON` (the default). -It will automatically fetch doctest and `enable_testing()`. - -The following test targets are available: - -`lexy_test`:: - Tests for all headers in `lexy/`. -`lexy_ext_test`:: - Tests for all headers in `lexy_ext/`. -`lexy_test_XXX`:: - Tests for example `XXX`. -`lexy_test_playground`, `lexy_test_godbolt`, `lexy_test_godbolt_examples`, `lexy_test_playground_examples`:: - Compile-only targets that ensure the examples of the documentation all compile. - -The minimal workflow to build lexy and run all tests is: - -``` -cmake -S /path/to/lexy -B /path/to/build -cd /path/to/build -cmake --build . -ctest -``` - -=== Benchmarks - -Benchmarks are only available if `LEXY_BUILD_BENCHMARKS` is `ON` (not the default). -It will automatically fetch nanobench and necessary data files. -Refer to the `benchmarks/` folder for details. - -=== Docs - -Docs can only be built if `LEXY_BUILD_DOCS` is `ON` (not the default). -It requires that you have installed https://gohugo.io/[hugo], https://asciidoctor.org/[Asciidoctor], and https://github.com/pygments/pygments.rb[pygments.rb]. -Docs can be build by two targets: - -`lexy_docs_serve`:: - This will compile the docs and serve the website on localhost. -`lexy_docs`:: - This will compile the docs into `docs/public`. - -=== Packaging - -lexy also exposes a custom target `lexy_package`. -It will create a file `lexy-src.zip` in the build directory containing all source files necessary for downstream users to use lexy. - diff --git a/assembler/ext/src/lexy/docs/content/learn/versioning.adoc b/assembler/ext/src/lexy/docs/content/learn/versioning.adoc deleted file mode 100644 index 924998674b..0000000000 --- a/assembler/ext/src/lexy/docs/content/learn/versioning.adoc +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Versioning and compatibility policy ---- - -lexy uses https://calver.org[calender versioning] according to the following schema: - -``` -YYYY.MM.N[-beta] -``` - -* `YYYY.MM` the year and month of the release for `N = 0`. -* `N` the minor/patch number of the release. -* `-beta` suffix indicating a beta release. - -== Major releases - -A major release is released when enough features have accumulated, but at least once for each new Unicode version. -We promise: - -* No change in semantics of existing functionality. - In particular, all DSL rules will continue to accept the same input as they have in the previous version, and produce the same values. - This does _not_ apply to the behavior on invalid input, see below. -* No removal of functionality unless it has been deprecated in a previous major release. -* No build breaking changes: whenever possible, we will add an alternative with a different spelling and deprecate the previous version instead. - -We reserve the right to: - -* Deprecate existing functionality and remove previously deprecated functionality. -* Change anything that is not documented. - In particular, writing custom rules, readers, or parse actions is not guaranteed to work across major releases. -* Change everything about the extension headers. -* Change the behavior of rules on invalid input. - This includes generated error messages and error recovery. - We reserve the right to add error recovery to rules that currently do not have error recovery, - remove error recovery of existing rules, or change error recovery. - What is considered invalid input does not change, however. -* Change the ABI. -* Add new functionality, change the signature of existing functions (in an API compatible way), change transitive includes and implementation details. - -== Minor releases - -A minor (or patch) release is done to fix bugs or improve existing functionality. -It increments `N` but leaves `YYYY.MM` unchanged, even if released in a different month. -Minor releases are fully API and ABI compatible. - -We will only add minor releases to the latest major release and do not support multiple major releases at the same time. - -== Beta release - -We can do a beta release of any major or minor release first. -We reserve the right to make any changes between the beta release and the final release for new functionality introduced in the beta release. -Stability guarantees for existing functionality still applies. - diff --git a/assembler/ext/src/lexy/docs/content/learn/walkthrough.adoc b/assembler/ext/src/lexy/docs/content/learn/walkthrough.adoc deleted file mode 100644 index cd07ff5322..0000000000 --- a/assembler/ext/src/lexy/docs/content/learn/walkthrough.adoc +++ /dev/null @@ -1,703 +0,0 @@ ---- -title: Walkthrough — parser for custom package format ---- -:toc: left -:toclevels: 1 - -Let's apply everything to a more complex example. -Our goal is to parse some simple configuration file of a software package. - -A sample input file can look like this: - -.`package.config` ----- -name = lexy -version = 0.0.0 -authors = ["Jonathan Müller"] ----- - -And we want to parse it into the following C++ data structure using `lexy`: - -.`PackageConfig` -[source,cpp] ----- -struct PackageVersion -{ - int major; - int minor; - int patch; -}; - -struct PackageConfig -{ - std::string name; - PackageVersion version; - std::vector authors; -}; ----- - -The full source code can be found at {{< github-example config >}}. - -Following the three steps outlined in the {{< ref "learn/warmup" >}}[warmup], our program has the following structure: - -[source,cpp] ----- -#include -#include - -<1> -struct PackageVersion { … }; -struct PackageConfig { … }; - -//=== grammar ===// -#include -#include - -namespace grammar <2> -{ - namespace dsl = lexy::dsl; - - … - - struct config { … }; -} - -//=== parsing ===// -#include -#include -#include - -int main() -{ - auto file = lexy::read_file(filename); <3> - if (!file) - { … } - - auto result = lexy::parse(file.buffer(), lexy_ext::report_error); <4> - if (!result) <5> - { … } - - if (result.has_value()) <6> - { - PackageConfig config = result.value(); - … - } -} ----- -<1> The user code that defines the C++ data structures. - It does not need to know anything about `lexy`. -<2> The grammar. It contains multiple productions, but the entry production is `grammar::config`. - This is the production we're parsing. -<3> We want to read the config from a file, so we use {{% docref "lexy::read_file" %}}. - We specify that the file uses UTF-8 as the input encoding. - Reading a file can fail, so we need to handle that (not shown here). -<4> Then we can parse our entry production using the action {{% docref "lexy::parse" %}}. - We give it the buffer of our file and a callback to invoke on errors. -<5> If parsing produced any errors, handle them somehow. -<6> If parsing was able to give as a value (i.e. the input was either well-formed or lexy could recover from all errors that happened), - use that value. - If you don't care about error recovery, you just need the `!result` check. - -== Parsing the package name - -We will create a separate production for each of the fields (name, version, authors). -Let's start with the production for the name, as that is the simplest one. - -.Package name ----- -name = lexy ----- - -Here, we're only concerned with the part after the equal sign, so the `lexy` in the example above. -A package name follows the same rules as a C++ identifier, except that leading underscores are not allowed. -As a regex, a name is described by `[a-zA-Z][a-zA-Z_0-9]*`, so one alpha character, followed by zero or more alphanumeric characters or underscores. - -In lexy, we can use the pre-defined {{% char-class-rule %}}s {{% docref "lexy::dsl::ascii::alpha" %}} and {{% docref "lexy::dsl::ascii::word" %}}. -We can then combine them in {{% docref sequence %}} with a {{% docref "lexy::dsl::while_" %}} rule: - -```cpp -struct name -{ - static constexpr auto rule = dsl::ascii::alpha + dsl::while_(dsl::ascii::word); -}; -``` - -However, this doesn't produce a value; we need to wrap everything in the {{% docref "lexy::dsl::capture" %}} rule, -which matches something and produces a {{% docref "lexy::lexeme" %}} (think string view) over the part of the input that was consumed by it. -But this specific pattern is so common that lexy provides a built-in rule for it {{% docref "lexy::dsl::identifier" %}}: - -```cpp -struct name -{ - static constexpr auto rule = [] { - auto lead_char = dsl::ascii::alpha; - auto trailing_char = dsl::ascii::word; - return dsl::identifier(lead_char, trailing_char); <1> - }(); - - static constexpr auto value = lexy::as_string; <2> -}; -``` -<1> Match an identifier whose leading char is `dsl::ascii::alpha` and all trailing chars are `dsl::ascii::word`. - Everything consumed is captured. -<2> Convert the captured lexeme into a `std::string` using the callback {{% docref "lexy::as_string" %}}. - -First field done, let's move on to the next one. - -== Parsing the package version - -The next field is the version. - -.Package version ----- -version = 0.0.0 ----- - -Again, we're only concerned with the value after the equal sign for now. -It consists of three numbers separated by dots, where a number is a non-empty sequence of digits. - -We can parse decimal numbers using {{% docref "lexy::dsl::integer" %}}, and as we've seen {{% docref "lexy::dsl::times" %}} can parse something `N` times with an optional separator: - -[source,cpp] ----- -struct version -{ - static constexpr auto rule = []{ - auto number = dsl::integer; - auto dot = dsl::period; - return dsl::times<3>(number, dsl::sep(dot)); - }(); - - static constexpr auto value = lexy::construct; -}; ----- - -Let's also allow the special value `unreleased` as an alternate spelling for `0.0.0`. -For that, we need to use a {{% docref choice %}} between the previous `dsl::times` rule and {{% docref "LEXY_LIT" %}}`("unreleased")`. -As discussed in the {{< ref "learn/branching" >}}[branching tutorial], we need to use {{% branch-rule %}}s to let lexy know how to make a decision. -Luckily, `LEXY_LIT` is already a branch rule, so we can turn the number part into one by using {{% docref "lexy::dsl::else_" %}}: - -[source,cpp] ----- -struct version -{ - static constexpr auto rule = []{ - auto number = dsl::integer; - auto dot = dsl::period; - auto dot_version = dsl::times<3>(number, dsl::sep(dot)); - - auto unreleased = LEXY_LIT("unreleased"); - - return unreleased | dsl::else_ >> dot_version; <1> - }(); - - static constexpr auto value = lexy::construct; <2> -}; ----- -<1> We're trying to match the literal `unreleased`, if that doesn't work, we unconditionally parse a dotted version. -<2> If we're matching `unreleased`, no value is produced. - However, in that case {{% docref "lexy::construct" %}} will value construct a `PackageVersion`, which produces `{0, 0, 0}` anyway, - which is actually what we want. - To get a different value, we either need to write our own overloaded callback using {{% docref "lexy::callback" %}}, - or by using {{% docref "lexy::bind" %}}. - -Alternatively, we could have turned `dot_version` into a branch by adding a condition that checks for a digit using {{% docref "lexy::dsl::digit" %}}, -and wrapping it in {{% docref "lexy::dsl::peek" %}} to ensure the digit is not consumed. - -== Parsing the package author - -Continuing on, we want to parse the author of the package: - -.Package author ----- -authors = ["Jonathan Müller"] ----- - -It is a comma-separated list of strings surrounded by square brackets. - -We could manually build something that parses a string by using {{% docref "lexy::dsl::while_" %}} and {{% docref "lexy::dsl::capture" %}} again; -we just need to be careful to match string characters that are not quotes. -However, again lexy provides built-in support in the form of {{% docref "lexy::dsl::delimited" %}}, which parses zero or more occurrences of a char class surrounded by a specified delimiter. -As we want quotation marks, we can use {{% docref "lexy::dsl::quoted" %}} directly: - -[source,cpp] ----- -struct author <1> -{ - static constexpr auto rule = dsl::quoted(dsl::code_point); <2> - - static constexpr auto value = lexy::as_string; <3> -}; ----- -<1> The production that parses a single author. -<2> Parse a string literal that contains arbitrary characters using {{% docref "lexy::dsl::code_point" %}}. -<3> Convert it into a `std::string` using {{% docref "lexy::as_string" %}}. - Note that the callback is used as a {{% docref sink %}} here: - it will be repeatedly invoked to accumulate each character of the string. - -This works, but we need to make two improvements. -First, we don't want control characters such as newline in our string. -For that, we can subtract the char class {{% docref "lexy::dsl::ascii::control" %}} from `dsl::code_point`, -or, as that is the default, just use {{% docref "lexy::dsl::operator- (unary)" %}}. -Second, we have no way to embed quotes in the author's name, as they terminate the string. -This can be solved by adding escape sequences, which {{% docref "lexy::dsl::delimited" %}} supports out-of-the box: - -[source,cpp] ----- -struct author -{ - static constexpr auto rule = [] { - auto cp = -dsl::ascii::control; <1> - auto escape = dsl::backslash_escape <2> - .rule(dsl::lit_c<'u'> >> dsl::code_point_id<4>) <3> - .rule(dsl::lit_c<'U'> >> dsl::code_point_id<8>); - - return dsl::quoted(cp, escape); <4> - }(); - - static constexpr auto value = lexy::as_string; <5> -}; ----- -<1> Allow anything that is not a control character. -<2> We use `\` as the escape character using {{% docref "lexy::dsl::backslash_escape" %}}, - which is just an alias for {{% docref "lexy::dsl::escape" %}} using a backslah. -<3> These two lines define `\uXXXX` and `\uXXXXXXXX` to specify character codes. - {{% docref "lexy::dsl::code_point_id" %}} is a convenience alias for {{% docref "lexy::dsl::integer" %}} - which parses a code point using `N` hex digits. -<4> The `\u` and `\U` rules all produce a {{% docref "lexy::code_point" %}}. - `lexy::as_string` can only convert it back into a string, if we tell it the encoding we want. - So we add `lexy::utf8_encoding` as the second optional argument to enable that. - -The traditional escape sequences such as `\"`, `\n`, and so on, can be implemented by providing a {{% docref "lexy::symbol_table" %}} that defines a mapping for escape characters to their replacement value. -See {{< github-example json >}} for an example. - -Now we just need to parse a list of authors. -{{% docref "lexy::dsl::list" %}} can be used like that: -it parses the item once and then as often as it matches. -But unlike {{% docref "lexy::dsl::while_" %}} it allows the item to produce a value and will collect them all in a {{% docref sink %}} like {{% docref "lexy::as_list" %}}. -Like {{% docref "lexy::dsl::times" %}}, we can also specify a separator, in which case item does not need to be {{% branch-rule %}} as lexy can make a decision just based on the existence of a separator. - -However, as the list here is surrounded by square brackets, we can use `.list()` of {{% docref "lexy::dsl::square_bracketed" %}} instead. -It is a special case of the generic {{% docref "lexy::dsl::brackets" %}}, which in turn is a wrapper over {{% docref "lexy::dsl::terminator" %}}. -As discussed in the {{< ref "learn/branching" >}}[tutorial about branching], they allow parsing things without requiring a branch condition. - -[source,cpp] ----- -struct author_list -{ - static constexpr auto rule - = dsl::square_bracketed.list(dsl::p, dsl::sep(dsl::comma)); <1> - - static constexpr auto value = lexy::as_list>; <2> -}; ----- -<1> Parse the comma-separated list of authors surrounded by square brackets. -<2> Each call to {{% docref "lexy::dsl::p" %}} produces a `std::string`, the sink {{% docref "lexy::as_list" %}} collects them all into the specified container. - -== Putting it together - -Parsing the entire config is now very straightforward: - -[source,cpp] ----- -struct config -{ - static constexpr auto rule = []{ - auto make_field = [](auto name, auto rule) { <1> - return name + dsl::lit_c<'='> + rule + dsl::newline; <2> - }; - - auto name_field = make_field(LEXY_LIT("name"), dsl::p); <3> - auto version_field = make_field(LEXY_LIT("version"), dsl::p); - auto authors_field - = make_field(LEXY_LIT("authors"), dsl::p); - - return name_field + version_field + authors_field; <4> - }(); - - static constexpr auto value = lexy::construct; <5> -}; ----- -<1> We define a little helper function that builds a rule that parses a field given its name and value. -<2> Each field consists of the name, an equal sign, the value rule, and a newline matched by the {{% docref "lexy::dsl::newline" %}} token. -<3> Define each field using the productions we've built above. -<4> Match them all in order. -<5> Construct the package config from the resulting `std::string`, `PackageVersion` and `std::vector`. - -This works! - -We can now almost parse the sample input I've given above: - -.`package.config` ----- -name=lexy -version=0.0.0 -authors=["Jonathan Müller"] ----- - -We don't support whitespace between the elements. -We want to support ASCII blank characters (space and tab) surrounding the equal sign and the brackets and comma of the author list. -This can be done either manually or automatically. - -To parse whitespace manually, we can use {{% docref "lexy::dsl::whitespace" %}}. -It behaves like {{% docref "lexy::dsl::while_" %}} and parses a specified rule zero or more times, but treats the matched content as whitespace. -We then need to insert it everywhere we want to skip whitespace: - -[source,cpp] ----- -constexpr auto ws = dsl::whitespace(dsl::ascii::blank). <1> - -struct config -{ - static constexpr auto rule = []{ - auto make_field = [](auto name, auto rule) { - return name + ws + dsl::lit_c<'='> + ws + rule + ws + dsl::newline; <2> - }; - - … - }(); -}; - -… ----- -<1> Define the whitespace globally. {{% docref "lexy::dsl::ascii::blank" %}} is a char class that matches space or tab. -<2> Insert it everywhere we want to allow whitespace. - -However, this is a lot of work. -In this particular case, it is easier to use {{% docref "whitespace" "automatic whitespace skipping" %}}. -This is done by adding a `static constexpr` member called `whitespace` to the root production: - -[source,cpp] ----- -struct config -{ - static constexpr auto whitespace = dsl::ascii::blank; <1> - - static constexpr auto rule = [] { … } (); <2> - static constexpr auto value = lexy::construct; -}; ----- -<1> Define what whitespace is for our grammar. -<2> Nothing needs to change in any of the rules here! - -That is all! Now lexy will automatically skip whitespace after every {{% token-rule %}} in the grammar. - -However, that can be a bit much. -For example, it will now skip whitespace after each component of the version number, so something like `version = 0 . 0 . 0` is fine. -There are to ways to prevent that. -The first is to use {{% docref "lexy::dsl::no_whitespace" %}} which parses a rule but disables whitespace skipping. -This is used internally by {{% docref "lexy::dsl::identifier" %}} and {{% docref "lexy::dsl::delimited" %}}, so those cases are fine. -The second is to have the `version` production inherit {{% docref "lexy::token_production" %}}. -This instructs lexy to treat the entire production as a token for the purposes of whitespace skipping: -it will not skip whitespace while parsing the production and all child productions, but instead only once when it's done: - -[source,cpp] ----- -struct version : lexy::token_production <1> -{ - … -}; ----- -<1> Disable automatic whitespace skipping inside the `version`. - -Now we can parse the input shown in the beginning! - -== Polish: Arbitrary ordering of fields - -To make usability nicer, let's support arbitrary ordering of the fields in our config file. -This can be done using {{% docref "lexy::dsl::combination" %}}, which parses each rule specified once, but in arbitrary order. -The values produced during parsing are not passed to a callback, as that will require `N!` overloads, but instead it uses a sink. -That's a problem though: how can we know which value should be assigned to which field? - -The solution is to use the {{% docref "lexy::as_aggregate" %}} callback together with {{% docref "LEXY_MEM" %}}. -Using `LEXY_MEM(name) = rule` in the DSL assigns the value of `rule` to the member `name`, -`lexy::as_aggregate` then constructs `T` by collecting the values of all members: - -[source,cpp] ----- -struct config -{ - static constexpr auto whitespace = dsl::ascii::blank; - - static constexpr auto rule = [] { - auto make_field = [](auto name, auto rule) { - return name >> dsl::lit_c<'='> + rule + dsl::newline; <1> - }; - - auto name_field = make_field(LEXY_LIT("name"), LEXY_MEM(name) = dsl::p); <2> - auto version_field - = make_field(LEXY_LIT("version"), LEXY_MEM(version) = dsl::p); - auto authors_field - = make_field(LEXY_LIT("authors"), LEXY_MEM(authors) = dsl::p); - - return dsl::combination(name_field, version_field, authors_field) + dsl::eof; <3> - }(); - - static constexpr auto value = lexy::as_aggregate; <4> -}; ----- -<1> {{% docref "lexy::dsl::combination" %}} requires a {{% branch-rule %}} to know which rule to parse. - Luckily, we can use the name of the field for that. -<2> Each rule now contains the assignment to the appropriate member using {{% docref "LEXY_MEM" %}}. -<3> Instead of a sequence, we now have `dsl::combination()`. - We also added {{% docref "lexy::dsl::eof" %}} to ensure that there are no trailing fields at the end. -<4> We use {{% docref "lexy::as_aggregate" %}} as our sink. - -This will match each field exactly once, but in any order. - -== Polish: Better error messages - -Out of the box, lexy already gives pretty good error messages. -The {{% docref "error callback" %}} passed to {{% docref "lexy::parse" %}} is invoked with some context information like the current production stored in {{% docref "lexy::error_context" %}} as well the actual {{% docref "lexy::error" %}}. -Using `lexy_ext::report_error`, they are then nicely formatted: - -.Name that starts with an underscore. ----- -error: while parsing name - | - 1: 8| name = _lexy - | ^ expected 'ASCII.alpha' character ----- - -.Missing version number ----- -error: while parsing version - | - 2:11| version = 0.0 - | ~~~^ expected '.' ----- - -.Author name not quoted. ----- -error: while parsing author_list - | - 3:12| authors = [Jonathan Müller] - | ^ expected '"' ----- - -=== More specific error messages - -However, some of the generic errors are a bit confusing for end users. -For example, if we have control characters in a string we just get a cryptic "expected complement char" error message, -as that's the error given by `-char`. -We can change the error of a {{% token-rule %}} using its {{% docref ".error" %}} member: - -[source,cpp] ----- -struct author -{ - struct invalid_character <1> - { - static constexpr auto name = "invalid string character"; <2> - }; - - static constexpr auto rule = [] { - auto cp = (-dsl::ascii::control).error; <3> - - … - }(); - - … -}; ----- -<1> The tag that will be associated with the error. -<2> We override the default message (which would be `author::invalid_character`) to the more friendly `invalid string character`. -<3> We specify that on token failure, we want an error with the given tag. - -Likewise, if we specify the same field twice we get the generic "combination duplicate" error message. -Additionally, if we add an unknown field we get the generic "exhausted choice" error. -Both issues can be improved by specifying custom tags in our {{% docref "lexy::dsl::combination" %}} call. - -[source,cpp] ----- -struct config -{ - struct unknown_field <1> - { - static constexpr auto name = "unknown config field"; <2> - }; - struct duplicate_field <1> - { - static constexpr auto name = "duplicate config field"; <2> - }; - - static constexpr auto rule = [] { - … - - auto combination = dsl::combination(name_field, version_field, authors_field) - .missing_error.duplicate_error; <3> - return combination + dsl::eof; - }(); -}; ----- -<1> Define the tags. -<2> Override the default message, which is the type name. -<3> Specify the error on failure. - The missing error is the one triggered when no field condition matched, the duplicate one if we had a field twice. - -Now an invalid string character is reported as `invalid string character` and a duplicated config field as `duplicate config field`: - -.Missing closing string delimiter ----- -error: while parsing author - | - 3:28| authors = ["Jonathan Müller] - | ~~~~~~~~~~~~~~~^ invalid string character ----- - -.Duplicate config field error ----- -error: while parsing config - | - 1: 1| name = lexy - | ^ beginning here - | - 3: 1| version = 0.0.0 - | ^^^^^^^^^^^^^^^ duplicate config field ----- - -=== Expecting common mistakes - -The package name must not contain hyphens as in `my-package`. -If a user attempts to use such a name, {{% docref "lexy::dsl::identifier" %}} stops parsing at the first hyphen, and the error is about an expected newline. -We can improve that by requiring that there is whitespace following the identifier. -If that is not the case, the identifier contains invalid characters. - -For that, we can use {{% docref "lexy::dsl::peek" %}}, which checks whether a rule would match at the current position, without consuming anything. -It also has a `.error` member that can be used to specify a custom tag: - -[source,cpp] ----- -struct name -{ - struct invalid_character <1> - { - static constexpr auto name = "invalid name character"; <2> - }; - - static constexpr auto rule = [] { - … - - return dsl::identifier(lead_char, trailing_char) - + dsl::peek(dsl::ascii::space).error; <3> - }(); -}; ----- -<1> Define a tag. -<2> Give it a custom message. -<3> Issue the error unless the name is followed by the required space character (either trailing whitespace or the newline). - -Now the error message tells exactly what is going on: - -.Invalid name character error ----- -error: while parsing name - | - 1:10| name = my-package - | ~~^ invalid name character ----- - -Likewise, we can use {{% docref "lexy::dsl::peek_not" %}}, which fails if a rule would match, if we were to specify a build string in our version: - -[source,cpp] ----- -struct version -{ - struct forbidden_build_string <1> - { - static constexpr auto name = "build string not supported"; <2> - }; - - static constexpr auto rule = [] { - … - - auto dot_version = dsl::times<3>(number, dsl::sep(dot)) - + dsl::peek_not(dsl::lit_c<'-'>).error; <3> - - … - }(); -}; ----- -<1> Define a tag. -<2> Give it a custom message. -<3> Raise the error when the beginning of a build string is encountered. - -.Forbidden build string ----- -error: while parsing version - | - 2:16| version = 0.0.0-alpha - | ~~~~~^ build string not supported ----- - -== Polish: Better error recovery - -lexy also provides error recovery out of the box. -For example, if we're missing a comma in our author list `["author 1" "author 2"]`, lexy will correctly report an error yet recovers and produces a list containing the two authors. -This is possible since we're using {{% docref "lexy::dsl::brackets" %}}, so it knows when the list is supposed to end. - -Yet there are more cases where we can recover, we just need to teach lexy about it. -This can be done using {{% docref "lexy::dsl::try_" %}}. -This rule parses a rule and on failure, attempts to recover by parsing an optional recovery rule. -Parsing can then continue. - -For example, consider the rule that parses a config field: - -[source,cpp] ----- -auto make_field = [](auto name, auto rule) { - return name >> dsl::lit_c<'='> + rule + dsl::newline; -}; ----- - -Note that the `=` sign between the name and the value is not required to be able to parse it; something like `version 1.0.0` is not ambiguous. -So instead of specifying `dsl::lit_c<'='>`, we can use `dsl::try_(dsl::lit_c<'='>)`: -this tries to parse an `=` sign and issues an error if there isn't one, but then it just continues as if nothing happens. -So `version 1.0.0` will lead to an error message complaining about the missing `=`, but still give you the appropriate config object. -Note that this is unlike {{% docref "lexy::dsl::if_" %}}`(dsl::lit_c<'='>)` which would not raise an error if there is no `=`, as there the `=` is optional. - -Also consider the case of `name = my-package` again. -We're correctly getting an error about the invalid character in the package name. -But as a failure on {{% docref "lexy::dsl::peek" %}} doesn't affect subsequent rules (it wouldn't have consumed anything anyway), -parsing continues and tries to parse {{% docref "lexy::dsl::newline" %}}, which then fails. -A recovery strategy would be to discard anything until you've reached the end of line: - -[source,cpp] ----- -auto make_field = [](auto name, auto rule) { - auto end = dsl::try_(dsl::newline, dsl::until(dsl::newline)); <1> - return name >> dsl::try_(dsl::lit_c<'='>) + rule + end; -}; ----- -<1> If we don't have a newline immediately, we discard everything until we have consumed one to recover. - When parsing continues, we're at the next line. - -Now parsing `name = my-package` will complain about the `-` in the name, a missing newline, but then recovers to produce a package called `my`. - -Another place were we can use recovery is a missing version number like `version = 1.0`. -For that, we wrap every number and period in `dsl::try_`: - -[source,cpp] ----- -struct version : lexy::token_production -{ - static constexpr auto rule = [] { - auto number = dsl::try_(dsl::integer, dsl::nullopt); <1> - auto dot = dsl::try_(dsl::period); <2> - auto dot_version = dsl::times<3>(number, dsl::sep(dot)) - + dsl::peek_not(dsl::lit_c<'-'>).error; - - … - }(); - - static constexpr auto value - = lexy::bind(lexy::construct, lexy::_1 or 0, lexy::_2 or 0, lexy::_3 or 0); <3> -}; ----- -<1> If we don't have an integer, we recover by parsing {{% docref "lexy::dsl::nullopt" %}} which just produces the tag value {{% docref "lexy::nullopt" %}}. -<2> If we don't have a dot, we do nothing. -<3> As we now recover from input like `1.0` by producing the values `1, 0, lexy::nullopt{}`, we need to ensure we're still producing a correct `PackageVersion`. - For that we use the {{% docref "lexy::bind" %}} callback, and specify that if any arguments are `lexy::nullopt`, we want `0` instead. - -Now we recover from version strings like `1.0` or `1..0`, where missing fields are treated as zeroes. - diff --git a/assembler/ext/src/lexy/docs/content/learn/warmup.adoc b/assembler/ext/src/lexy/docs/content/learn/warmup.adoc deleted file mode 100644 index a203587c77..0000000000 --- a/assembler/ext/src/lexy/docs/content/learn/warmup.adoc +++ /dev/null @@ -1,195 +0,0 @@ ---- -title: Warming up — the first parser ---- -:toc: left - -Using lexy takes three steps: - -1. Define the grammar. -2. Create an input. -3. Call a parse action. - -Let's apply it to parse HTML colors such as `#FF00FF` into the following struct: - -```cpp -struct Color -{ - std::uint8_t r, g, b; -}: -``` - -## 1. Define the grammar - -A _grammar_ consists of _productions_. -Each production defines a _rule_, which controls what is being parsed, and produces a _value_. -In lexy, productions are structs with a `static constexpr` member called `rule`. -The rule is defined by the DSL: lexy provides simple rules that can be composed to parse more complex things. -A grammar consists of multiple of those structs; it is recommended to put them all in a separate namespace: - -```cpp -#include <1> - -namespace grammar <2> -{ - namespace dsl = lexy::dsl; <3> - - struct color { … }; <4> -} -``` -<1> All DSL objects are defined in `lexy/dsl.hpp`. -<2> We use a designated namespace to define our grammar. -<3> For convenience, we alias the namespace of the DSL objects. -<4> Productions are structs. - -Let's start simple by parsing a single color channel, that is, two hex digits. -For that, there is the rule {{% docref "lexy::dsl::n_digits" %}}: -it parses `N` digits in the specified base. -As such, a production that parses two hex digits looks like so: - -```cpp -struct channel <1> -{ - static constexpr auto rule = dsl::n_digits<2, dsl::hex>; <2> -}; -``` -<1> We define a new production `channel`... -<2> ... that matches 2 hex digits. - -A color then consists of a hash sign followed by three channels. -A hash sign can be parsed by {{% docref "lexy::dsl::hash_sign" %}} (which is just a convenience alias for the general {{% docref "lexy::dsl::lit" %}} rule which parses a fixed string); -the channel can be parsed by {{% docref "lexy::dsl::p" %}}, which parses another production. -If we want to parse two or more rules in sequence we can use {{% docref "lexy::dsl::operator+" %}}: - -```cpp -struct color -{ - static constexpr auto rule = dsl::hash_sign + dsl::p + dsl::p + dsl::p; -}; -``` - -That's a lot of repetition, so we can use {{% docref "lexy::dsl::times" %}}, which parses another rule `N` times in sequence. -The grammar as written also allows arbitrary stuff after the last channel, such as `#FF00FF Hello World!`. -To prevent that, we need to match {{% docref "lexy::dsl::eof" %}} after the last channel, which only succeeds if we are at EOF. - -```cpp -struct color -{ - static constexpr auto rule = dsl::hash_sign + dsl::times<3>(dsl::p) + dsl::eof; -}; -``` - -Putting it together, we have a simple grammar that parses an HTML color. - -{{% playground-example color "Parse an HTML color" %}} - -## 2. Create an input - -You can't just directly parse something; you have to use one of the provided input classes. -They also take care of {{% encoding %}} if necessary. - -Strings ({{% docref "lexy::string_input" %}}):: -```cpp -#include - -auto literal = lexy::zstring_input("#FF00FF"); -auto str = lexy::string_input(some_string); -``` - -Files ({{% docref "lexy::read_file" %}}):: -```cpp -#include - -auto file = lexy::read_file(path); -if (!file) { … } -auto input = file.buffer(); -``` - -Command-line arguments ({{% docref "lexy::argv_input" %}}):: -```cpp -#include - -auto input = lexy::argv_input(argc, argv); -``` - -Iterator ranges ({{% docref "lexy::range_input" %}}):: -```cpp -#include - -auto input = lexy::range_input(begin, end); -``` - -## 3. Call a parse action - -Once you have defined a grammar and an input, you invoke an action that reads the input and processes it according to the grammar. - -The simplest action is {{% docref "lexy::match" %}}, which just gives you `true` if the input matches the grammar and `false` otherwise: - -```cpp -auto good = lexy::zstring_input("#FF00FF"); -CHECK(lexy::match(good) == true); - -auto bad = lexy::zstring_input("#FFF"); -CHECK(lexy::match(bad) == false); -``` - -If you want to figure out _why_ it didn't match, you can use {{% docref "lexy::validate" %}}. -It takes an additional {{% docref "error callback" %}} that is invoked with the error, which you can use to print additional information to the user. -The extension library provides a callback that formats the error message nicely and prints it to stderr: - -```cpp -auto bad = lexy::zstring_input("#FFF"); -auto result = lexy::validate(bad, lexy_ext::report_error); -CHECK(result.is_error()); -``` - -There are also actions to parse the input into a {{% docref "lexy::parse_tree" %}} ({{% docref "lexy::parse_as_tree" %}}) and to trace the parsing algorithm for debugging purposes ({{% docref "lexy::trace" %}}). -Both of those are available to play with in the link:/playground?example=color[online playground]. - -What we really want to do though, is parse the input into our `Color` struct. -For that, we need to use the action {{% docref "lexy::parse" %}}: -it parses the input, reports error to the error callback, and produces a user-defined value. -This values is controlled by adding an additional `static constexpr` member to each production of the grammar called `value`. -It specifies a {{% docref "callback" %}} that is invoked with all values produced during parsing of the rule; -lexy provides common callbacks by including `lexy/callback.hpp`. - -So what values are produced by parsing the rules? - -Well, right now: none. -None of the primitive rules we've used produce any values, they just match input. -The exception is {{% docref "lexy::dsl::p" %}} which produces the result of parsing the child production, -but as that doesn't produce a value currently either, nothing happens. - -So instead of just blindly matching the digits, we have to convert them into an integer and produce them. -This can be done by wrapping the {{% docref "lexy::dsl::n_digits" %}} rule into a call to the {{% docref "lexy::dsl::integer" %}} rule, -and providing an appropriate callback: - -```cpp -struct channel -{ - static constexpr auto rule = dsl::integer(dsl::n_digits<2, dsl::hex>); <1> - static constexpr auto value = lexy::forward; <2> -}; -``` -<1> We want to convert the matched digits into a `std::uint8_t`, which is then produced by parsing the rule. -<2> The callback uses {{% docref "lexy::forward" %}}, which just forwards the produced value as the result of parsing the production. - -Now each call to {{% docref "lexy::dsl::p" %}} in the `color` production will result in a single `std::uint8_t`, which are then passed to the provided callback: - -```cpp -struct color -{ - static constexpr auto rule = dsl::hash_sign + dsl::times<3>(dsl::p) + dsl::eof; - static constexpr auto value = lexy::construct; <1> -}; -``` -<1> Accept the three integers and construct our `Color` struct from them using {{% docref "lexy::construct" %}}. - -## Putting it all together - -Combining everything, we have the full example for parsing the HTML color into our struct `Color`: - -{{% godbolt-example color "Parse an HTML color" %}} - -Note how we're checking whether parsing produced a value with `.has_value()`, and not whether there were any parse errors `.is_error()`, `operator bool()`. -This is because lexy implements error recovery: certain errors can be recovered during parsing. - diff --git a/assembler/ext/src/lexy/docs/content/playground/_index.md b/assembler/ext/src/lexy/docs/content/playground/_index.md deleted file mode 100644 index 6ba5fde55c..0000000000 --- a/assembler/ext/src/lexy/docs/content/playground/_index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "Playground" -menu: - main: - name: "Playground" - weight: 3 ---- - -Enter the grammar in the left editor (`lexy/dsl.hpp` and namespace alias `dsl` is pre-included) and the input in the right editor. -The result of parsing the selected entry production on that input is displayed in the bottom window. -The encoding is `lexy::utf8_encoding`. - -The online playground is powered by [Compiler Explorer](https://godbolt.org/), [Ace](https://ace.c9.io/), [ansi_up](https://github.com/drudru/ansi_up), and [d3-graphviz](https://github.com/magjac/d3-graphviz). - diff --git a/assembler/ext/src/lexy/docs/content/reference/_index.adoc b/assembler/ext/src/lexy/docs/content/reference/_index.adoc deleted file mode 100644 index b583a96112..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/_index.adoc +++ /dev/null @@ -1,132 +0,0 @@ ---- -layout: single -title: "Reference" -menu: - main: - name: "Reference" - weight: 2 -outputs: [html, json] ---- -:toc: left - -To use lexy, you need three things: - -1. Define a link:#grammar[grammar] using the rule DSL and callbacks. -2. Create an link:#input[input] object that represents the input you want to parse. -3. Call an link:#action[action] that will parse the grammar on the input. - -lexy is designed to work with your own types and data structures. -As such, its usage can be hidden away in the implementation of a parse function whose interface does not mention lexy specific types. -Nevertheless, lexy defines some link:#infrastructure[infrastructure] types that can be used as vocabulary types in your project interfaces. - -[#infrastructure] -== Infrastructure - -{{% headerref "code_point" %}}:: - A Unicode code point, and related algorithms. -{{% headerref "lexeme" %}}:: - A lexeme, i.e. a subrange of the input. -{{% headerref "token" %}}:: - Identify and store tokens, i.e. concrete realization of {{% token-rule %}}s. -{{% headerref "parse_tree" %}}:: - A parse tree. -{{% headerref "error" %}}:: - The parse errors. -{{% headerref "input_location" %}}:: - Compute human readable line/column numbers for a position of the input. -{{% headerref "visualize" %}}:: - Visualize the data structures. - -[#input] -== Inputs and Encodings - -[source,cpp] ----- -template -concept reader = …; - -template -concept input = requires(const T& obj) { - { obj.reader() } -> reader; -}; ----- - -An input defines the input that will be parsed by lexy. -It has a corresponding {{% encoding %}} that controls, among other things, its character type and whether certain rules are available. -The input itself is unchanging and it produces a reader which remembers the current position of the input during parsing. - -.The supported encodings of {{% headerref "encoding" %}}: -{{% docref "lexy::default_encoding" %}}:: - An unknown single byte encoding. -{{% docref "lexy::ascii_encoding" %}}:: - ASCII -{{% docref "lexy::utf8_encoding" %}}, {{% docref "lexy::utf16_encoding" %}}, {{% docref "lexy::utf32_encoding" %}}:: - UTF-8, UTF-16, UTF-32 -{{% docref "lexy::byte_encoding" %}}:: - Bytes, not text. - -.The pre-defined inputs: -{{% headerref "range_input" %}}:: - Use a generic iterator range as input. -{{% headerref "string_input" %}}:: - Use a string as input. -{{% headerref "buffer" %}}:: - Create a buffer that contains the input. -{{% headerref "file" %}}:: - Use a file as input. -{{% headerref "argv_input" %}}:: - Use the command-line arguments as input. -{{% headerref "lexeme_input" %}}:: - Use a subset of an existing input while computing correct line/column information. - -[#grammar] -== The grammar DSL - -[source,cpp] ----- -template -concept production = requires { - { T::production } -> rule; - { T::whitespace } -> rule; // optional - { T::value } -> callback-or-sink; // optional -}; ----- - -The grammar is specified by _productions_: classes with a `::rule` member that specifies the {{% rule %}}. -They can optionally have a `::whitespace` member that controls {{% docref "whitespace" "automatic whitespace skipping" %}}. -Both of those are specified in a C++ DSL. -The action {{% docref "lexy::parse" %}} also needs a `::value` member that controls the value produced by parsing the production. -It is specified using callbacks, special function objects, and sinks. - -{{% headerref "grammar" %}}:: - Type traits for defining and interacting with the grammar. -{{% headerref "dsl" %}}:: - The DSL for specifying parse rules. -{{% headerref "callback" %}}:: - The predefined callbacks and sinks for specifying the value. - -TIP: It is a recommended to put all the productions into a separate namespace. - -[#action] -== Actions - -Actions take a grammar and an input, and do something with the grammar on that input. - -They also optionally take a parse state argument. -If provided, it will be forwarded as state parameter to the callbacks, -and to rules such as {{% docref "lexy::dsl::scan" %}}. -It can be used to pass additional meta data or allocators etc. to the grammar. - -{{% headerref "action/match" %}}:: - Matches a grammar on an input and return a `true`/`false` result. -{{% headerref "action/validate" %}}:: - Validates that a grammar matches on an input, and returns the errors if it does not. -{{% headerref "action/parse" %}}:: - Parses a grammar on an input and returns its value. -{{% headerref "action/parse_as_tree" %}}:: - Parses a grammar on an input and returns the parse tree. -{{% headerref "action/scan" %}}:: - Parses a grammar manually by dispatching to other rules. -{{% headerref "action/trace" %}}:: - Traces parse events to visualize and debug the parsing process. - diff --git a/assembler/ext/src/lexy/docs/content/reference/action/match.adoc b/assembler/ext/src/lexy/docs/content/reference/action/match.adoc deleted file mode 100644 index 99bd63ef56..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/action/match.adoc +++ /dev/null @@ -1,36 +0,0 @@ ---- -header: "lexy/action/match.hpp" -entities: - "lexy::match": match ---- -:toc: left - -[#match] -== Action `lexy::match` - -{{% interface %}} ----- -namespace lexy -{ - template <_production_ Production> - constexpr bool match(const _input_ auto& input); - - template <_production_ Production, typename ParseState> - constexpr bool match(const _input_ auto& input, const ParseState& state); -} ----- - -[.lead] -An action that determines whether `Production` matches on `input`. - -It parses `Production` on input. -All values produced during parsing are discarded; -all errors ignored. -Returns `true` if parsing was successful without errors, -returns `false` if parsing lead to an error, even if it recovered. - -TIP: Use {{% docref "lexy::validate" %}} to get information about the parse error. - -NOTE: `Production` does not need to match the entire `input` to succeed. -Use {{% docref "lexy::dsl::eof" %}} if it should fail when it didn't consume the entire input. - diff --git a/assembler/ext/src/lexy/docs/content/reference/action/parse.adoc b/assembler/ext/src/lexy/docs/content/reference/action/parse.adoc deleted file mode 100644 index e96862b6f3..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/action/parse.adoc +++ /dev/null @@ -1,148 +0,0 @@ ---- -header: "lexy/action/parse.hpp" -entities: - "lexy::parse_result": parse_result - "lexy::parse": parse ---- -:toc: left - -[#parse_result] -== Class `lexy::parse_result` - -{{% interface %}} ----- -namespace lexy -{ - template - class parse_result - { - public: - using value_type = T; - using error_callback = ErrorCallback; - using error_type = _see-below_; - - //=== status ===// - constexpr explicit operator bool() const noexcept - { - return is_success(); - } - - constexpr bool is_success() const noexcept; - constexpr bool is_error() const noexcept; - constexpr bool is_recovered_error() const neoxcept; - constexpr bool is_fatal_error() const noexcept; - - //=== value ===// - constexpr bool has_value() const noexcept; - - constexpr const value_type& value() const& noexcept; - constexpr value_type&& value() && noexcept; - - //=== error list ===// - constexpr std::size_t error_count() const noexcept; - - constexpr const error_type& errors() const& noexcept; - constexpr error_type&& errors() && noexcept; - }; -} ----- - -[.lead] -The result of {{% docref "lexy::parse" %}}. - -It stores the status of the action, the value producing during parsing, -and the final error list of the {{% error-callback %}}, which has type `error_type`. - -NOTE: The status and error list are identical to {{% docref "lexy::validate_result" %}}. - -=== Status - -{{% interface %}} ----- -constexpr explicit operator bool() const noexcept -{ - return is_success(); -} - -constexpr bool is_success() const noexcept; <1> -constexpr bool is_error() const noexcept; <2> -constexpr bool is_recovered_error() const neoxcept; <3> -constexpr bool is_fatal_error() const noexcept; <4> ----- -<1> Returns `true` if parsing succeeded without raising any errors, `false` otherwise. -<2> Returns `true` if at least one error occurred during parsing, `false` otherwise. -<3> Returns `true` if at least one error occurred during parsing but it could recover from all of them, `false` otherwise. -<4> Returns `true` if at least one error occurred during parsing that could not be recovered, `false` otherwise. - -NOTE: `is_error()` is equivalent to `is_recovered_error() || is_fatal_error()`, and `is_success()` is `!is_error()`. - -=== Value - -{{% interface %}} ----- -constexpr bool has_value() const noexcept; <1> - -constexpr const value_type& value() const& noexcept; <2> -constexpr value_type&& value() && noexcept; <2> ----- -<1> Returns `true` if parsing could produce a value, `false` otherwise. - It produces a value when parsing succeeded (`is_success() == true`), - or when it could recover from all errors (`is_recovered_error() == true`). -<2> Returns the value producing during parsing, requires `has_value() == true`. - -CAUTION: If `has_value() == true` but `is_success() == false` (i.e. `is_recovered_error() == true`), -the value was produced after recovering from an error. -This means that some invariants that would be satisfied for a well-formed input are not necessarily satisfied now. -For example, in a well-formed input a {{% docref "lexy::dsl::identifier" %}} is not reserved, -but after recovery a reserved identifier is produced. - -== Error list - -{{% interface %}} ----- -constexpr std::size_t error_count() const noexcept; <1> - -constexpr const error_type& errors() const& noexcept; <2> -constexpr error_type&& errors() && noexcept; <2> ----- -<1> If `error_type` is `std::size_t`, returns `errors()`. - Otherwise, returns `errors().size()`. -<2> The final value of the `ErrorCallback`, unchanged. - -If `is_success() == true`, `error_count() == 0` and `errors()` returns the result of the sink callback that is finished without ever invoking it. - -[#parse] -== Action `lexy::parse` - -{{% interface %}} ----- -namespace lexy -{ - template <_production_ Production> - constexpr auto parse(const _input_ auto& input, - _error-callback_ auto error_callback) - -> parse_result<_see-below_, decltype(error_callback)>; - - template <_production_ Production, typename ParseState> - constexpr auto parse(const _input_ auto& input, const ParseState& parse_state, - _error-callback_ auto error_callback) - -> parse_result<_see-below_, decltype(error_callback)>; -} ----- - -[.lead] -An action that parses `Production` on `input` and produces a value. - -It parses `Production` on input. -All values produced during parsing are forwarded to the `Production::value` callback; -all errors raised are forwarded to the {{% error-callback %}}. -Returns the {{% docref "lexy::parse_result" %}} containing the final value and the result of the error callback. - -The value of any production `P` in the grammar is determined using {{% docref "lexy::production_value_callback" %}} and `P::value`: -all values produced by parsing `P::rule` will be forwarded to `lexy::production_value_callback`'s `operator()`. -This includes the value produced recursively by parsing a child production with {{% docref "lexy::dsl::p" %}} or {{% docref "lexy::dsl::recurse" %}}. -If `P::rule` contains a rule that requires a sink (e.g. {{% docref "lexy::dsl::list" %}}, it will use the sink of `lexy::production_value_callback`, which requires that `P::value` is a sink. -The final value of the parse action is the value produced by `Production`. - -TIP: Use {{% docref "lexy::bind" %}} and {{% docref "lexy::bind_sink" %}} with the placeholder {{% docref "lexy::parse_state" %}} to access the `state` object in existing callbacks. - diff --git a/assembler/ext/src/lexy/docs/content/reference/action/parse_as_tree.adoc b/assembler/ext/src/lexy/docs/content/reference/action/parse_as_tree.adoc deleted file mode 100644 index 97ed17fb95..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/action/parse_as_tree.adoc +++ /dev/null @@ -1,47 +0,0 @@ ---- -header: "lexy/action/parse_as_tree.hpp" -entities: - "lexy::parse_as_tree": parse_as_tree ---- -:toc: left - -[#parse_as_tree] -== Action `lexy::parse_as_tree` - -{{% interface %}} ----- -namespace lexy -{ - template <_production_ Production, - typename TK, typename MemRes, - _input_ Input> - auto parse_as_tree(parse_tree, TK, MemRes>& tree, - const Input& input, _error-callback_ auto error_callback) - -> validate_result; - - template <_production_ Production, - typename TK, typename MemRes, - _input_ Input, typename ParseState> - auto parse_as_tree(parse_tree, TK, MemRes>& tree, - const Input& input, const ParseState& parse_state, _error-callback_ auto error_callback) - -> validate_result; -} ----- - -[.lead] -An action that parses `Production` on `input` and produces a {{% docref "lexy::parse_tree" %}}. - -It parses `Production` on `input`. -All values produced during parsing are discarded; -all errors raised are forwarded to the {{% error-callback %}}. -Returns the {{% docref "lexy::validate_result" %}} containing the result of the error callback. - -During parsing, `tree` is cleared and replaced by a new tree that represents the parse tree of the input: -it will have a production node for each production, and a token node for each tokens as indicated by the {{% rule %}}s. -If a production is a {{% docref "lexy::transparent_production" %}}, it will not get its own node in the parse tree, -but the would-be children instead added to the currently active node. -If a token rule has an ignorable {{% docref "lexy::token_kind" %}} and matches without having consumed any input, it will not be added to the parse tree. - -The resulting parse tree is a lossless representation of the input: -Traversing all token nodes of the tree and concatenating their {{% docref "lexy::lexeme" %}}s will yield the same input back. - diff --git a/assembler/ext/src/lexy/docs/content/reference/action/scan.adoc b/assembler/ext/src/lexy/docs/content/reference/action/scan.adoc deleted file mode 100644 index 4804be328d..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/action/scan.adoc +++ /dev/null @@ -1,382 +0,0 @@ ---- -header: "lexy/action/scan.hpp" -entities: - "lexy::scan_failed": scan_result - "lexy::scan_result": scan_result - "lexy::scanner-common": scanner-common - "lexy::scanner": scan - "lexy::scan": scan ---- -:toc: left - -[#scan_result] -== Class `lexy::scan_result` - -{{% interface %}} ----- -namespace lexy -{ - struct scan_failed_t {}; - constexpr scan_failed_t scan_failed; - - template - class scan_result - { - public: - using value_type = T; - - constexpr scan_result() = default; - constexpr scan_result(scan_failed_t); - - constexpr scan_result(T&& value); // T != void only - constexpr scan_result(bool has_value); // T == void only - - constexpr bool has_value() const noexcept; - constexpr explicit operator bool() const noexcept - { - return has_value(); - } - - // T != void only - constexpr const T& value() const& noexcept; - constexpr T&& value() && noexcept; - - // T != void only - template - constexpr U value_or(U&& fallback) const& noexcept; - template - constexpr U value_or(U&& fallback) && noexcept; - }; -} ----- - -[.lead] -The result of an individual scanning operation. - -Like `std::optional`, it is either empty or stores a `T`. -Unlike `std::optional`, it supports `void` and is immutable. - -[#scanner-common] -== Common scanner interface - -{{% interface %}} ----- -namespace lexy -{ - template <_reader_ Reader> - class _scanner-common_ - { - public: - using encoding = typename Reader::encoding; - - _scanner-common_(const _scanner-common_&) = delete; - _scanner-common_& operator=(const _scanner-common_&) = delete; - - //=== status access ===// - constexpr explicit operator bool() const noexcept; - - constexpr bool is_at_eof() const; - - constexpr auto position() const noexcept - -> typename Reader::iterator; - - constexpr _input_ auto remaining_input() const noexcept; - - //=== parsing ===// - template - constexpr void parse(scan_result& result, _rule_ auto rule); - - template <_production_ Production> - constexpr auto parse(Production production = {}) - -> scan_result<_return-type-of-value_>; - - constexpr void parse(_rule_ auto rule); - - //=== branch parsing ===// - template - constexpr bool branch(scan_result& result, _branch-rule_ auto rule); - - template <_production_ Production> - constexpr bool branch(scan_result<_return-type-of-value_>& result, - Production production = {}); - - template - constexpr bool branch(_branch-rule_ auto rule); - - //=== error handling ===// - class error_recovery_guard; - - constexpr error_recovery_guard error_recovery(); - - constexpr bool discard(_token-rule_ auto rule); - - template - constexpr void error(Tag tag, Args&&... args); - template - constexpr void fatal_error(Tag tag, Args&&... args); - - //=== convenience ===// - // Forwards to `parse(result, rule)` overload. - template - constexpr scan_result parse(_rule_ auto rule); - - // Equivalent to `branch(dsl::peek(rule))`. - constexpr bool peek(_rule_ auto rule); - - // Equivalent to `parse(result, dsl::integer(digits))`. - template - constexpr scan_result auto integer(_token-rule_ auto digits); - template - constexpr scan_result integer(_digits-dsl_ digits); - template - constexpr scan_result integer(_ndigits-dsl_ digits); - - // Forwards to `parse(rule)` (without value!) and then returns a lexeme. - constexpr scan_result> capture(_rule_ auto rule); - // Forwards to `parse(result, dsl::capture_token(rule))`. - constexpr scan_result> capture_token(_token-rule_ auto rule); - }; -} ----- - -[.lead] -The scanner interface common to {{% docref "lexy::scanner" %}} and {{% docref "lexy::rule_scanner" %}}. - -A scanner allows parsing rules manually for full control. -It internally stores a reader, which remembers the current position in the input, -and it can be in one of three states: - -1. The ok state, which is the default one. - In that state, the scanner can be used to parse rules. -2. The error state, which is entered when a rule fails to parse. - In that state, any other rule parse has no effect. - Error recovery can be used to clear the state back to the ok state. -3. The recovery state, which is entered by error recovery. - In that state, the scanner can be used to parse rules to recover. - -=== Status access - -{{% interface %}} ----- -constexpr explicit operator bool() const noexcept; ----- - -[.lead] -Returns `true` if the scanner is currently in the ok state, `false` otherwise (error or recovery). - -{{% interface %}} ----- -constexpr bool is_at_eof() const; ----- - -[.lead] -Returns `true` if the current position of the reader is at EOF, `false` otherwise. - -{{% interface %}} ----- -constexpr auto position() const noexcept - -> typename Reader::iterator; ----- - -[.lead] -Returns an iterator to the current position of the reader. - -CAUTION: The iterator must only be dereferenced if `is_at_eof() == false`. - -{{% interface %}} ----- -constexpr _input_ auto remaining_input() const noexcept; ----- - -[.lead] -Returns a new input that can be used to access the input from `position()` until EOF. - -=== Parsing - -{{% interface %}} ----- -template -constexpr void parse(scan_result& result, _rule_ auto rule); - -template <_production_ Production> -constexpr auto parse(Production production = {}) - -> scan_result<_return-type-of-value_>; - -constexpr void parse(_rule_ auto rule); ----- - -[.lead] -Parses the given `rule`. - -If the scanner is in the error state, immediately returns without doing anything. -This makes it unnecessary to check for errors after each parse step. - -Otherwise, parses the `rule` beginning at the current reader position. -If that succeeds, consumes everything consumed by `rule`, generating the necessary tokens in the parse tree if necessary, -and returns. -Otherwise, consumes everything already consumed by `rule` and puts the scanner in the error state. - -The first overload parses the `rule` as if the parse action {{% docref "lexy::parse" %}} was used, -regardless of the actual parse action used in the top-level. -If `rule` parses a child production `P`, it invokes the `P::value` callback as necessary to produce a value. -When the rule succeeds, all arguments produced by `rule` are passed to `lexy::construct` and the result stored in `result`. - -The second overload parses the `production`; -it is equivalent to `parse(result, dsl::p)`. -The production can be specified by an explicit template argument or by passing an object as parameter. - -The third overload parses the `rule` as if the parse action {{% docref "lexy::match" %}} was used; -no value is produced and child productions do not need a `::value` member. - -=== Branch parsing - -{{% interface %}} ----- -template -constexpr bool branch(scan_result& result, _branch-rule_ auto rule); - -template <_production_ Production> -constexpr bool branch(scan_result<_return-type-of-value_>& result, - Production production = {}); - -template -constexpr bool branch(_branch-rule_ auto rule); ----- - -[.lead] -Branch parses the given `rule`. - -If the scanner is in the error state, immediately returns `false` without doing anything. -This makes it unnecessary to check for errors after each parse step. -It returns `false`, as the branch couldn't be taken. - -Otherwise, branch parses the `rule` beginning at the current reader position. -If that backtracks, the reader is not advanced and it returns `false`. -If that succeeds, consumes everything consumed by `rule`, generating the necessary tokens in the parse if necessary, and returns `true`. -Otherwise, consumes everything already consumed by `rule` and puts the scanner in the error state. -It then also returns `true`, as parsing has already committed to take the branch and only failed later. - -Similar to `.parse()`, the first overload produces a value, the second overload a production, and the third overload does not produce values. - -NOTE: `scanner.branch(condition) ? scanner.parse(a) : scanner.parse(b)` is entirely equivalent to `scanner.parse(condition >> a | dsl::else_ >> b)`. - -=== Error handling - -{{% interface %}} ----- -class error_recovery_guard -{ -public: - error_recovery_guard(const error_recovery_guard&) = delete; - error_recovery_guard& operator=(const error_recovery_guard&) = delete; - - constexpr void cancel() &&; - constexpr void finish() &&; -}; - -constexpr error_recovery_guard error_recovery(); ----- - -[.lead] -Allows recovery from a failed state. - -Calling `.error_recovery()` is only allowed when the scanner is currently in the failed state. -It puts the scanner in the recovery state and returns a new `error_recovery_guard` object. - -The scanner can then be used to try and recover from the error. -If that succeeds, calling `.finish()` on the `error_recovery_guard` object puts the scanner in the ok state. -Otherwise, calling `.cancel()` resets the scanner back to the failed state. -Any input already consumed during recovery stays consumed. - -{{% playground-example "scan-recovery" "Manually parse an integer surrounded by quotes" %}} - -{{% interface %}} ----- -constexpr bool discard(_token-rule_ auto rule); ----- - -[.lead] -Parses a token rule and discards it by producing an error token. - -If the scanner is in a failed state, returns `false` without doing anything. -Otherwise, attempts to match `rule` at the current error position. -If that consumes a non-zero amount of input, generates an error token. -It returns `true` if matching was successful, `false` otherwise. - -NOTE: It is meant to be called during error recovery only. - -{{% interface %}} ----- -template -constexpr void error(Tag tag, Args&&... args); - -template -constexpr void fatal_error(Tag tag, Args&&... args); ----- - -[.lead] -Raise a {{% docref "lexy::error" %}}. - -Both overloads construct a `lexy::error` object with the specified `Tag` from the specified arguments and forward it to the handler. -The second overload then puts the scanner in a failed state, the first overload leaves the state unchanged. - -[#scan] -== Action `lexy::scan` - -{{% interface %}} ----- -namespace lexy -{ - template <_production_ ControlProduction, - _input_ Input, typename ParseState, _error-callback_ ErrorCallback> - class scanner - : public _scanner-common_ - { - public: - constexpr const ParseState& parse_state() const; - - constexpr auto finish() && -> lexy::validate_result; - }; - - template <_production_ ControlProduction = void> - constexpr scanner scan(const _input_ auto& input, - _error-callback_ auto error_callback); - - template <_production_ ControlProduction = void, typename ParseState> - constexpr scanner scan(const _input_ auto& input, - const ParseState& parse_state, - _error-callback_ auto error_callback); -} ----- - -[.lead] -A parse action that allows manual parsing of an input. - -Unlike the other actions, it does not directly parse a given production on the input. -Instead, it returns a scanner object that allows manual control over the parsing process. - -The scanner object starts parsing the input from the beginning using the same handler as {{% docref "lexy::validate" %}} internally. -It implements the {{% docref "lexy::scanner-common" %}} interface for parsing individual rules. -During parsing, any errors will be forwarded to the {{% error-callback %}}. -`.finish()` can be called at the end to return the result in a {{% docref "lexy::validate_result" %}} object, whose status corresponds to the scanner state as follows: - -* If the scanner is in the ok state and no errors have been reported to the error callback, `is_success()` will return `true`. -* If the scanner is in the ok state but error have been reported, `is_recovered_error()` will return `true`. -* Otherwise, if the scanner is not in the ok state, `is_fatal_error()` will return `true`. - -If the error callback does not return an interesting result, `.finish()` does not need to be called. - -An optional `ControlProduction` can be specified. -This is used to specify whitespace for {{% docref "whitespace" "automatic whitespace skipping" %}}, -the recursion depth for {{% docref "lexy::dsl::recurse" %}}, and other meta data of the "grammar" being parsed. -It does not need a `::rule` member; any member specified will be ignored. - -{{% godbolt-example "scan" "Use `lexy` as a verbose `std::scanf` replacement" %}} - -TIP: See {{< github-example "shell" >}} for an example that uses `lexy::scan()` to handle parsing directives that don't directly belong to the grammar. - -NOTE: Use {{% docref "lexy::dsl::scan" %}} if you want to manually parse some production of your grammar. - -CAUTION: The overload that takes a `parse_state` internally stores a pointer to it. -As such, `parse_state` must live as long as the `lexy::scanner` object. - diff --git a/assembler/ext/src/lexy/docs/content/reference/action/trace.adoc b/assembler/ext/src/lexy/docs/content/reference/action/trace.adoc deleted file mode 100644 index 466f6c2023..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/action/trace.adoc +++ /dev/null @@ -1,97 +0,0 @@ ---- -header: "lexy/action/trace.hpp" -entities: - "lexy::trace_to": trace - "lexy::trace": trace - "lexy::dsl::debug": debug - "LEXY_DEBUG": debug ---- -:toc: left - -[.lead] -Visualize the parsing process. - -[#parse] -== Action `lexy::trace` and `lexy::trace_to` - -{{% interface %}} ----- -namespace lexy -{ - template <_production_ Production, typename TokenKind = void, - std::output_iterator OutputIt> - OutputIt trace_to(OutputIt out, const auto _input_& input, - visualization_options opts = {}); - - template <_production_ Production, typename TokenKind = void, - std::output_iterator OutputIt, typename ParseState> - OutputIt trace_to(OutputIt out, const auto _input_& input, - const ParseState& parse_state, - visualization_options opts = {}); - - template <_production_ Production, typename TokenKind = void> - void trace(std::FILE* file, const auto _input_& input, - visualization_options opts = {}); - - template <_production_ Production, typename TokenKind = void, - typename ParseState> - void trace(std::FILE* file, const auto _input_& input, - const ParseState& parse_state, - visualization_options opts = {}); -} ----- - -[.lead] -An action that traces the events of parsing `Production` on `input` and visualizes them. - -The first two overloads write the events to `out`; the last two to `file`. -Like {{% docref "lexy::visualize_to" %}}, the output is meant to be human-readable only. -It is not documented exactly and subject to change. - -The events it reports are: - -* Whenever parsing of a production starts or is finished. -* Whenever parsing of a production starts in a branch condition and is then canceled as the branch couldn't be taken. -* Whenever a token is parsed. -* Whenever parsing needs to backtrack to an earlier position. -* Whenever an error is encountered. -* Whenever non-trivial error recovery starts, finishes or fails, - e.g. by a {{% docref "lexy::dsl::try_" %}} rule. -* Whenever a {{% docref "lexy::dsl::debug" %}} rule is matched. - -For each event, the line and column information in the input is given. -Events are structured in a hierarchy like {{% docref "lexy::parse_tree" %}}. - -{{% playground-example "trace" "Trace parsing of a grammar" "trace" %}} - -[#debug] -== Rule `lexy::dsl::debug` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template - constexpr _rule_ auto debug; -} - -#define LEXY_DEBUG(Str) lexy::dsl::debug ----- - -[.lead] -Creates a debug event for {{% docref "lexy::trace" %}}. - -Parsing:: - Always succeeds without consuming anything. -Errors:: - None. -Values:: - None. - -It generates a debug event at the current input position with the associated message `Str`. -This is only meaningful for {{% docref "lexy::trace" %}} and is ignored otherwise. -See an example there. - -The macro `LEXY_DEBUG(Str)` is equivalent to `debug`, except that it also works on older compilers that do not support C++20's extended NTTPs. -Use this instead of `debug` if you need to support them. - diff --git a/assembler/ext/src/lexy/docs/content/reference/action/validate.adoc b/assembler/ext/src/lexy/docs/content/reference/action/validate.adoc deleted file mode 100644 index 7ee511c6cc..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/action/validate.adoc +++ /dev/null @@ -1,149 +0,0 @@ ---- -header: "lexy/action/validate.hpp" -entities: - "lexy::validate_result": validate_result - "lexy::validate": validate - "error callback": error-callback ---- -:toc: left - -[.lead] -Validate input. - -[#error-callback] -== Error callback - -[source,cpp,subs="+quotes"] ----- -template -concept _error-callback_ = _callback_ || _sink_; ----- - -[.lead] -The callback types used for error reporting. - -If it is a link:{{< relref "callback#sink" >}}[sink], it must not return `void`. -Its sink callback must have the signature -[source,cpp,subs="+quotes"] ----- -template <_production_ Production, _input_ Input, typename Tag> -void operator()(const lexy::error_context& context, - const lexy::error_for& error); ----- -It will be invoked for each {{% docref "lexy::error" %}} object with the corresponding {{% docref "lexy::error_context" %}}. -The final result of the sink, the error list, is then made available. - -If it is a link:{{< relref "callback#callback" >}}[callback], it must return `void` with the same signature. -{{% docref "lexy::collect" %}} is used to turn into a sink that counts the invocations of the callback. -As such, it's final value is a `std::size_t`. - -TIP: Use the extension `lexy_ext::report_error` of `lexy_ext/report_error.hpp` for a simple error callback that formats the error nicely and prints it to `stderr`. - -TIP: Use the other overload of {{% docref "lexy::collect" %}} to turn a non-`void` returning callback into a sink that collects all values into the specified container. - -[#validate_result] -== Class `lexy::validate_result` - -{{% interface %}} ----- -namespace lexy -{ - template - class validate_result - { - public: - using error_callback = ErrorCallback; - using error_type = _see-below_; - - //=== status ===// - constexpr explicit operator bool() const noexcept - { - return is_success(); - } - - constexpr bool is_success() const noexcept; - constexpr bool is_error() const noexcept; - constexpr bool is_recovered_error() const neoxcept; - constexpr bool is_fatal_error() const noexcept; - - //=== error list ===// - constexpr std::size_t error_count() const noexcept; - - constexpr const error_type& errors() const& noexcept; - constexpr error_type&& errors() && noexcept; - }; -} ----- - -[.lead] -The result of {{% docref "lexy::validate" %}} and {{% docref "lexy::parse_as_tree" %}}. - -It stores the status of the action and the final error list of the {{% error-callback %}}, which has type `error_type`. - -=== Status - -{{% interface %}} ----- -constexpr explicit operator bool() const noexcept -{ - return is_success(); -} - -constexpr bool is_success() const noexcept; <1> -constexpr bool is_error() const noexcept; <2> -constexpr bool is_recovered_error() const neoxcept; <3> -constexpr bool is_fatal_error() const noexcept; <4> ----- -<1> Returns `true` if parsing succeeded without raising any errors, `false` otherwise. -<2> Returns `true` if at least one error occurred during parsing, `false` otherwise. -<3> Returns `true` if at least one error occurred during parsing but it could recover from all of them, `false` otherwise. -<4> Returns `true` if at least one error occurred during parsing that could not be recovered, `false` otherwise. - -NOTE: `is_error()` is equivalent to `is_recovered_error() || is_fatal_error()`, and `is_success()` is `!is_error()`. - -== Error list - -{{% interface %}} ----- -constexpr std::size_t error_count() const noexcept; <1> - -constexpr const error_type& errors() const& noexcept; <2> -constexpr error_type&& errors() && noexcept; <2> ----- -<1> If `error_type` is `std::size_t`, returns `errors()`. - Otherwise, returns `errors().size()`. -<2> The final value of the `ErrorCallback`, unchanged. - -If `is_success() == true`, `error_count() == 0` and `errors()` returns the result of the sink callback that is finished without ever invoking it. - -[#validate] -== Action `lexy::validate` - -{{% interface %}} ----- -namespace lexy -{ - template <_production_ Production> - constexpr auto validate(const _input_ auto& input, - _error-callback_ auto error_callback) - -> validate_result; - - template <_production_ Production, typename ParseState> - constexpr auto validate(const _input_ auto& input, - const ParseState& state, - _error-callback_ auto error_callback) - -> validate_result; -} ----- - -[.lead] -An action that validates `input` according to `Production`. - -It parses `Production` on input. -All values produced during parsing are discarded; -all errors raised are forwarded to the {{% error-callback %}}. -Returns the {{% docref "lexy::validate_result" %}} containing the result of the error callback. - -NOTE: `Production` does not need to match the entire `input` to succeed. -Use {{% docref "lexy::dsl::eof" %}} if it should fail when it didn't consume the entire input. - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/_index.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/_index.adoc deleted file mode 100644 index a7d91dc81a..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/_index.adoc +++ /dev/null @@ -1,149 +0,0 @@ ---- -layout: single -header: "lexy/callback.hpp" -entities: - "callback": callback - "sink": sink ---- -:toc: left - -[.lead] -Callbacks that receive the values produced during parsing and process them. - -[#callback] -== Callback - -{{% interface %}} ----- -namespace lexy -{ - template - concept _callback_ = requires { typename T::return_type; } - - template - constexpr bool is_callback = _callback_; - - template - concept _callback-for_ = callback - && requires(const T& cb, Args&&... args) { - { cb(std::forward(args)...) } - -> std::same_as; - }; - - template - constexpr bool is_callback_for = _callback-for_; - - template - concept _callback-with-state_ = callback - && requires(const T& cb, const State& state) { - { cb[state](std::forward(args)...) } - -> std::same_as; - }; - - template - constexpr bool is_callback_state - = _callback-with-state_; -} ----- - -[.lead] -A _callback_ is a function object with a `return_type` typedef that specifies its return type. - -The callback can have multiple overloads of `operator()`, but all of them must return the same type. -To be usable in the grammar, a callback must not have any mutable state. - -A callback can optionally take a state. -This is an additional parameter that is passed via `operator[]` in addition to all the arguments. -During parsing, the callback arguments are the values produced by the rules while the state parameter is the parse state. - -[#sink] -== Sink - -{{% interface %}} ----- -namespace lexy -{ - template - concept _sink-callback_ = requires (T& cb) { - typename T::return_type; - - // there exist some args... with: - { cb(args...) } -> std::same_as; - - { std::move(cb).finish() } -> std::same_as; - }; - - template - concept _sink_ = requires (const T& s, Args&&... args) { - { s.sink(std::forward(args)...) } -> _sink-callback_; - }; - - template - constexpr bool is_sink = _sink_; - - template - using sink_callback = /* return type of .sink(Args...) */; - - template - constexpr bool is_sink_callback_for - = /* T is a sink callback that can be invoked with Args... */; -} ----- - -[.lead] -A _sink_ is an object with a `sink()` member function that returns a _sink callback_, which is a callback that can be invoked multiples times before producing the final value. - -The `sink()` member function can take arbitrary arguments to construct the sink callback. -This is used to e.g. pass allocator parameters to a container's constructor. -During parsing, `sink()` is passed the parse state, if it accepts it, otherwise it is invoked without arguments. - -The sink callback can be invoked with some arguments, and will somehow append them to the result. -Calling `finish()` on the sink callback will return the finished result. -Once `finish()` has been called, the sink callback is never used again. -During parsing, the sink callback is repeatedly invoked by values produced during a list rule. - -== Pre-defined callbacks and sinks - -[%collapsible] -.Adapters and composition -==== -{{% docref "lexy::callback" %}}:: - Turn an overload set of function objects into a callback. -{{% docref "lexy::mem_fn" %}}:: - Turn a member function/data pointer into a callback. -{{% docref "lexy::operator|" %}} and {{% docref "lexy::operator>>" %}}:: - Combine callbacks and sinks. -{{% docref "lexy::bind" %}} and {{% docref "lexy::bind_sink" %}}:: - Bind parameters and reorder and transform arguments of a callback or sink. -{{% docref "lexy::fold" %}} and {{% docref "lexy::fold_inplace" %}}:: - Fold over all arguments of a sink. -==== - -[%collapsible] -.Primitives -==== -{{% docref "lexy::noop" %}}:: - Do nothing. -{{% docref "lexy::constant" %}}:: - Produce a constant value. -{{% docref "lexy::forward" %}}:: - Forward an existing value unchanged. -{{% docref "lexy::construct" %}} and {{% docref "lexy::new_" %}}:: - Construct a new object. -{{% docref "lexy::bit_cast" %}}:: - Constructs a new object by reinterpreting the bits of an existing one. -==== - -[%collapsible] -.Rule specific -==== -{{% docref "lexy::as_integer" %}}:: - Produce a (signed) integer value. -{{% docref "lexy::as_string" %}}:: - Produce a string. -{{% docref "lexy::as_list" %}} and {{% docref "lexy::as_collection" %}}:: - Produce a container from all list items. -{{% docref "lexy::as_aggregate" %}}:: - Produce an aggregate by setting the specified members. -==== - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/adapter.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/adapter.adoc deleted file mode 100644 index 1bcb9e134c..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/adapter.adoc +++ /dev/null @@ -1,77 +0,0 @@ ---- -header: "lexy/callback/adapter.hpp" -entities: - "lexy::callback": callback - "lexy::mem_fn": mem_fn ---- -:toc: left - -[.lead] -Adapt a function object or sink into a callback. - -[#callback] -== Callback `lexy::callback` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr _callback_ auto callback(Fns&&... fns); -} ----- - -[.lead] -Turns a regular invocable into a callback by specifying the return type, or creates an overload set of existing callbacks. - -The returned callback will take arbitrary arguments and perform overload resolution on the `fns`, -which must be invocables. -The result must return an object of the specified `ReturnType`. - -If no `ReturnType` is specified and all `fns` are itself _callbacks_, it will be the common type of all their return types. -Otherwise, it defaults to `void`. - -{{% godbolt-example "callback" "Build a callback from lambdas" %}} - -[#callback-sink] -== Callback `lexy::callback` (sink overload) - -{{% interface %}} ----- -namespace lexy -{ - constexpr _callback_ auto callback(_sink_<> auto&& sink); -} ----- - -[.lead] -Turns a sink into a callback. - -The resulting callback will take arbitrary arguments. -It will first obtain the sink callback of `sink`, then pass each argument to it in a separate invocation. -The finished result is returned by the callback. - -{{% godbolt-example "callback-fold" "Turn a sink into a callback" %}} - -NOTE: See {{% docref "lexy::collect" %}} for the inverse operation that turns a callback into a sink. - -[#mem_fn] -== Callback `lexy::mem_fn` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr _callback_ auto mem_fn(Member ClassT::* mem_ptr); -} ----- - -[.lead] -Turns a member function or data pointer into a callback. - -It is equivalent to `lexy::callback(mem_ptr)`, where `ReturnType` is deduced from the type of `mem_ptr`. - -NOTE: `mem_fn` is not necessary for passing a member function pointer to e.g. {{% docref "lexy::callback" %}}; -they all use INVOKE internally. - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/aggregate.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/aggregate.adoc deleted file mode 100644 index 3ed8340043..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/aggregate.adoc +++ /dev/null @@ -1,46 +0,0 @@ ---- -header: "lexy/callback/aggregate.hpp" -entities: - "lexy::as_aggregate": as_aggregate ---- - -[#as_aggregate] -== Callback and sink `lexy::as_aggregate` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr auto as_aggregate; -} ----- - -[.lead] -Callback and sink to construct the aggregate `T` from the {{% docref "lexy::member" %}} and value pairs produced by {{% docref "lexy::dsl::member" %}}. - -As a callback it has the following overloads: - -`(lexy::nullopt)`:: - Returns a value constructed `T`. -`(T&& t)`:: - Forwards an existing object unchanged. -`(Args&& ... args)`:: - Requires that the arguments are pairs of {{% docref "lexy::member" %}} instantiations and arbitrary types. - It will create a value constructed `T` and repeatedly invoke the function of the `lexy::member` object on the aggregate object and the value. - The result is an aggregate where all members specified as the first argument of pair are set to the value of the second argument; - if the same member is given multiple times, it is repeatedly updated. - This is then returned. -`(T&& result, Args&&... args)`:: - Same as the overload above, but it starts with `result` instead of a new object. - This allows other rules to set/override members of `result`. - -As a sink, it value initializes an object of type `T`. -The sink callback has only one overload that accepts a {{% docref "lexy::member" %}} object and value; -it will invoke the associated function on the result object and the value. -The final aggregate is returned at the end. - -{{% godbolt-example member "Parse a point" %}} - -TIP: See {{< github-example "email" >}} (productions `fields` and `message`) for a complex example that makes use of `as_aggregate`. - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/bind.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/bind.adoc deleted file mode 100644 index 9fb2f88c14..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/bind.adoc +++ /dev/null @@ -1,176 +0,0 @@ ---- -header: "lexy/callback/bind.hpp" -entities: - "lexy::values": values - "lexy::nth_value": nth_value - "lexy::placeholders": nth_value - "lexy::parse_state": parse_state - "lexy::bind": bind - "lexy::bind_sink": bind_sink ---- -:toc: left - -[.lead] -Bind parameters of a callback or sink. - -[#values] -== Placeholder `lexy::values` - -{{% interface %}} ----- -namespace lexy -{ - constexpr auto values; -} ----- - -[.lead] -A placeholder that expands to all values produced by a rule unchanged. - -In a bound call of the form `bound[state](args...)`, expands to `args...`. -The arguments are forwarded unchanged and in the same order. -This happens in addition to any {{% docref "lexy::nth_value" %}} expansion. - -{{% godbolt-example "bind-values" "Emulate `std::bind_front()`" %}} - -[#nth_value] -== Placeholder `lexy::nth_value` - -{{% interface %}} ----- -namespace lexy -{ - struct _nth_value-impl_ - { - template - constexpr _nth_value-impl_ map(Fn&& fn) const; - - template - constexpr _nth_value-impl_ or_(Arg&& fallback) const; - template - constexpr _nth_value-impl_ operator||(Arg&& fallback) const; - - constexpr _nth_value-impl_ or_default() const; - }; - - template - constexpr _nth_value-impl_ nth_value; - - inline namespace placeholders - { - constexpr auto _1 = nth_value<1>; - … - constexpr auto _8 = nth_value<8>; - } -} ----- - -[.lead] -A placeholder that expands to the Nth value produced by a rule. - -In a bound call of the form `bound[state](args...)`, expands to the Nth argument (1-indexed). -It is ill-formed if there are fewer than N arguments. -For convenience, placeholders 1 through 8 are pre-defined. - -The member function `map()` takes an invocable `fn` and returns a placeholder that expands to the transformed value. -In a bound call of the form `bound[state](args...)`, expands to the `std::invoke(fn, arg)`, where `arg` is the Nth argument. - -The member function `or_()` or the `operator||` overload (which can be invoked as `lexy::_1 || fallback` and `lexy::_1 or fallback`) take a `fallback` value and return a placeholder that expands to the Nth value or `fallback`. -In a bound call of the form `bound[state](args...)` with fewer than N arguments, -expands to `fallback`. -In a bound call of the form `bound[state](args...)` where the Nth argument is of type {{% docref "lexy::nullopt" %}}, expands to `fallback`. -Otherwise, expands to the Nth argument. - -The member function `or_default()` returns a placeholder that expands to the Nth value or a default-constructed object. -It is equivalent to `or_()` with a fallback value that is implicitly convertible to any other type by default constructing it. - -`map()` and one of `or_()`, `operator||`, and `or_default()` can be combined. -If that is the case, the fallback value is not transformed by `fn` but produced as specified. - -{{% godbolt-example "bind-reorder-map" "Reorder and map arguments" %}} - -{{% godbolt-example "bind-fallback" "Produce a different value from `lexy::opt`" %}} - -[#parse_state] -== Placeholder `lexy::parse_state` - -{{% interface %}} ----- -namespace lexy -{ - struct _parse_state-impl_ - { - template - constexpr auto map(Fn&& fn) const; - }; - - constexpr _parse_state-impl_ parse_state; -} ----- - -[.lead] -A placeholder that expands to the parse state. - -In a bound call of the form `bound[state](args...)`, expands to `state`. -It is ill-formed if no `state` was provided to the callback. - -The member function `map()` takes an invocable `fn` and returns a placeholder that expands to the transformed parse state. -In a bound call of the form `bound[state](args...)`, expands to the `std::invoke(fn, state)`. - -{{% godbolt-example "bind-parse_state" "Access additional state in a callback" %}} - -[#bind] -== Callback `lexy::bind` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr _callback_ auto bind(_callback_ auto callback, BoundArgs&&... args); -} ----- - -[.lead] -Bind parameters or transform and reorder arguments of a callback. - -When invoked as `bound[state](args...)` it invokes `callback` with the bound arguments. -If the bound argument is a placeholder, it is expanded as described there. -Otherwise, the bound argument is forwarded as-is. - -{{% godbolt-example "bind-constant" "Bind all parameters" %}} - -CAUTION: Arguments to the bound callback are silently discarded if they're not needed by a placeholder. - -[#bind_sink] -== Sink `lexy::bind_sink` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr _sink_<> auto bind_sink(_sink_ auto sink, BoundArgs&&... args); -} ----- - -[.lead] -Bind parameters of the `.sink()` member function. - -It returns a sink whose `sink()` member function forwards to `sink` and returns the same sink callback. -However, `sink.sink()` is invoked by the bound arguments. - -A call to `bound.sink()` results in a call to `sink.sink(args...)`, where no argument must be a placeholder. -A call to `bound.sink(state)` results in a call to `sink.sink()` with the expanded arguments: -If the argument is a placeholder, it is expanded as described there but note that there are no values, only a state parameter. -Otherwise, the bound argument is forwarded as-is. - -A call to `bound(...)` will be forwarded as-is onto `sink(...)`, allowing a bound sink to be used with rules like `opt_list` from {{% docref "lexy::dsl::terminator" %}}. - -{{% godbolt-example "bind_sink-parse_state" "Construct the list of integers with a custom allocator" %}} - -TIP: Specifically for passing allocators to {{% docref "lexy::as_list" %}} or {{% docref "lexy::as_collection" %}}, use its `.allocator()` function instead. -This also uses the allocator if used as a callback. - -NOTE: The bound arguments must either be constants or {{% docref "lexy::parse_state" %}}; other placeholder make no sense as the call does not have any values. - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/bit_cast.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/bit_cast.adoc deleted file mode 100644 index 072f2cbe0d..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/bit_cast.adoc +++ /dev/null @@ -1,28 +0,0 @@ ---- -header: "lexy/callback/bit_cast.hpp" -entities: - "lexy::bit_cast": bit_cast ---- - -[#bit_cast] -== Callback `lexy::bit_cast` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr _callback_ auto bit_cast; -} ----- - -[.lead] -A callback that calls https://en.cppreference.com/w/cpp/numeric/bit_cast[`std::bit_cast`]. - -It requires that `T` is trivially copyable. -It accepts any type that is also trivially copyable and has the same size as `T`. -It then converts the argument to `T` by reinterpreting the bits. - -NOTE: If `std::bit_cast` is not available, it is emulated. -This might make the callback non-`constexpr` and require that `T` is in addition default constructible. - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/composition.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/composition.adoc deleted file mode 100644 index 22bbe53052..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/composition.adoc +++ /dev/null @@ -1,57 +0,0 @@ ---- -header: "lexy/callback/composition.hpp" -entities: - "lexy::operator|": compose-callback - "lexy::operator>>": compose-sink ---- -:toc: left - -[.lead] -Compose callbacks and sinks. - -[#compose-callback] -== Callback `lexy::operator|` - -{{% interface %}} ----- -namespace lexy -{ - constexpr _callback_ auto operator|(_callback_ auto first, _callback_ auto second); -} ----- - -[.lead] -Composes two callbacks. - -The result is a callback that forwards all arguments to `first`, then forwards that result to `second.` -If either `first` or `second` is a callback with a state argument, the result is as well and it will forward the state. - -{{% godbolt-example "compose-callback" "Compose two callbacks" %}} - -[#compose-sink] -== Callback and sink `lexy::operator>>` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr auto operator>>(_sink_ auto sink, _callback_ auto callback); -} ----- - -[.lead] -Combines a sink and a callback. - -The result is both a sink and a callback. -As a sink, it forwards to the `sink`. -As a callback, it forwards all arguments to `callback`. -If the callback accepts a state, the result does as well and will forward it. - -{{% godbolt-example "compose-sink" "Compose a sink and a callback" %}} - -TIP: If you have a production that produces both a list and some other values, -using `sink >> callback` would work and the `callback` is called with the final list and the other values. -However, it is better to split the list part into a separate production that needs only a sink. -Use `operator>>` only if you need to post-process the result of a sink. - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/constant.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/constant.adoc deleted file mode 100644 index 49277c495a..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/constant.adoc +++ /dev/null @@ -1,26 +0,0 @@ ---- -header: "lexy/callback/constant.hpp" -entities: - "lexy::constant": constant ---- -:toc: left - -[#constant] -== Callback `lexy::constants` - -{{% interface %}} ----- -namespace lexy -{ - template - consteval _callback_ auto constant(Arg&& arg); -} ----- - -[.lead] -Produces a constant value. - -It is a callback that accepts zero arguments and produces a copy of the constant. - -{{% godbolt-example "true_false" "Produce constant values" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/container.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/container.adoc deleted file mode 100644 index 8dd9a9ef10..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/container.adoc +++ /dev/null @@ -1,182 +0,0 @@ ---- -header: "lexy/callback/container.hpp" -entities: - "lexy::as_list": as_list - "lexy::as_collection": as_list - "lexy::concat": concat - "lexy::collect": collect ---- -:toc: left - -[.lead] -Callbacks and sinks for constructing containers. - -[#as_list] -== Callback and sink `lexy::as_list` and `lexy::as_collection` - -{{% interface %}} ----- -namespace lexy -{ - template - struct _as-container_ - { - //=== callback ===// - using return_type = Container; - - constexpr Container operator()(lexy::nullopt) const; - constexpr Container operator()(Container&& container) const; - - template - constexpr Container operator()(Args&&... args) const; - template - constexpr Container operator()(const Container::allocator_type& allocator, - Args&&... args) const; - - //=== sink ===// - struct _sink-callback_ - { - using return_type = Container; - - template - constexpr void operator()(T&& obj); - - template - constexpr void operator()(Args&&... args); - - constexpr Container finish() &&; - }; - - constexpr _sink-callback_ sink() const; - constexpr _sink-callback_ sink(const Container::allocator_type& allocator) const; - - //=== allocator ===// - template - constexpr auto allocator(AllocatorFn allocator_fn) const; - - constexpr auto allocator() const - { - return allocator(_identity-fn_); - } - }; - - template - constexpr _as-container_ as_list; - - template - constexpr _as-container_ as_collection; -} ----- - -[.lead] -Callbacks and sink to construct the given `Container`. - -`as_list` is used for positional containers like `std::vector`. -It calls `.push_back()` and `.emplace_back()`. -`as_collection` is used for non-positional containers like `std::set`. -It calls `.insert()` and `.emplace()`. - -As a callback, they have the following overloads: - -`(lexy::nullopt)`:: - Returns an empty container by default constructing it. -`(Container&& container)`:: - Forwards an existing container unchanged. -`(Args&&... args)`:: - Repeatedly calls `.push_back()`/`.insert()` on an empty container; - if called with `N` arguments, the resulting container will contain `N` items. - If `.reserve(sizeof...(args))` is well-formed, calls that first. - The final container is returned. -`(const typename Container::allocator_type& allocator, Args&&... args)`:: - Same as above, but constructs the empty container using the given `allocator`. - -As a sink, `.sink()` can be called with zero arguments or with one argument of type `Container::allocator_type`. -In the first case, it default constructs an empty container. -In the second case, it constructs it using the allocator. -The resulting sink callback has the following overloads and returns the finished container: - -`(T&& object)`:: - Calls `.push_back()`/`.insert()` on the container. -`(Args&&... args)`:: - Calls `.emplace_back()`/`.emplace()` on the container. - -The `.allocator()` function takes a function that obtains the allocator from the parse state. -If the function is not provided, it uses the parse state itself as the allocator. -It returns a new callback and sink that accepts the parse state. -It then has the same overloads and behaviors, except that it will always use the allocator obtained via the `allocator_fn` from the parse state. -As a callback, this behavior is similar to {{% docref "lexy::bind" %}} where the allocator is bound via {{% docref "lexy::parse_state" %}}. -As a sink, this behavior is similar to {{% docref "lexy::bind_sink" %}} where the allocator is bound via {{% docref "lexy::parse_state" %}}. - -{{% godbolt-example "as_list" "Construct a list of integers" %}} - -{{% godbolt-example "as_list-allocator" "Construct a list of integers with a custom allocator" %}} - -[#concat] -== Callback and sink `lexy::concat` - -{{% interface %}} ----- -namespace lexy -{ - template - struct _concat-impl_ - { - using return_type = Container; - - constexpr Container operator()() const; - constexpr Container operator()(lexy::nullopt) const; - constexpr Container operator()(Container&& head, Container&&... tail) const; - - constexpr _sink_ auto sink() const; - }; - - template - constexpr _concat-impl_ concat; -} ----- - -[.lead] -Callback and sink that concatenates multiple containers. - -As a callback, it accepts zero or more existing containers, and will concatenate them together. -This is done by repeatedly calling `.append()` or `.push_back()` on the first container. - -As a sink, it creates a default constructed container object as the current result. -It can then be invoked with a single container object. -If the current result is still empty, the new container is move assigned into it. -Otherwise, the new container is appended by calling `.append()` or `.push_back()`. - -{{% godbolt-example "concat" "Construct a list of integers from a list of list of integers" %}} - -[#collect] -== Sink `lexy::collect` - -{{% interface %}} ----- -namespace lexy -{ - constexpr _sink_<> auto collect(_callback_ auto&& callback) - requires std::is_void_v<_callback-return-type_>; - - template - constexpr _sink_<> auto collect(_callback_ auto&& callback); - requires !std::is_void_v<_callback-return-type_>; -} ----- - -[.lead] -Turns a callback into a sink by collecting all results. - -The first overload requires that the `callback` returns `void`. -It returns a sink that repeatedly invokes `callback` and produces the number of invocations as a `std::size_t`. - -The second overload requires that the `callback` does not return `void`. -`.sink()` can be called with zero arguments or with one argument of type `Container::allocator_type`. -In the first case, it default constructs an empty container; in the second case, it constructs it using the allocator. -The sink callback just forwards to `callback` and adds the result to the container by calling `.push_back()`. -The final container is returned. - -NOTE: See {{% docref "lexy::callback" %}} for the inverse operation that turns a sink into a callback. - -TIP: Use `collect` for the error callback. It will collect all errors into a single container. - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/fold.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/fold.adoc deleted file mode 100644 index 92e5496bb3..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/fold.adoc +++ /dev/null @@ -1,80 +0,0 @@ ---- -header: "lexy/callback/fold.hpp" -entities: - "lexy::fold": fold - "lexy::fold_inplace": fold_inplace - "lexy::count": count ---- -:toc: left - -[.lead] -Sinks that fold over the items. - -[#fold] -== Sink `lexy::fold` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr _sink<>_ auto fold(Arg&& init, Op&& ... op); -} ----- - -[.lead] -Sink that folds over all arguments. - -When `sink()` is called, creates a `T result` by constructing it from `T(init)`, if that is well-formed, and invoking `init()` otherwise. -Every time the sink callback is invoked, folds the arguments via `result = std::invoke(make-overloaded(op...), std::move(result), args...)`. -The final value of `result` is returned by `finish()`. - -{{% godbolt-example "fold" "Parse a list of points and sum the x components" %}} - -NOTE: Usually with fold algorithms, `op` is a binary function. -As the `operator()` of the sink callback can take arbitrary arguments, this is not necessarily the case here. -The first argument will always be the current `result`, all other arguments are received from the sink callback. - -TIP: Use {{% docref "lexy::callback" %}} to use `fold` as a callback. - -[#fold_inplace] -== Sink `lexy::fold_inplace` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr _sink<>_ auto fold_inplace(Arg&& init, Op&& ... op); -} ----- - -[.lead] -Sink that folds over all arguments, modifying the current value. - -When `sink()` is called, creates a `T result` by constructing it from `T(init)`, if that is well-formed, and invoking `init()` otherwise. -Every time the sink callback is invoked, folds the arguments via `std::invoke(make-overloaded(op...), result, args...)`, -expecting that `op` modifies `result` to the new value. -The final value of `result` is returned by `finish()`. - -{{% godbolt-example "fold_inplace" "Parse a list of numbers, but store them in reverse" %}} - -NOTE: `lexy::fold` accepts `operator+`, `lexy::fold_inplace` accepts `operator+=`. - -[#count] -== Sink `lexy::count` - -{{% interface %}} ----- -namespace lexy -{ - constexpr _sink<>_ auto count = - = fold_inplace(0, [](std::size_t& result, auto&&...) { ++result; }); -} ----- - -[.lead] -Counts the number of invocation of the sink callback. - -It is entirely equivalent to the `lexy::fold_inplace` call specified above. - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/forward.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/forward.adoc deleted file mode 100644 index 593aa5be93..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/forward.adoc +++ /dev/null @@ -1,32 +0,0 @@ ---- -header: "lexy/callback/forward.hpp" -entities: - "lexy::forward": forward ---- - -[#forward] -== Callback `lexy::forward` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr _callback_ auto forward; - - template <> - constexpr _callback_ auto forward; -} ----- - -[.lead] -`lexy::forward` is a callback that forwards an existing object. - -The primary template accepts `const T&` and `T&&` and forwards them as a `T`. - -The specialization for `void` is both a callback and a sink. -As a callback it accepts no arguments or a single argument of type {{% docref "lexy::nullopt" %}}, and does nothing to return `void`. -As a sink, it can be invoked multiple times with the same arguments, doing nothing and finally returning `void`. - -{{% godbolt-example "true_false" "Forward the value of child productions" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/integer.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/integer.adoc deleted file mode 100644 index 7d69b5a65c..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/integer.adoc +++ /dev/null @@ -1,31 +0,0 @@ ---- -header: "lexy/callback/integer.hpp" -entities: - "lexy::as_integer": as_integer ---- - -[#as_integer] -== Callback `lexy::as_integer` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr _callback_ auto as_integer; -} ----- - -[.lead] -Creates an integer of type `T`. - -It is a callback with three overloads: - -`(const auto& value)`:: returns `T(value)`. -`(lexy::plus_sign, const auto& value)`:: returns `T(value)`. -`(lexy::minus_sign, const auto& value)`:: returns `T(-value)`. - -It is best used together with {{% docref "lexy::dsl::integer" %}} and {{% docref "lexy::dsl::sign" %}}. - -{{% godbolt-example sign "A number with an optional plus/minus sign" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/noop.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/noop.adoc deleted file mode 100644 index fb3cdd42fa..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/noop.adoc +++ /dev/null @@ -1,26 +0,0 @@ ---- -header: "lexy/callback/noop.hpp" -entities: - "lexy::noop": noop ---- - -[#noop] -== Callback and sink `lexy::noop` - -{{% interface %}} ----- -namespace lexy -{ - constexpr _callback_ auto noop; - constexpr _sink<>_ auto noop; -} ----- - -[.lead] -A callback and sink that ignores all arguments and returns `void`. - -As a callback, it can be called with arbitrary arguments that are all ignored. -As a sink, the sink callback also ignores all arguments. - -{{% godbolt-example "noop" "Ignore all errors produced during parsing" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/object.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/object.adoc deleted file mode 100644 index 0f55287b49..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/object.adoc +++ /dev/null @@ -1,58 +0,0 @@ ---- -header: "lexy/callback/object.hpp" -entities: - "lexy::construct": construct - "lexy::new_": new_ ---- -:toc: left - -[.lead] -Construct objects. - -[#construct] -== Callback `lexy::construct` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr _callback_ auto construct; - - template <> - constexpr _callback_ auto construct; -} ----- - -[.lead] -Construct an object of type `T`. - -The primary template accepts arbitrary arguments and returns `T(std::forward(args)...)` if that is well-formed, -otherwise `T{std::forward(args)...}`. -The specialization for `void` accepts no arguments and does nothing to return `void`. - -{{% godbolt-example "point" "Construct a point from two integers" %}} - -NOTE: `construct` supports both types with constructor as well as aggregates or built-in types. - -[#new_] -== Callback `lexy::new_` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr _callback_ auto new_; -} ----- - -[.lead] -Construct an object of type `T` on the heap. - -It accepts arbitrary arguments and calls `new T(std::forward(args)...)` if that is well-formed, -otherwise `new T{std::forward(args)...}`. -Then returns a pointer of the specified type as the result. - -{{% godbolt-example "new" "Construct a point on the heap and returns a `std::unique_ptr`" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/callback/string.adoc b/assembler/ext/src/lexy/docs/content/reference/callback/string.adoc deleted file mode 100644 index 66c4451a90..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/callback/string.adoc +++ /dev/null @@ -1,76 +0,0 @@ ---- -header: "lexy/callback/string.hpp" -entities: - "lexy::as_string": as_string ---- - -[#as_string] -== Callback and sink `lexy::as_string` - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr auto as_string; -} ----- - -[.lead] -Callback and sink to construct the given `String`. - -The {{% encoding %}} parameter is only relevant when it needs to encode a {{% docref "lexy::code_point" %}}. -By default, it is deduced from the character type of `String`. -The character type of `Encoding` must be compatible with the one from `String`, i.e. the latter must be the primary or one of the secondary character types. - -As a callback, it has the following overloads; `A` is `typename String::allocator_type`: - -`(lexy::nullopt)`:: - Returns an empty string by default-constructing it. -`(String&& str)`:: - Forwards an existing string unchanged. -`(lexy::lexeme lex)` and `(const A& allocator, lexy::lexeme lex)`:: - Requires that the character type of `lex` is compatible with the character type of `Encoding`. - If the iterator type of `lex` is a pointer whose value type is the same as the character type of `String`, - returns `String(lex.data(), lex.size())`; - otherwise, returns `String(lex.begin(), lex.end())`. - The second version passes the `allocator` as last parameter. -`(Iterator begin, Iterator end)` and `(const A& allocator, Iterator begin, Iterator end)`:: - Constructs a string from an iterator range directly. -`(lexy::code_point cp)` and `(const A& allocator, lexy::code_point cp)`:: - Encodes `cp` in the `Encoding`, which must be ASCII, UTF-8, UTF-16, or UTF-32. - Returns `String(begin, end)`, where `[begin, end)` is an iterator range to the encoded representation of `cp`. - The second version passes the `allocator` as last parameter. - -As a sink, `.sink()` can be called with zero arguments or with one argument of type `String::allocator_type`. -In the first case, it default constructs an empty container. -In the second case, it constructs it using the allocator. -The resulting sink callback has the following overloads and returns the finished string: - -`(CharT c)`:: - Calls `.push_back(c)` on the resulting string. - Requires that this is well-formed. -`(String&& str)`:: - Calls `.append(std::move(str))` on the resulting string. -`(lexy::lexeme lex)`:: - Requires that the character type of `lex` is compatible with the character type of `Encoding`. - Calls `.append(lex.begin(), lex.end())` on the resulting string. -`(Iterator begin, Iterator end)`:: - Calls `.append(begin, end)`. -`(lexy::code_point cp)`:: - Encodes `cp` in the `Encoding`, which must be ASCII, UTF-8, UTF-16, or UTF-32. - Calls `.append(begin, end)`, where `[begin, end)` is an iterator range to the encoded representation of `cp`, on the resulting string. - -It also provides a member function `.case_folding()` that accepts a case folding DSL object like {{% docref "lexy::dsl::ascii::case_folding" %}} or {{% docref "lexy::dsl::unicode::simple_case_folding" %}}. -It returns a callback where each resulting string will be case folded before returned. -It requires that `Encoding` is ASCII, UTF-8, UTF-16, or UTF-32. - -{{% godbolt-example list_sep "Build a list of characters" %}} - -{{% godbolt-example quoted_escape "Parse a string literal" %}} - -{{% godbolt-example identifier_case_folded "Parse a case-insensitive identifier" %}} - -NOTE: `lexy::as_string` is a valid callback that can convert a {{% docref "lexy::lexeme" %}} to a `std::string_view`, -provided that the character types are an exact match and that the iterators of the input are pointers. - diff --git a/assembler/ext/src/lexy/docs/content/reference/code_point.adoc b/assembler/ext/src/lexy/docs/content/reference/code_point.adoc deleted file mode 100644 index 60cccec9b8..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/code_point.adoc +++ /dev/null @@ -1,223 +0,0 @@ ---- -header: "lexy/code_point.hpp" -entities: - "lexy::code_point": code_point - "lexy::code_point::general_category_t": general_category - "lexy::simple_case_fold": simple_case_fold ---- -:toc: left - -[.lead] -Vocabulary types for code points, and simple Unicode algorithms. - -[#code_point] -== Class `lexy::code_point` - -{{% interface %}} ----- -namespace lexy -{ - class code_point - { - public: - constexpr code_point() noexcept; - constexpr explicit code_point(char32_t value) noexcept; - - constexpr char32_t value() const noexcept; - - //=== classification ===// - constexpr bool is_ascii() const noexcept; - constexpr bool is_bmp() const noexcept; - constexpr bool is_valid() const noexcept; - - constexpr bool is_control() const noexcept; - constexpr bool is_surrogate() const noexcept; - constexpr bool is_private_use() const noexcept; - constexpr bool is_noncharacter() const noexcept; - - constexpr bool is_scalar() const noexcept; - - //=== general category ===// - enum general_category_t; - - constexpr general_category_t general_category() const; - - struct _gc-group_; - // _gc-group_ constants, see below. - - //=== comparison ===// - friend constexpr bool operator==(code_point lhs, code_point rhs) noexcept; - friend constexpr bool operator!=(code_point lhs, code_point rhs) noexcept; - }; -} ----- - -[.lead] -A single Unicode https://en.wikipedia.org/wiki/Code_point[code point]. - -It is a simple wrapper over a `char32_t`. - -=== Constructors - -{{% interface %}} ----- -constexpr code_point() noexcept; <1> -constexpr explicit code_point(char32_t value) noexcept; <2> ----- -<1> Creates an invalid code point. -<2> Creates the code point with the specified value. - -=== Classification - -{{% interface %}} ----- -constexpr bool is_ascii() const noexcept; <1> -constexpr bool is_bmp() const noexcept; <2> -constexpr bool is_valid() const noexcept; <3> ----- -<1> Returns `true` if the code point is ASCII (`0x00-0x7F`), `false` otherwise. -<2> Returns `true` if the code point is in the link:https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane[Unicode BMP] (`0x0000-0xFFFF`), `false` otherwise. -<3> Returns `true` if the code point is a value in the Unicode codespace (`<= 0x10'FFFF`), `false` otherwise. - -{{% interface %}} ----- -constexpr bool is_control() const noexcept; <1> -constexpr bool is_surrogate() const noexcept; <2> -constexpr bool is_private_use() const noexcept; <3> -constexpr bool is_noncharacter() const noexcept; <4> ----- -<1> Returns `true` if the code point's general category is `Cc` (control), `false` otherwise. -<2> Returns `true` if the code point's general category is `Cs` (surrogate), `false` otherwise. -<3> Returns `true` if the code point's general category is `Co` (private-use), `false` otherwise. -<4> Returns `true` if the code point's general category is `Cn` (not assigned) and the code point is not reserved, `false` otherwise. - -NOTE: Those are all of the link:https://en.wikipedia.org/wiki/Unicode_character_property#General_Category[general categories] that are stable. -As such, they are available without the Unicode database. - -{{% interface %}} ----- -constexpr bool is_scalar() const noexcept -{ - return is_valid() && !is_surrogate(); -} ----- - -[.lead] -Returns `true` if the code point is valid and not a surrogate, `false` otherwise. - -[#general_category] -=== General Category - -{{% interface %}} ----- -enum general_category_t -{ - // Enum values written in the same line are aliases. - - Lu, uppercase_letter, - Ll, lowercase_letter, - Lt, titlecase_letter, - Lm, modifier_letter, - Lo, other_letter, - - Mn, nonspacing_mark, - Mc, spaing_mark, - Me, enclosing_mark, - - Nd, decimal_number, - Nl, letter_number, - No, other_number, - - Pc, connector_punctuation, - Pd, dash_punctuation, - Ps, open_punctuation, - Pe, closing_punctuation, - Pi, initial_puncutation, - Pf, final_puncutation, - Po, other_punctuation, - - Sm, math_symbol, - Sc, currency_symbol, - Sk, modifier_symbol, - So, other_symbol, - - Zs, space_separator, - Zl, line_separator, - Zp, paragraph_separator, - - Cc, control, - Cf, format, - Cs, surrogate, - Co, private_use, - Cn, unassigned, -}; - -constexpr general_category_t general_category() const; ----- - -[.lead] -Returns the link:https://en.wikipedia.org/wiki/Unicode_character_property#General_Category[general category] of the code point. - -This function requires the Unicode database. - -{{% interface %}} ----- -struct _gc-group_ -{ - friend constexpr bool operator==(_gc-group_ group, general_category_t cat); - friend constexpr bool operator==(general_category_t cat, _gc-group_ group); - - friend constexpr bool operator!=(_gc-group_ group, general_category_t cat); - friend constexpr bool operator!=(general_category_t cat, _gc-group_ group); -}; - -static constexpr _gc-group_ LC; // LC = Lu, Ll, Lt -static constexpr _gc-group_ cased_letter = LC; - -static constexpr _gc-group_ L; // L = Lu, Ll, Lt, Lm, Lo -static constexpr _gc-group_ letter = L; - -static constexpr _gc-group_ M; // M = Mn, Mc, Me -static constexpr _gc-group_ mark = M; - -static constexpr _gc-group_ N; // N = Nd, Nl, No -static constexpr _gc-group_ number = N; - -static constexpr _gc-group_ P; // P = Pc, Pd, Ps, Pe, Pi, Pf, Po -static constexpr _gc-group_ punctuation = P; - -static constexpr _gc-group_ Z; // Z = Zs, Zl, Zp -static constexpr _gc-group_ separator = Z; - -static constexpr _gc-group_ C; // C = Cc, Cf, Cs, Co, Cn -static constexpr _gc-group_ other = C; ----- - -[.lead] -Tag objects to check for a specific Unicode category. -They have an overloaded `operator==` and `operator!=` with the `general_category_t` and can be used to check that a code point category is in the group. - -This can be done without the Unicode database, but the category of a code point requires the Unicode database. - -[#simple_case_fold] -== Function `lexy::simple_case_fold` - -{{% interface %}} ----- -namespace lexy -{ - constexpr code_point simple_case_fold(code_point cp) noexcept; -} ----- - -[.lead] -Returns the code point after performing Unicode simple https://unicode.org/faq/casemap_charprop.html#2[case folding]. - -Informally, it converts `cp` to its lower case variant if it is a letter with casing, and returns `cp` unchanged otherwise (there are exceptions where a character is case folded to an upper case letter instead). -This is used for case-insensitive comparison. - -Unlike full case folding, simple case folding will always map one code point to another code point. -This causes different behavior in some situations. -For example, under full case folding `ẞ` (U+1E9E, LATIN CAPITAL LETTER SHARP S) is folded to `ss`, but to `ß` (U+00DF, LATIN CAPITAL LETTER SMALL S) under simple case folding. -As such, using full case folding `Maß` and `MASS` are identical, but not under simple case folding. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/_index.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/_index.adoc deleted file mode 100644 index b9e3636a13..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/_index.adoc +++ /dev/null @@ -1,313 +0,0 @@ ---- -layout: single -header: "lexy/dsl.hpp" -entities: - "rule": doc ---- -:toc: left - -[.lead] -The rule DSL for specifying the grammar. - -[source,cpp,subs="+quotes"] ----- -template -concept _rule_ = …; ----- - -The grammar in lexy is specified in several productions, where each one defines an associated _rule_. -This rule is an object built from the objects and functions of namespace `lexy::dsl` that defines some (implementation-defined) parsing function. -Parsing a rule takes the reader, which remembers the current position of the input, and the context, which stores information about the current production and whitespace rules, and is responsible for handling errors and values. - -Parsing can have one of the following results: - -* Parsing can succeed. - Then it consumes some input by advancing the reader position and produces zero or more values. -* Parsing can fail. - Then it reports an error, potentially after having consumed some input but without producing values. - The parent rule can react to the failure by recovering from it or they fail itself. -* Parsing can fail, but then recover. - Then it has reported an error, but now it has consumed enough input to be in a known good state and parsing continues normally. - See {{% docref "error recovery" %}} for details. - -A {{% branch-rule %}} is a special kind of rule that has an easy to check condition. -They are used to guide decisions in the parsing algorithm. -Every branch rule defines some (implementation defined) branch parsing function. -It mostly behaves the same as the normal parse rule, but can have one additional result: -branch parsing can _backtrack_. -If it backtracks, it hasn't consumed any input, raised errors or produced values. -The parsing algorithm is then free to try another branch. - -NOTE: The idea is that a branch rule can relatively quickly decide whether or not it should backtrack. -If a branch rule does not backtrack, but fails instead, this failure is propagated and the parsing algorithm does not try another branch. - -A {{% token-rule %}} is a special kind of rule that describes the atomic elements. -Parsing them never produces any values and can happen easily, -as such they're also branch rules where the entire rule is used as the condition. -Because they're atomic elements of the input, they also participate in {{% docref "whitespace" "automatic whitespace skipping" %}}: -after every token, lexy will automatically skip whitespace, if one has been defined. - -The parse context stores state that can be accessed during parsing. -This includes things like the current recursion depth, see {{% docref "lexy::dsl::recurse" %}}, -whether or not automatic whitespace skipping is currently enabled, see {{% docref whitespace "whitespace skipping" %}}, -but also arbitrary user-defined variables, see {{% docref "lexy::dsl::context_flag" %}}, {{% docref "lexy::dsl::context_counter" %}}, and {{% docref "lexy::dsl::context_identifier" %}}. - -When a rule modifies the context during parsing, by adding an additional context variable for example, -this modification is available for all following rules in the current production and all child productions. -In particular, the modification is no longer visible in any parent production. -If a rule is parsed in a loop, e.g. by {{% docref "lexy::dsl::loop" %}} or {{% docref "lexy::dsl::list" %}}, -any context modification does not persist between loop iterations, and is also not available outside the loop. - -== How to read the DSL documentation footnote:[link:https://xkcd.com/1343[obligatory XKCD]] - -The behavior of a rule is described by the following sections. - -Matching/parsing:: - This section describes what input is matched for the rule to succeed, and what is consumed. - For token rules it is called "matching", otherwise "parsing". -+ -It often delegates to the behavior of other rules: -Here, the term "parsing" refers to the parsing operation of a rule, -"branch parsing" or "try to parse" refers to the special parsing operation of a branch rule, which can backtrack, -"matching" refers to the parsing operation of a token rule, which cannot produce values, -and "try matching" refers to the branch parsing operation of a token rule, which cannot produce values or raise errors. -Branch parsing:: - This section describes what input is matched, consumed, and leads to a backtracking for a branch rule. - Note that a rule can parse something different here than during non-branch parsing. -Errors:: - This section describes what errors are raised, when, and where. - It also describes whether the rule can recover after the error. -Values:: - This section describes what values are produced during a successful parsing operation. - It is omitted for token rules, which never produce values. -Parse tree:: - This section describes what nodes are created in the `lexy::parse_tree`. - If omitted, a token rule creates a single token node covering everything consumed, - and a rule produces no extra nodes besides the ones created by the other rules it parses. - -If a rule parses another rule in a new context (e.g. {{% docref "lexy::dsl::peek" %}}), -the other rule does not have access to context variables, and any context modification is not visible outside of the rule. - -== The rule DSL - -[%collapsible] -.Primitive rules -==== -{{% docref "lexy::dsl::any" %}}:: - match anything -{{% docref "lexy::dsl::eof" %}}:: - match EOF -{{% docref "lexy::dsl::newline" %}} and {{% docref "lexy::dsl::eol" %}}:: - match the end of a line -==== - -[%collapsible] -.Literal rules -==== -{{% docref "lexy::dsl::lit_c" %}}:: - match a single character -{{% docref "lexy::dsl::lit" %}} and {{% docref "LEXY_LIT" %}}:: - match character sequences -{{% docref "lexy::dsl::lit_b" %}}:: - match a sequence of bytes -{{% docref "lexy::dsl::lit_cp" %}}:: - match a code point with the specified value -{{% docref "punctuators" %}}:: - match common punctuation -{{% docref "lexy::dsl::literal_set" %}} and {{% docref "LEXY_LITERAL_SET" %}}:: - match one of the specified literals -{{% docref "lexy::dsl::followed_by" %}} and {{% docref "lexy::dsl::not_followed_by" %}}:: - ensure a literal is (not) followed by a char class -{{% docref "lexy::dsl::ascii::case_folding" %}} and {{% docref "lexy::dsl::unicode::simple_case_folding" %}}:: - match a literal case-insensitively -==== - -[%collapsible] -.Char classes -==== -{{% docref "lexy::dsl::code_point" %}}:: - match specific Unicode code points -{{% docref "lexy::dsl::ascii" %}}:: - match ASCII char classes -{{% docref "lexy::dsl::unicode" %}}:: - match Unicode char classes -{{% docref "lexy::dsl::operator/ (char class)" %}}, {{% docref "lexy::dsl::operator- (unary)" %}}, {{% docref "lexy::dsl::operator-" %}}, {{% docref "lexy::dsl::operator&" %}}:: - combine char classes -{{% docref "LEXY_CHAR_CLASS" %}}:: - create a named char class -==== - -[%collapsible] -.Branch conditions -==== -{{% docref "lexy::dsl::operator>>" %}}:: - add a branch condition to a rule -{{% docref "lexy::dsl::else_" %}}:: - branch condition that is always taken -{{% docref "lexy::dsl::peek" %}} and {{% docref "lexy::dsl::peek_not" %}}:: - check whether something matches without consuming it -{{% docref "lexy::dsl::lookahead" %}}:: - check whether something matches somewhere in the input without consuming it -==== - -[%collapsible] -.Combinators -===== -{{% docref "lexy::dsl::token" %}}:: - turn a rule into a token -{{% docref "lexy::dsl::operator+" %}}:: - parse a sequence of rules -{{% docref "lexy::dsl::operator|" %}}:: - parse one of the specified (branch) rules -{{% docref "lexy::dsl::combination" %}} and {{% docref "lexy::dsl::partial_combination" %}}:: - parse all (some) of the (branch) rules in arbitrary order -{{% docref "lexy::dsl::if_" %}} and {{% docref "lexy::dsl::opt" %}}:: - parse a branch rule if its condition matches -{{% docref "lexy::dsl::loop" %}}:: - parse a rule repeatedly -{{% docref "lexy::dsl::while_" %}} and {{% docref "lexy::dsl::while_one" %}}:: - parse a branch rule while its condition matches -{{% docref "lexy::dsl::list" %}}:: - parse a list of things -{{% docref "lexy::dsl::times" %}} and {{% docref "lexy::dsl::repeat" %}}:: - parse a rule `N` times -{{% docref "lexy::dsl::until" %}}:: - skip everything until a rule matches -===== - - -[%collapsible] -.Brackets and delimited -===== -{{% docref "lexy::dsl::terminator" %}}:: - parse something that ends with a terminator -{{% docref "lexy::dsl::brackets" %}}:: - parse something surrounded by brackets -{{% docref "lexy::dsl::delimited" %}} and {{% docref "lexy::dsl::escape" %}}:: - parse everything between two delimiters, with optional escape sequences -===== - -[%collapsible] -.Productions -==== -{{% docref "lexy::dsl::p" %}} and {{% docref "lexy::dsl::recurse" %}}:: - parse another production -{{% docref "lexy::dsl::inline_" %}}:: - parse another production's rule inline -{{% docref "lexy::dsl::return_" %}}:: - exit early from parsing a production -==== - -[%collapsible] -.Values -===== -{{% docref "lexy::dsl::capture" %}}:: - capture everything consumed by a token rule -{{% docref "lexy::dsl::position" %}}:: - produce the current input position -{{% docref "lexy::dsl::nullopt" %}}:: - produce an empty placeholder value -{{% docref "lexy::dsl::member" %}}:: - parse something into a member variable -{{% docref "lexy::dsl::scan" %}}:: - parse a completely user-defined rule -===== - -[%collapsible] -.Errors and error recovery -===== -{{% docref "lexy::dsl::error" %}}:: - explicitly raise an error -{{% docref "lexy::dsl::must" %}}:: - raise an error if a branch backtracks -{{% docref "lexy::dsl::try_" %}}:: - recover from a failed rule -{{% docref "lexy::dsl::recover" %}}:: - recover by looking and then continuing with some other rule -{{% docref "lexy::dsl::find" %}}:: - recover by looking for synchronization tokens -===== - -[%collapsible] -.Whitespace -==== -{{% docref "lexy::dsl::whitespace" %}}:: - explicitly skip whitespace -{{% docref "lexy::dsl::no_whitespace" %}}:: - do not skip whitespace -==== - -[%collapsible] -.Identifiers -==== -{{% docref "lexy::dsl::identifier" %}}:: - parse an identifier -{{% docref "lexy::dsl::keyword" %}}:: - parse a keyword -{{% docref "lexy::dsl::symbol" %}}:: - parse one of the specified symbols and produce their value -==== - -[%collapsible] -.Numbers -==== -{{% docref "lexy::dsl::zero" %}}:: - parse zero -{{% docref "lexy::dsl::digit" %}}:: - parse a digit -{{% docref "lexy::dsl::digits" %}}:: - parse one or more digits -{{% docref "lexy::dsl::n_digits" %}}:: - parse N digits -{{% docref "lexy::dsl::integer" %}}:: - convert digits to an integer -{{% docref "lexy::dsl::sign" %}}, {{% docref "lexy::dsl::plus_sign" %}} and {{% docref "lexy::dsl::minus_sign" %}}:: - parse a sign -{{% docref "lexy::dsl::code_point_id" %}}:: - convert N digits into a code point -==== - -[%collapsible] -.Operator precedence parsing -==== -{{% docref "lexy::dsl::op" %}}:: - parse an operator -{{% docref "lexy::dsl::operator/ (operator)" %}}:: - parse one of multiple operators -{{% docref "expression" %}}:: - parse an expression consisting of multiple operators -==== - -[%collapsible] -.Context-sensitive parsing -==== -{{% docref "lexy::dsl::context_flag" %}}:: - a boolean flag -{{% docref "lexy::dsl::context_counter" %}}:: - an integer counter -{{% docref "lexy::dsl::context_identifier" %}}:: - an identifier variable -==== - -[%collapsible] -.Byte input -==== -{{% docref "lexy::dsl::bytes" %}} and {{% docref "lexy::dsl::padding_bytes" %}}:: - parse `N` bytes -{{% docref "lexy::dsl::bint8" %}}, {{% docref "lexy::dsl::bint16" %}}, ... :: - parse a little/big endian integer -{{% docref "lexy::dsl::bits" %}}:: - parse a byte with specific bit patterns -{{% docref "lexy::dsl::bom" %}}:: - parse a byte-order mark (BOM) -==== - -[%collapsible] -.Input and action specific rules -==== -{{% docref "lexy::dsl::argv_separator" %}}:: - match the argument separator of a {{% docref "lexy::argv_input" %}} -{{% docref "lexy::dsl::debug" %}}:: - generate a debug event that is visualized by {{% docref "lexy::trace" %}} -==== - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/any.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/any.adoc deleted file mode 100644 index 7d5c99673e..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/any.adoc +++ /dev/null @@ -1,34 +0,0 @@ ---- -header: "lexy/dsl/any.hpp" -entities: - "lexy::dsl::any": any ---- - -[#any] -== Token rule `lexy::dsl::any` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _token-rule_ auto any; -} ----- - -[.lead] -`any` is a {{% token-rule %}} that matches anything. - -Matching:: - Consumes the entire input. - If the rule is matched in a context where the reader has been artificially delimited, - consumes only until the end of the partial input is reached. -Errors:: - None. -Parse tree:: - Single token node with the {{% docref "lexy::predefined_token_kind" %}} `lexy::any_token_kind`. - -{{% playground-example any "Match literally any input" %}} - -CAUTION: `any` does not care what input it consumes; it can be anything, including ill-formed Unicode. -To restrict the input that is consumed, use {{% docref "lexy::dsl::while_" %}} instead. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/ascii.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/ascii.adoc deleted file mode 100644 index 9aee7b8dc4..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/ascii.adoc +++ /dev/null @@ -1,139 +0,0 @@ ---- -header: "lexy/dsl/ascii.hpp" -entities: - "lexy::dsl::ascii": doc - "lexy::dsl::ascii::control": class - "lexy::dsl::ascii::blank": class - "lexy::dsl::ascii::newline": class - "lexy::dsl::ascii::other_space": class - "lexy::dsl::ascii::space": class - "lexy::dsl::ascii::digit": class - "lexy::dsl::ascii::lower": class - "lexy::dsl::ascii::upper": class - "lexy::dsl::ascii::alpha": class - "lexy::dsl::ascii::alpha_underscore": class - "lexy::dsl::ascii::alpha_digit": class - "lexy::dsl::ascii::alnum": class - "lexy::dsl::ascii::word": class - "lexy::dsl::ascii::alpha_digit_underscore": class - "lexy::dsl::ascii::punct": class - "lexy::dsl::ascii::graph": class - "lexy::dsl::ascii::print": class - "lexy::dsl::ascii::character": class - "lexy::dsl::ascii::one_of": one_of - "LEXY_ASCII_ONE_OF": one_of ---- -:toc: left - -[.lead] -Char class rules for matching the ASCII char classes. - -[#class] -== ASCII char classes - -{{% interface %}} ----- -namespace lexy::dsl -{ - namespace ascii - { - constexpr _char-class-rule_ auto control; - - constexpr _char-class-rule_ auto blank; - constexpr _char-class-rule_ auto newline; - constexpr _char-class-rule_ auto other_space; - constexpr _char-class-rule_ auto space; - - constexpr _char-class-rule_ auto digit; - - constexpr _char-class-rule_ auto lower; - constexpr _char-class-rule_ auto upper; - constexpr _char-class-rule_ auto alpha; - constexpr _char-class-rule_ auto alpha_underscore; - - constexpr _char-class-rule_ auto alpha_digit; - constexpr _char-class-rule_ auto alnum = alpha_digit; - - constexpr _char-class-rule_ auto word; - constexpr _char-class-rule_ auto alpha_digit_underscore = word; - - constexpr _char-class-rule_ auto punct; - - constexpr _char-class-rule_ auto graph; - constexpr _char-class-rule_ auto print; - - constexpr _char-class-rule_ auto character; - } -} ----- - -[.lead] -These {{% char-class-rule %}}s match one ASCII character from a char class, -as specified in the table below. - -[%collapsible] -.The char classes -==== -|=== -| Token Rule | Char Class | `` function (C locale) - -| `control` | `0x00-0x1F`, `\x7F` | `std::iscntrl()` -| `blank` | `' '` (space) or `'\t'` | `std::isblank()` -| `newline` | `'\n'` or `'\r'` | n/a -| `other_space` | `'\f'` or `'\v\` | n/a -| `space` | `blank`, `newline`, `other_space` | `std::isspace()` -| `digit` | `0123456789` | `std::isdigit()` -| `lower` | `abcdefghijklmnopqrstuvwxyz` | `std::islower()` -| `upper` | `ABCDEFGHIJKLMNOPQRSTUVWXYZ` | `std::isupper()` -| `alpha` | `lower`, `upper` | `std::isalpha()` -| `alpha_underscore` | `lower`, `upper`, `'_'` | n/a -| `alpha_digit` | `lower`, `upper`, `digit` | `std::isalnum()` -| `word` | `lower`, `upper`, `digit`, `'_'` | n/a -| `punct` | ``!"#$%&'()*+,-./:;\<\=>?@[\]^_`{\|}~`` | `std::ispunct()` -| `graph` | `alpha_digit`, `punct` | `std::isgraph()` -| `print` | `alpha_digit`, `punct`, `' '` (space) | `std::ispunct()` -| `character` | any ASCII character | n/a -|=== -==== - -{{% playground-example identifier "A C-like identifier" %}} - -{{% playground-example whitespace "Allow ASCII whitespace between tokens" %}} - -NOTE: The only difference between `lexy::dsl::ascii::digit` and {{% docref "lexy::dsl::digit" "`lexy::dsl::digit`" %}} is the name of the character class in the error. - -CAUTION: Differentiate between `lexy::dsl::ascii::newline`, which matches `\r` or `\n`, and {{% docref "lexy::dsl::newline" %}}, which matches `\r\n` or `\n`! - -CAUTION: As token rules, they match {{% docref whitespace whitespace %}} immediately following the character. -As such, the rule is best used in contexts where automatic whitespace skipping is disabled. -They can safely be used as part of the whitespace definition. - -TIP: The equivalent of `std::isxdigit()` is {{% docref "lexy::dsl::digit" "`lexy::dsl::digit`" %}}. - -TIP: Use {{% docref "lexy::dsl::unicode" %}} for the equivalent Unicode character classes. - -[#one_of] -== Char class rule `lexy::dsl::ascii::one_of` - -{{% interface %}} ----- -namespace lexy::dsl::ascii -{ - template - constexpr _char-class-rule_ auto one_of; -} - -#define LEXY_ASCII_ONE_OF(Str) lexy::dsl::ascii::one_of ----- - -[.lead] -`one_of` is a {{% char-class-rule %}} that matches one of the specified ASCII characters. -Its name is `Str`. - -The macro `LEXY_ASCII_ONE_OF(Str)` is equivalent to `one_of`, except that it also works on older compilers that do not support C++20's extended NTTPs. -Use this instead of `one_of` if you need to support them. - -{{% playground-example "one_of" "Match the name of a musical note." %}} - -NOTE: It is impossible to match the null character using `one_of`. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/bits.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/bits.adoc deleted file mode 100644 index 314325c537..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/bits.adoc +++ /dev/null @@ -1,103 +0,0 @@ ---- -header: "lexy/dsl/byte.hpp" -entities: - "lexy::dsl::bit": doc - "lexy::dsl::bit::_0": bit01 - "lexy::dsl::bit::_1": bit01 - "lexy::dsl::bit::nibble": bit_nibble - "lexy::dsl::bit::_": bit_any - "lexy::dsl::bit::any": bit_any - "lexy::dsl::bits": bits ---- -:toc: left - -[.lead] -Rules that match specific bits. - -The inputs all work on byte boundaries, so it is not possible to match and consume individual bits. -However, the {{% docref "lexy::dsl::bits" %}} rule allows consuming 8 (specific) bits at a time. -To specify bit value, there are special bit rules in namespace `lexy::dsl::bit`. - -[#bit01] -== Bit rules `lexy::dsl::bit::_0` and `lexy::dsl::bit::_1` - -{{% interface %}} ----- -namespace lexy::dsl::bit -{ - constexpr _bit-rule_ auto _0; - constexpr _bit-rule_ auto _1; -} ----- - -[.lead] -`_0` and `_1` are bit rules that match a zero/one bit. - -They specify one bit each. - -[#bit_nibble] -== Bit rule `lexy::dsl::bit::nibble` - -{{% interface %}} ----- -namespace lexy::dsl::bit -{ - template - constexpr _bit-rule_ auto nibble; -} ----- - -[.lead] -`nibble` is a bit rule that matches a specific nibble.e. four bits. - -It requires that `0 <= Value <= 0xF`. -It then matches the specified four bits of `Value`. - -[#bit_any] -== Bit rules `lexy::dsl::bit::any` and `lexy::dsl::bit::_` - -{{% interface %}} ----- -namespace lexy::dsl::bit -{ - template - constexpr _bit-rule_ auto any; - - constexpr _bit-rule_ auto _ = any<1>; -} ----- - -[.lead] -`any` is a bit rule that matches `N > 0` bits of arbitrary value. - -It specifies `N` bits. - -== Token rule `lexy::dsl::bits` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _token-rule_ auto bits(_bit-rule_ auto ... bits); -} ----- - -[.lead] -`bits` is a {{% token-rule %}} that matches a byte with the specified bit values. - -Requires:: - In total, `bits` specify exactly eight bit values. - The {{% encoding %}} is `lexy::byte_encoding`. -Matching:: - Matches and consumes one byte. - It then checks that the byte has the specified bits, by applying each bit rule in turn. - From left to right, bit rules specify the most significant bit (e.g. the sign bit) down to the least significant bit (e.g. the even/odd bit). -Errors:: - {{% docref "lexy::expected_char_class" %}} (`"bits"`): - if the input was at EOF or the byte value does not match the pattern specified by the bits. - The rule then fails. - -{{% godbolt-example bits "Manually match a UTF-8 code point" %}} - -TIP: Combine it with e.g. {{% docref "lexy::dsl::bint8" %}} to match an integer with specified bits set. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/bom.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/bom.adoc deleted file mode 100644 index 1ca9e0b46b..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/bom.adoc +++ /dev/null @@ -1,46 +0,0 @@ ---- -header: "lexy/dsl/bom.hpp" -entities: - "lexy::dsl::bom": bom ---- - -[#bom] -== Literal rule `lexy::dsl::bom` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template - constexpr _literal-rule_ auto bom; -} ----- - -[.lead] -`bom` is a {{% literal-rule %}} that matches the https://en.wikipedia.org/wiki/Byte_order_mark[byte order mark (BOM)] of the given {{% encoding %}} in the given {{% docref "lexy::encoding_endianness" %}}. - -It is equivalent to the {{% docref "lexy::dsl::lit_b" %}} rule given in the table above. -If the combination of `Encoding` and `Endianness` is not listed, it succeeds without matching anything. - -[%collapsible] -.The possible BOMs -==== -|=== -| Encoding | Endianness | BOM - -| UTF-8 | _ignored_ | `lit_b<0xEF, 0xBB, 0xBF>` -| UTF-16 | little | `lit_b<0xFF, 0xFE>` -| UTF-16 | big | `lit_b<0xFE, 0xFF>` -| UTF-32 | little | `lit_b<0xFF, 0xFE, 0x00, 0x00>` -| UTF-32 | big | `lit_b<0x00, 0x00, 0xFE, 0xFF>` - -|=== -==== - -{{% godbolt-example bom "Skip an optional UTF-8 BOM" %}} - -CAUTION: As a token rule, it matches whitespace immediately following the BOM. -As such, the rule is best used in contexts where automatic whitespace skipping is disabled. - -NOTE: When using `lexy::read_file()` as input, BOM has been taken care of by default. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/brackets.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/brackets.adoc deleted file mode 100644 index 46d51c491c..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/brackets.adoc +++ /dev/null @@ -1,157 +0,0 @@ ---- -header: "lexy/dsl/brackets.hpp" -entities: - "lexy::dsl::brackets": brackets - "lexy::dsl::round_bracketed": brackets-predefined - "lexy::dsl::square_bracketed": brackets-predefined - "lexy::dsl::curly_bracketed": brackets-predefined - "lexy::dsl::angle_bracketed": brackets-predefined - "lexy::dsl::parenthesized": brackets-predefined ---- -:toc: left - -[.lead] -Rules for parsing bracketed or parenthesized expressions. - -[#brackets] -== Rule DSL `lexy::dsl::brackets` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct _brackets-dsl_ // note: not a rule itself - { - constexpr _branch-rule_ auto open() const; - constexpr _branch-rule_ auto close() const; - - constexpr _terminator-dsl_ as_terminator() const; - - constexpr _brackets-dsl_ limit(auto ... limit); - constexpr _rule_ auto recovery_rule() const; - - //=== rules ===// - constexpr _branch-rule_ auto operator()(_rule_ auto rule) const; - - constexpr _branch-rule_ auto try_(_rule_ auto rule) const; - - constexpr _branch-rule_ auto opt(_rule_ auto rule) const; - - constexpr _branch-rule_ auto list(_rule_ auto item) const; - constexpr _branch-rule_ auto list(_rule_ auto item, _separator_ auto sep) const; - - constexpr _branch-rule_ auto opt_list(_rule_ auto item) const; - constexpr _branch-rule_ auto opt_list(_rule_ auto item, _separator_ auto sep) const; - }; - - constexpr _brackets-dsl_ brackets(_branch-rule_ auto open, _branch-rule_ auto close); -} ----- - -[.lead] -`brackets` is not a rule, but a DSL for specifying rules that all parse something surrounded by brackets. - -Many rules require a {{% branch-rule %}} as argument, like {{% docref "lexy::dsl::list" %}}. -However, there isn't always an easy way to check for a branch condition and sometimes the rule in question is always surrounded by brackets. -Then you can use `brackets`: -it specifies branch rules for open and closing brackets and provides ways of building rules where any branch condition is just "the closing bracket hasn't been matched yet". -As such, you don't need to provide a branch condition anymore. - -Common brackets, like parentheses, are predefined (see below). - -NOTE: See {{% docref "lexy::dsl::terminator" %}} if you want to parse something that is just terminated by something and doesn't have an "opening bracket". - -=== Branch rules `.open()` and `.close()` - -{{% interface %}} ----- -constexpr _branch-rule_ auto open() const; <1> -constexpr _branch-rule_ auto close() const; <2> ----- -<1> Returns the opening bracket rule passed as first argument to `brackets()`. -<2> Returns the opening bracket rule passed as second argument to `brackets()`. - -=== `.as_terminator()`, `.limit()`, and `.recovery_rule()` - -{{% interface %}} ----- -constexpr _terminator-dsl_ as_terminator() const; <1> - -constexpr _brackets-dsl_ limit(auto ... limit); <2> -constexpr _rule_ auto recovery_rule() const; <3> ----- -<1> Returns the corresponding `terminator`. -<2> Sets the limit for error recovery. -<3> Returns `as_terminator().recovery_rule()`. - -`brackets` itself is just a thin wrapper over {{% docref "lexy::dsl::terminator" %}}; -`as_terminator()` returns that terminator: -`lexy::dsl::brackets(open, close).as_terminator()` is equivalent to `lexy::dsl::terminator(close)`; -`lexy::dsl::brackets(open, close).limit(tokens...).as_terminator()` is equivalent to `lexy::dsl::terminator(close).limit(tokens...).as_terminator()`. - -=== Bracketed rules - -{{% interface %}} ----- -constexpr _branch-rule_ auto operator()(_rule_ auto rule) const -{ - return open() >> as_terminator()(rule); -} - -constexpr _branch-rule_ auto try_(_rule_ auto rule) const -{ - return open() >> as_terminator().try_(rule); -} - -constexpr _branch-rule_ auto opt(_rule_ auto rule) const -{ - return open() >> as_terminator().opt(rule); -} - -constexpr _branch-rule_ auto list(_rule_ auto item) const -{ - return open() >> as_terminator().list(item); -} -constexpr _branch-rule_ auto list(_rule_ auto item, _separator_ auto sep) const -{ - return open() >> as_terminator().list(item, sep); -} - -constexpr _branch-rule_ auto opt_list(_rule_ auto item) const -{ - return open() >> as_terminator().opt_list(item); -} -constexpr _branch-rule_ auto opt_list(_rule_ auto item, _separator_ auto sep) const -{ - return open() >> as_terminator().opt_list(item, sep); -} ----- - -[.lead] -Parse something surrounded by brackets. - -They are all entirely equivalent to the expression indicated above: -the result is a {{% docref branch %}} whose condition is `open()`, -and then it parses `as_terminator().foo(...)`, where the terminator is `close()`. - -[#brackets-predefined] -== Predefined brackets - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _brackets-dsl_ auto round_bracketed = brackets(lit_c<'('>, lit_c<')'>); - constexpr _brackets-dsl_ auto square_bracketed = brackets(lit_c<'['>, lit_c<']'>); - constexpr _brackets-dsl_ auto curly_bracketed = brackets(lit_c<'{'>, lit_c<'}'>); - constexpr _brackets-dsl_ auto angle_bracketed = brackets(lit_c<'<'>, lit_c<'>'>); - - constexpr _brackets-dsl_ auto parenthesized = round_bracketed; -} ----- - -[.lead] -ASCII brackets are pre-defined. - -{{% playground-example parenthesized "Parse a parenthesized list of things" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/branch.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/branch.adoc deleted file mode 100644 index f28825afcb..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/branch.adoc +++ /dev/null @@ -1,93 +0,0 @@ ---- -header: "lexy/dsl/branch.hpp" -entities: - "branch-rule": doc - "lexy::dsl::operator>>": branch - "branch": branch - "lexy::dsl::else_": else_ ---- -:toc: left - -[.lead] -The `operator>>` overload for rules and `else_` branch rule. - -{{% interface %}} ----- -template -concept _branch-rule_ = _rule_ && …; ----- - -A _branch rule_ is a rule that has an associated condition. -The parsing algorithm can efficiently check whether the condition would match at the current reader position. -As such, they are used to make decisions: -once a branch condition matches, the branch is taken without backtracking. - -[#branch] -== Branch rule `lexy::dsl::operator>>` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct _branch_ {}; // models _branch-rule_ - - constexpr _branch_ operator>>(_branch-rule_ auto condition, _rule_ auto then); - - constexpr _branch_ operator+(_branch_ br, _rule_ auto then); -} ----- - -[.lead] -`operator>>` (branch) turns a rule into a branch rule by giving it another branch rule as condition. - -Parsing:: - Parses `condition` and `then` in {{% docref sequence %}}. -Branch parsing:: - Tries to parse `condition` and backtracks if that backtracks. - Then parses `then`. -Errors:: - All errors raised by `condition` and `then`. - The rule then fails if they have failed. -Values:: - All values produced by `condition` followed by all values of `then`. - -If the result of `operator>>` is used in the beginning of a {{% docref sequence %}} with a rule, i.e. as `(condition >> rule1) + rule2`, -this is equivalent to `condition >> rule1 + rule2`, i.e. the original branch is extended. -`rule1 + (condition >> rule2)`, on the other hand, is equivalent to `rule1 + condition + rule2`. - -{{% playground-example if "Only parse a fraction if preceded by a dot" %}} - -NOTE: A branch rule is only parsed as a branch if its required. -If you just use it by itself, the branch condition does not matter. -Use {{% docref "lexy::dsl::if_" %}} to conditionally execute a branch. - -CAUTION: If `then` is also a branch rule, it will still only use `condition` as the condition. - -[#else_] -== Branch rule `lexy::dsl::else_` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct _else_ // note: not a _rule_ itself - { - friend constexpr _branch-rule_ operator>>(_else_, _rule_ auto rule); - }; - - constexpr _else_ else_; -} ----- - -[.lead] -`else_` is a tag that can be used as the condition for link:#branch[`operator>>`] to indicate that the rule should always be taken. - -(Branch) Parsing:: - Parses `rule` without every backtracking. -Errors:: - All errors raised by parsing `rule`. -Values:: - All values produced by `rule`. - -{{% playground-example choice_else "If it is not a known greeting, require that the empty is empty" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/byte.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/byte.adoc deleted file mode 100644 index e9e90ffed8..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/byte.adoc +++ /dev/null @@ -1,139 +0,0 @@ ---- -header: "lexy/dsl/byte.hpp" -entities: - "lexy::dsl::byte": bytes - "lexy::dsl::bytes": bytes - "lexy::dsl::padding_bytes": bytes - "lexy::dsl::bint8": int - "lexy::dsl::bint16": int - "lexy::dsl::little_bint16": int - "lexy::dsl::big_bint16": int - "lexy::dsl::bint32": int - "lexy::dsl::little_bint32": int - "lexy::dsl::big_bint32": int - "lexy::dsl::bint64": int - "lexy::dsl::little_bint64": int - "lexy::dsl::big_bint64": int ---- -:toc: left - -[.lead] -Rules that match one or more bytes. - -[#bytes] -== Token rule `lexy::dsl::byte` and `lexy::dsl::bytes` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template - constexpr _token-rule_ auto bytes; - - constexpr _token-rule_ auto byte = bytes<1>; -} ----- - -[.lead] -`bytes` is a {{% token-rule %}} that matches `N` arbitrary bytes. - -Requires:: - The input {{% encoding %}} is `lexy::byte_encoding`. -Matching:: - Matches and consumes `N` bytes. -Errors:: - {{% docref "lexy::expected_char_class" %}} (`"byte"`): - if EOF was encountered early; at the position of the last byte it could consume. - The rule then fails. -Parse tree:: - Single token node with the {{% docref "lexy::predefined_token_kind" %}} `lexy::any_token_kind`. - -CAUTION: Combining {{% docref "lexy::dsl::capture" %}} with `bytes` does not do any endianness conversion. - -[#padding_bytes] -== Branch rule `lexy::dsl::padding_bytes` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template - constexpr _branch-rule_ auto padding_bytes; -} ----- - -[.lead] -`padding_bytes` is a {{% branch-rule %}} that matches `N` padding bytes. - -Padding bytes are bytes whose value doesn't matter: -they're only expected to have a certain value, but it's okay, if they don't. - -(Branch) parsing:: - (Branch) parses {{% docref "lexy::dsl::bytes" %}}. - If that succeeds, the branch is taken. - It then checks if the `N` consumed bytes have the given `Value`. -Errors:: - * All errors raised by parsing `bytes`, if not branch parsing. - The rule then fails. - * {{% docref "lexy::expected_literal" %}} if a byte did not have `Value`. - The rule then recovers. - -NOTE: Branch parsing will not backtrack if the padding bytes do not have the given `Value`. - -[#int] -== Binary integer branch rules - -{{% interface %}} ----- -namespace lexy -{ - struct mismatched_byte_count {}; -} - -namespace lexy::dsl -{ - struct _binary-integer-dsl__ // models _branch-rule_ - { - constexpr _branch-rule_ operator()(_token-rule_ bytes) const; - }; - - constexpr _binary-integer-dsl_ bint8; - - constexpr _binary-integer-dsl_ bint16; - constexpr _binary-integer-dsl_ little_bint16; - constexpr _binary-integer-dsl_ big_bint16; - - constexpr _binary-integer-dsl_ bint32; - constexpr _binary-integer-dsl_ little_bint32; - constexpr _binary-integer-dsl_ big_bint32; - - constexpr _binary-integer-dsl_ bint64; - constexpr _binary-integer-dsl_ little_bint64; - constexpr _binary-integer-dsl_ big_bint64; -} ----- - -[.lead] -`[little/big_]bintN` is a {{% branch-rule %}} that converts `N / 8` bytes into an `N` bit integer. - -Each rule has the associated bit width `N` and endianness: -for the prefixed ones it is little/big endian, for the unprefixed ones it is the native endianness. -The endianness doesn't matter for `bint8`. - -They delegate to the associated `bytes` rule, which can be specified using the function call operator. -If none has been specified, they default to {{% docref "lexy::dsl::bytes" %}}. - -(Branch) parsing:: - (Branch) parses `bytes`. - If that succeeds, the branch is taken. - It then checks that `N / 8` bytes have been consumed. -Errors:: - * All errors raised by parsing `bytes`. - The rule then fails. - * `lexy::mismatched_byte_count`: if `bytes` succeeded but did not consume `N / 8` bytes; - its range covers everything consumed by `bytes`. - The rule then fails. -Values:: - A `std::uint_leastN_t` which results in reading `N / 8` bytes in the specified endianness. - This conversion can never fail. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/capture.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/capture.adoc deleted file mode 100644 index 3c5453c21e..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/capture.adoc +++ /dev/null @@ -1,37 +0,0 @@ ---- -header: "lexy/dsl/capture.hpp" -entities: - "lexy::dsl::capture": capture ---- - -[#capture] -== Branch rule `lexy::dsl::capture` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _branch-rule_ auto capture(_rule_ auto rule); -} ----- - -[.lead] -`capture_token` is a {{% branch-rule %}} that parses `rule` capturing everything it has consumed but excluding whitespace as a value. - -Requires:: - `rule` is either a {{% token-rule %}} or {{% docref "lexy::dsl::p" %}} where the production is a token production. -(Branch) Parsing:: - Parses `rule` unchanged. -Errors:: - All errors raised by `rule`. - The rule then fails if `rule` has failed. -Values:: - A {{% docref "lexy::lexeme" %}} whose range covers everything consumed by `token` except any trailing whitespace. - Then all values produced by `rule`. - -{{% godbolt-example capture "Get a single code point" %}} - -TIP: Use the callback {{% docref "lexy::as_string" %}} to convert the {{% docref "lexy::lexeme" %}} to a string. - -TIP: In most cases, you should prefer {{% docref "lexy::dsl::identifier" %}} instead. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/case_folding.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/case_folding.adoc deleted file mode 100644 index 6d39188af9..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/case_folding.adoc +++ /dev/null @@ -1,69 +0,0 @@ ---- -header: "lexy/dsl/case_folding.hpp" -entities: - "lexy::dsl::ascii::case_folding": ascii - "lexy::dsl::unicode::simple_case_folding": simple ---- -:toc: left - -[.lead] -Rules for case-insensitive parsing. - -[#ascii] -== Literal rule `lexy::dsl::ascii::case_folding` - -{{% interface %}} ----- -namespace lexy::dsl::ascii -{ - constexpr _literal-rule_ auto case_folding(_literal-rule_ lit); -} ----- - -[.lead] -`case_folding` is a {{% literal-rule %}} that matches another {{% literal-rule %}} but performing case folding of ASCII characters. - -Requires:: - `lit` is not a rule that is already case folded. -Matching:: - Matches and consumes `lit` on an input where uppercase ASCII characters are converted to lowercase first. - As such, `lit` is matched case-insensitively. -Errors:: - All errors raised by `lit` when it fails. -Parse tree:: - The single token node created by `lit`; its content is the input as it was before the case folding. - -{{% playground-example case_folding "Match a literal case-insensitively" %}} - -CAUTION: As all uppercase characters of the input are converted to lowercase, but `lit` itself is unchanged, `lit` must not match uppercase characters: -`case_folding(LEXY_LIT("ABC"))` will never match. - -[#simple] -== Literal rule `lexy::dsl::unicode::simple_case_folding` - -{{% interface %}} ----- -namespace lexy::dsl::unicode -{ - constexpr _literal-rule_ auto simple_case_folding(_literal-rule_ lit); -} ----- - -[.lead] -`simple_case_folding` is a {{% literal-rule %}} that matches another {{% literal-rule %}} but performing simple case folding of Unicode characters. - -It requires the Unicode database. - -Requires:: - `lit` is not a rule that is already case folded. -Matching:: - Matches and consumes `lit` on an input where all code points are transformed using {{% docref "lexy::simple_case_fold" %}}. - As such, `lit` is matched case-insensitively. -Errors:: - All errors raised by `lit` when it fails. -Parse tree:: - The single token node created by `lit`; its content is the input as it was before the case folding. - -CAUTION: As all uppercase characters of the input are converted to lowercase, but `lit` itself is unchanged, `lit` must not match uppercase characters: -`simple_case_folding(LEXY_LIT("ABC"))` will never match. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/char_class.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/char_class.adoc deleted file mode 100644 index b224a6b98d..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/char_class.adoc +++ /dev/null @@ -1,169 +0,0 @@ ---- -header: "lexy/dsl/char_class.hpp" -entities: - "char-class-rule": doc - "literal-char-class-rule": doc - "LEXY_CHAR_CLASS": macro - "lexy::dsl::operator/ (char class)": union - "lexy::dsl::operator- (unary)": complement - "lexy::dsl::operator-": minus - "lexy::dsl::operator&": intersection ---- -:toc: left - -[.lead] -Char class builders and combinators. - -{{% interface %}} ----- -template -concept _char-class-rule_ = _token-rule_ && …; ----- - -A _char class rule_ is a special {{% token-rule %}} that matches a single code point from a given set, the _char class_. -Each char class rule has the same parsing behavior: - -Matching:: - * If the current code unit is an ASCII character, matches and consumes it. - Checks if that character is part of the char class. - * Otherwise, if the char class contains non-ASCII characters, matches and consumes all code points that form a code point in this encoding. - For ASCII, UTF-32, {{% docref "lexy::default_encoding" %}} and {{% docref "lexy::byte_encoding" %}}, this is always a single code unit, for UTF-8, this is up to 4 code units, and for UTF-16, this is up to 2 code units. - Checks if that code point is part of the char class. -Errors:: - {{% docref "lexy::expected_char_class" %}} with the name of the char class, at the starting reader position if - * the current code unit is ASCII but not part of the char class, or - * the current code point is not part of the char class, or - * the current code unit(s) do not form a valid code point. - This includes surrogates, overlong UTF-8 sequences, or out of range code points. - The rule then fails. - -For a char class rule, {{% docref ".error" %}} and {{% docref ".kind" %}} are overridden to ensure the resulting token rule is still a char class rule. -In the case of `.error`, the corresponding error type is raised instead. - -{{% interface %}} ----- -template -concept _literal-char-class-rule_; ----- - -A _literal char class rule_ is a rule that can behave like a char class. -Those are - -* a {{% docref "lexy::dsl::lit" %}} (or {{% docref "lexy::dsl::lit_c" %}}) rule matching a single ASCII character, -* a {{% docref "lexy::dsl::lit" %}} (or {{% docref "lexy::dsl::lit_c" %}}) rule whose char type is `char32_t` matching a single character, -* a {{% docref "lexy::dsl::lit_b" %}} rule matching an arbitrary byte, -* a {{% docref "lexy::dsl::lit_cp" %}} rule, and -* {{% docref "lexy::dsl::operator/ (char class)" %}} combinations of the above. - -Literal char class rules can be used with the char class operators. -If they specify a non-ASCII character, the input {{% encoding %}} must be ASCII, UTF-8, UTF-16, or UTF-32 (if it is ASCII, the character will never be matched). -The exception is {{% docref "lexy::dsl::lit_b" %}} where the encoding must be {{% docref "lexy::default_encoding" %}} or {{% docref "lexy::byte_encoding" %}}. - -[#macro] -== Char class `LEXY_CHAR_CLASS` - -{{% interface %}} ----- -#define LEXY_CHAR_CLASS(Name, CharClassRule) ----- - -[.lead] -`LEXY_CHAR_CLASS` is a {{% char-class-rule %}} that is a (re)named version of `CharClassRule`. - -It is equivalent to `CharClassRule`, but overrides its name (in the error) to be the string literal `Name`. -It also type-erases the type of `CharClassRule` to shorten it, which can improve error messages and compilation times. - -{{% playground-example char_class_macro "Match an atom of an email address" %}} - -[#union] -== Char class union `lexy::dsl::operator/ (char class)` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _char-class-rule_ auto operator/(_char-class-rule_ auto lhs, - _char-class-rule_ auto rhs); - constexpr _char-class-rule_ auto operator/(_char-class-rule_ auto lhs, - _literal-char-class-rule_ auto rhs); - constexpr _char-class-rule_ auto operator/(_literal-char-class-rule_ auto lhs, - _char-class-rule_ auto rhs); -} ----- - -[.lead] -`operator/` (char class union) is a {{% char-class-rule %}} that matches a union of char classes. - -It matches all characters that are contained in at least one of the char classes. -Its name is `union`. - -{{% playground-example char_class_union "Match an identifier consisting of upper case characters or digits" %}} - -[#complement] -== Char class complement `lexy::dsl::operator- (unary)` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _char-class-rule_ auto operator-(_char-class-rule_ auto rule); - constexpr _char-class-rule_ auto operator-(_literal-char-class-rule_ auto rule); -} ----- - -[.lead] -`operator-` (char class complement) is a {{% char-class-rule %}} that matches the complement of another char class. - -It matches all characters that are not part of the char class `rule`. -Its name is `complement`. - -{{% playground-example quoted "Match non-control characters in a string literal" %}} - -[#minus] -== Char class minus `lexy::dsl::operator-` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _char-class-rule_ auto operator-(_char-class-rule_ auto set, - _char-class-rule_ auto minus); - constexpr _char-class-rule_ auto operator-(_char-class-rule_ auto set, - _literal-char-class-rule_ auto minus); -} ----- - -[.lead] -`operator-` (char class minus) is a {{% char-class-rule %}} that removes characters from another char class. - -It matches all characters that are part of `set` but not part of `minus`. -Its name is `minus`. - -{{% playground-example char_class_minus "Match upper case characters except for `X`" %}} - -[#intersection] -== Char class intersection `lexy::dsl::operator&` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _char-class-rule_ auto operator&(_char-class-rule_ auto lhs, - _char-class-rule_ auto rhs); - constexpr _char-class-rule_ auto operator&(_char-class-rule_ auto lhs, - _literal-char-class-rule_ auto rhs); - constexpr _char-class-rule_ auto operator&(_literal-char-class-rule_ auto lhs, - _char-class-rule_ auto rhs); - constexpr _char-class-rule_ auto operator&(_literal-char-class-rule_ auto lhs, - _literal-char-class-rule_ auto rhs); -} ----- - -[.lead] -`operator&` (char class intersection) is a {{% char-class-rule %}} that matches an intersection of char classes. - -It matches all characters that are contained in all of the char classes. -Its name is `intersection`. - -{{% playground-example char_class_intersection "Match all printable space characters" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/choice.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/choice.adoc deleted file mode 100644 index 967d75154a..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/choice.adoc +++ /dev/null @@ -1,62 +0,0 @@ ---- -header: "lexy/dsl/choice.hpp" -entities: - "lexy::dsl::operator|": choice - "choice": choice ---- -:toc: left - -[#choice] -== Rule `lexy::dsl::operator|` - -{{% interface %}} ----- -namespace lexy -{ - struct exhausted_choice {}; -} - -namespace lexy::dsl -{ - struct _choice_ {}; // models _rule_, and sometimes _branch-rule_ - - constexpr _choice_ operator|(_branch-rule_ auto lhs, _branch-rule_ auto rhs); - - constexpr _choice_ operator|(_choice_ lhs, _branch-rule_ auto rhs); - constexpr _choice_ operator|(_branch-rule_ auto lhs, _choice_ rhs); - constexpr _choice_ operator|(_choice_ lhs, _choice_ rhs); -} ----- - -[.lead] -`operator|` (choice) is a rule that parses one of the specified {{% branch-rule %}}s. - -Parsing:: - Tries to parse `lhs`, then tries to parse `rhs`. -Branch parsing:: - It is a branch rule if neither `lhs` nor `rhs` are unconditional branches (e.g. {{% docref "lexy::dsl::else_" %}}). - Tries to parse `lhs`, then tries to parse `rhs`. - Backtracks instead of failing for an exhausted choice. -Errors:: - * `lexy::exhausted_choice`: if neither `lhs` nor `rhs` could be parsed, at the starting reader position. The rule then fails. - * All errors raised by `lhs` or `rhs` during branch parsing. - The rule then fails if they have failed. -Values:: - All values produced by the selected branch. - -`operator|` can be chained: -`a | (b | c)` is equivalent to `a | lexy::dsl::else_ >> (b | c)`, and likewise for the other cases. - -{{% playground-example choice "Parse a greeting" %}} -{{% playground-example choice_error "Raise a different error if no greeting matches" %}} -{{% playground-example choice_else "Do something differently if no greeting matches" %}} - -{{% playground-example choice_production "Branches can be arbitrarily complex" %}} - -{{% playground-example choice_branch "Only the branch condition is checked" %}} - -TIP: Use {{% docref "lexy::dsl::operator>>" %}} to turn a rule into a branch by giving it a condition. -Use {{% docref "lexy::dsl::peek" %}} or {{% docref "lexy::dsl::lookahead" %}} as conditions if there is no simple token rule to check the beginning of the branch. - -NOTE: If one of the branches is always taken (e.g. because it uses {{% docref "lexy::dsl::else_" %}}), the `lexy::exhausted_choice` error is never raised. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/code_point.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/code_point.adoc deleted file mode 100644 index 6154d38908..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/code_point.adoc +++ /dev/null @@ -1,83 +0,0 @@ ---- -header: "lexy/dsl/code_point.hpp" -entities: - "lexy::dsl::code_point": code_point ---- - -[#code_point] -== Char class rule `lexy::dsl::code_point` - -{{% interface %}} ----- -namespace lexy::dsl -{ - class _code-point-dsl_ // models _char-class-rule_ - { - public: - template - constexpr _token-rule_ auto if_() const; - - template - constexpr _token-rule_ auto set() const; - template - constexpr _token-rule_ auto range() const; - - constexpr _token-rule_ auto ascii() const; - constexpr _token-rule_ auto bmp() const; - constexpr _token-rule_ auto noncharacter() const; - - template - constexpr _token-rule_ auto general_category() const; - template - constexpr _token-rule_ auto general_category() const; - }; - - constexpr _code-point-dsl_ auto code_point; -} ----- - -[.lead] -`code_point` is a {{% char-class-rule %}} that matches a specified set of Unicode code points. - -`code_point`:: - matches an arbitrary scalar code point - Its char class name is `code-point`. -`code_point.if_()`:: - matches all code points where the predicate returns `true`. - The predicate must have a `constexpr bool operator()(lexy::code_point)`. - Its char class name is the type name of `P`. -`code_point.set()`:: - matches the specified code points. - Its name is `code-point.set`. -`code_point.range()`:: - matches the code points in the range `[Low, High]` (both sides inclusive). - Its name is `code-point.range`. -`code_point.ascii()`:: - matches all ASCII code points. - Its name is `code-point.ASCII`. -`code_point.bmp()`:: - matches all code points in the BMP. - Its name is `code-point.BMP`. -`code_point.noncharacter()`:: - matches all non-character code points. - Its name is `code-point.noncharacter`. -`code_point.general_category()`:: - matches all code points with the specified category or category group. - Its name is the name of the category. - This requires the Unicode database, except for `Cc`, `Cs`, and `Co`, which are fixed. - -{{% playground-example code_point "Parse one code point in the inputs encoding" %}} - -{{% playground-example code_point_if "Parse even code points only" %}} - -CAUTION: As a token rule, it matches {{% docref whitespace whitespace %}} immediately following the code point. -As such, the rule is best used in contexts where automatic whitespace skipping is disabled. - -NOTE: See {{% docref "lexy::dsl::unicode" %}} for common predefined predicates. - -NOTE: `.ascii()`, `.bmp()`, and `.noncharacter()` corresponds to the corresponding member function of {{% docref "lexy::code_point" %}}. -The other classification functions don't have rules: -* `cp.is_valid()` and `cp.is_scalar()` is always `true`; `cp.is_surrogate()` is never `true`. -* `cp.is_control()` is general category `Cc`. -* `cp.is_private_use()` is general category `Co`. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/combination.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/combination.adoc deleted file mode 100644 index 0ced375ba7..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/combination.adoc +++ /dev/null @@ -1,104 +0,0 @@ ---- -header: "lexy/dsl/combination.hpp" -entities: - "lexy::dsl::combination": combination - "lexy::dsl::partial_combination": partial_combination ---- -:toc: left - -[.lead] -The `combination` and `partial_combination` rules. - -[#combination] -== Rule `lexy::dsl::combination` - -{{% interface %}} ----- -namespace lexy -{ - struct combination_duplicate {}; -} - -namespace lexy::dsl -{ - struct _combination-dsl_ // models _rule_ - { - template - static constexpr _rule_ auto missing_error; - - template - static constexpr _rule_ auto duplicate_error; - }; - - constexpr _combination-dsl_ combination(_branch-rule_ auto ... branches); -} ----- - -[.lead] -`combination` is a rule that parses all of the specified {{% branch-rule %}}s, but in arbitrary order. - -Parsing:: - Parses the {{% docref choice %}} `(branches | ...)` a total of `sizeof...(branches)` times in {{% docref sequence %}}. -Errors:: - * `lexy::exhausted_choice`: if one iteration of the choice does not match; at the starting position of the iteration. - The rule then fails. - This error tag can be changed by specifying a different `Tag` using `.missing_error`. - * `lexy::combination_duplicate`: if one iteration parses a branch rule that has already been selected in a previous iteration; at the starting position of the later iteration. - The rule then recovers without consuming additional input, but the values produced by the duplicate are not forwarded to the sink, - and the duplicated iteration does not count towards the total number of repetitions. - This error tag can be changed by specifying a different `Tag` using `.duplicate_error`. - * All other errors raised by the choice `(branches | ...)`, i.e. the errors raised by the individual rules during branch parsing. - The rule then fails if they have failed. -Values:: - It creates a sink of the current context. - All values produced by the selected branch in an iteration are forwarded to the sink. - The value of the finished sink is produced as only value of the `combination` rule. - -{{% playground-example combination "Parse `a`, `b`, `c` in some order" %}} - -WARNING: The branches are always tried in the same order and branches already taken are not removed in future iterations. -If an earlier branch always matches the same as a later branch, the later branch is not taken and the rule cannot succeed. - -TIP: Use {{% docref "lexy::dsl::member" %}} together with `lexy::as_aggregate` as the sink. - -[#partial_combination] -== Rule `lexy::dsl::partial_combination` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct _partial-combination-dsl_ // models _rule_ - { - template - static constexpr _rule_ auto duplicate_error; - }; - - constexpr auto partial_combination(_branch-rule_ auto ... branches) - -> _partial-combination-dsl_; -} ----- - -[.lead] -`partial_combination` is a rule that parses a subset of the specified {{% branch-rule %}}s, but in arbitrary order. - -Parsing:: - Parses the {{% docref choice %}} `(branches | ...)` a total of `sizeof...(branches)` times in {{% docref sequence %}}. - If the choice would fail with a `lexy::exhausted_choice` error, this error is not reported. - Instead the rule succeeds early without consuming additional input. -Errors:: - * `lexy::combination_duplicate`: if one iteration parses a branch rule that has already been selected in a previous iteration; at the starting position of the later iteration. - The rule then recovers without consuming additional input, but the values produced by the duplicate are not forwarded to the sink, - and the duplicated iteration does not count towards the total number of repetitions. - This error tag can be changed by specifying a different `Tag` using `.duplicate_error`. - * All other errors raised by the choice `(branches | ...)`, i.e. the errors raised by the individual rules during branch parsing. - The rule then fails if they have failed. -Values:: - It creates a sink of the current context. - All values produced by the selected branch in an iteration are forwarded to the sink. - The value of the finished sink is produced as only value of the `combination` rule. - -{{% playground-example partial_combination "Parse a subset of `a`, `b`, `c` in some order" %}} - -NOTE: `partial_combination` can match the empty string. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/context_counter.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/context_counter.adoc deleted file mode 100644 index 37a74490f4..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/context_counter.adoc +++ /dev/null @@ -1,199 +0,0 @@ ---- -header: "lexy/dsl/context_counter.hpp" -entities: - "lexy::dsl::context_counter": context_counter - "lexy::dsl::equal_counts": equal_counts ---- -:toc: left - -[.lead] -A counter that can be manipulated during parsing. - -[#context_counter] -== Rule DSL `lexy::dsl::context_counter` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct _context_counter-dsl_ // note: not a rule itself - { - template - constexpr _rule_ auto create() const; - - constexpr _rule_ auto inc() const; - constexpr _rule_ auto dec() const; - - constexpr _rule_ auto push(_rule_ auto r) const; - constexpr _rule_ auto pop(_rule_ auto r) const; - - template - constexpr _branch-rule_ auto is() const; - constexpr _branch-rule_ auto is_zero() const; - - constexpr _rule_ auto value() const; - }; - - template - constexpr _context_counter-dsl_ context_counter; -} ----- - -[.lead] -`context_counter` is not a rule, but a DSL for specifying rules that manipulate a counter of the current context. - -{{% playground-example "context_counter" "Parse `n` `a`, then `n` `b` without recursion" %}} - -=== Rule `.create()` - -{{% interface %}} ----- -template -constexpr _rule_ auto create() const; ----- - -[.lead] -`.create()` returns a rule that creates the counter. - -Parsing:: - Matches everything, without consuming anything. - As a side effect, it creates a counter with name `Id` inside the current context. - If a context variable (of any) type with that name already exists, it is shadowed. - This counter is initialized to `InitialValue`; it's underlying type is `int`. -Errors:: - None. -Values:: - None. - -=== Rules `.inc()`, `.dec()` - -{{% interface %}} ----- -constexpr _rule_ auto inc() const; -constexpr _rule_ auto dec() const; ----- - -[.lead] -`.inc()`, `.dec()` return rules that increment/decrement counter. - -Requires:: - A counter with the name `Id` has been created in the current context, - i.e. `.create()` has been parsed earlier. -Parsing:: - Matches everything, without consuming anything. - As a side effect, it modifies the counter with name `Id` of the current context: - * `.inc()` increments it by one. - * `.dec()` decrements it by one. -Errors:: - None. -Values:: - None. - -=== Rules `.push()`, `.pop()` - -{{% interface %}} ----- -constexpr _rule_ auto push(_rule_ auto r) const; -constexpr _rule_ auto pop(_rule_ auto r) const; ----- - -[.lead] -`.push()`, `.pop()` return rules that add/subtract the counter. - -Requires:: - A counter with the name `Id` has been created in the current context, - i.e. `.create()` has been parsed earlier. -Parsing:: - Parses `r` and counts the number of code units consumed by `r`. - As a side effect, it modifies the counter with name `Id` of the current context: - * `.push()` adds the number of code units to it. - * `.pop()` subtracts the number of code units from it. -Errors:: - All errors raised by parsing `r`. - The rule then fails if `r` has failed. -Values:: - All errors produced by parsing `r`. - -CAUTION: The count includes any whitespace characters. - -=== Branch rules `.is()`, `.is_zero()` - -{{% interface %}} ----- -template -constexpr _branch-rule_ auto is() const; - -constexpr _branch-rule_ auto is_zero() const -{ - return is<0>(); -} ----- - -[.lead] -`.is()` and `.is_zero()` return {{% branch-rule %}}s that check the value of the counter. - -Requires:: - A counter with the name `Id` has been created in the current context, - i.e. `.create()` has been parsed earlier. -Parsing:: - Matches everything, without consuming anything. -Branch parsing:: - Backtracks unless the value of the boolean with name `Id` of the current context is `Value` (`.is()`) or `0` (`.is_zero()`). - Then matches everything without consuming anything. -Errors:: - None. -Values:: - None. - -=== Rule `.value()` - -{{% interface %}} ----- -constexpr _rule_ auto value() const; ----- - -[.lead] -`.value()` is a rule that returns the value of the counter. - -Requires:: - A counter with the name `Id` has been created in the current context, - i.e. `.create()` has been parsed earlier. -Parsing:: - Matches everything, without consuming anything. -Errors:: - None. -Values:: - The current value of the counter (an `int`) with name `Id` of the current context. - -[#equal_counts] -== Rule DSL `lexy::dsl::equal_counts` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _branch-rule_ auto equal_counts(_context_counter-dsl_... counters); -} ----- - -[.lead] -`equal_counts` is a {{% branch-rule %}} that checks whether all counters have the same value. - -Requires:: - * `sizeof...(counters) > 1` - * All counters have been created in the current context, - i.e. `.create()` has been parsed earlier. -Parsing:: - Matches everything, without consuming anything. - Only succeeds if all counters have the same value in the current context. -Branch parsing:: - Backtracks unless all counters have the same value in the current context; no error is raised. - Matches everything, without consuming anything. -Errors:: - A generic error with the tag `lexy::unequal_counts` at the unchanged reader position. - It then recovers without having consumed any input. -Values:: - None. - -{{% playground-example "equal_counts" "Parse `n` `a`, then `n` `b`, then `n` `c`" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/context_flag.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/context_flag.adoc deleted file mode 100644 index 4051187c30..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/context_flag.adoc +++ /dev/null @@ -1,129 +0,0 @@ ---- -header: "lexy/dsl/context_flag.hpp" -entities: - "lexy::dsl::context_flag": context_flag ---- - -[#context_flag] -== Rule DSL `lexy::dsl::context_flag` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct _context_flag-dsl_ // note: not a rule itself - { - template - constexpr _rule_ auto create() const; - - constexpr _rule_ auto set() const; - constexpr _rule_ auto reset() const; - constexpr _rule_ auto toggle() const; - - constexpr _branch-rule_ auto is_set() const; - constexpr _branch-rule_ auto is_reset() const; - - constexpr _rule_ auto value() const; - }; - - template - constexpr _context_flag-dsl_ context_flag; -} ----- - -[.lead] -`context_flag` is not a rule, but a DSL for specifying rules that manipulate a boolean variable of the current context. - -{{% playground-example context_flag "Parse `(a|b|c)*` where the first b must occur after the first a" %}} - -=== Rule `.create()` - -{{% interface %}} ----- -template -constexpr _rule_ auto create() const; ----- - -[.lead] -`.create()` returns a rule that creates the boolean. - -Parsing:: - Matches everything, without consuming anything. - As a side effect, it creates a boolean with name `Id` inside the current context. - If a context variable (of any) type with that name already exists, it is shadowed. - This boolean is initialized to `InitialValue`. -Errors:: - None. -Values:: - None. - -=== Rules `.set()`, `.reset()`, `.toggle()` - -{{% interface %}} ----- -constexpr _rule_ auto set() const; -constexpr _rule_ auto reset() const; -constexpr _rule_ auto toggle() const; ----- - -[.lead] -`.set()`, `.reset()`, `.toggle()` return rules that change the value of the boolean variable. - -Requires:: - A boolean with the name `Id` has been created in the current context, - i.e. `.create()` has been parsed earlier. -Parsing:: - Matches everything, without consuming anything. - As a side effect, it modifies the boolean with name `Id` of the current context: - * `.set()` sets it to `true`. - * `.reset()` sets it to `false`. - * `.toggle()` changes its value from `true` to `false` or from `false` to `true`. -Errors:: - None. -Values:: - None. - -=== Branch rules `.is_set()`, `.is_reset()` - -{{% interface %}} ----- -constexpr _branch-rule_ auto is_set() const; -constexpr _branch-rule_ auto is_reset() const; ----- - -[.lead] -`.is_set()` and `.is_reset()` return {{% branch-rule %}}s that check the value of the boolean variable. - -Requires:: - A boolean with the name `Id` has been created in the current context, - i.e. `.create()` has been parsed earlier. -Parsing:: - Matches everything, without consuming anything. -Branch parsing:: - Backtracks unless the value of the boolean with name `Id` of the current context is `true` (`.is_set()`) or `false` (`.is_reset()`). - Then matches everything without consuming anything. -Errors:: - None. -Values:: - None. - -=== Rule `.value()` - -{{% interface %}} ----- -constexpr _rule_ auto value() const; ----- - -[.lead] -`.value()` is a rule that returns the value of the boolean variable. - -Requires:: - A boolean with the name `Id` has been created in the current context, - i.e. `.create()` has been parsed earlier. -Parsing:: - Matches everything, without consuming anything. -Errors:: - None. -Values:: - The current value of the boolean with name `Id` of the current context. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/context_identifier.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/context_identifier.adoc deleted file mode 100644 index ab6beb03f8..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/context_identifier.adoc +++ /dev/null @@ -1,111 +0,0 @@ ---- -header: "lexy/dsl/context_identifier.hpp" -entities: - "lexy::dsl::context_identifier": context_identifier ---- - -[#context_identifier] -== Rule DSL `lexy::dsl::context_identifier` - -{{% interface %}} ----- -namespace lexy -{ - struct different_identifier {}; -} - -namespace lexy::dsl -{ - struct _context_identifier-dsl_ // note: not a rule itself - { - constexpr _rule_ auto create() const; - - constexpr _branch-rule_ auto capture() const; - - constexpr _see-below_ rematch() const; - }; - - template - constexpr _context_identifier-dsl_ context_identifier(_identifier-dsl_ identifier); -} ----- - -[.lead] -`context_identifier` is not a rule, but a DSL for specifying rules that manipulate an {{% docref "lexy::dsl::identifier" %}} variable of the current context. - -{{% playground-example "context_identifier" "Parse the same word twice" %}} - -=== Rule `.create()` - -{{% interface %}} ----- -constexpr _rule_ auto create() const; ----- - -[.lead] -`.create()` returns a rule that creates the identifier variable. - -Parsing:: - Matches everything, without consuming anything. - As a side effect, it creates an identifier with name `Id` inside the current context. - If a context variable (of any) type with that name already exists, it is shadowed. - This identifier is initialized to the empty string; it's underlying type is {{% docref "lexy::lexeme" %}}. -Errors:: - None. -Values:: - None. - -=== Rule `.capture()` - -{{% interface %}} ----- -constexpr _branch-rule_ auto capture() const; ----- - -[.lead] -`.capture()` returns a {{% branch-rule %}} that parses an identifier and stores it in the variable. - -Requires:: - The identifier with the name `Id` has been created in the current context, - i.e. `.create()` has been parsed earlier. -(Branch) Parsing:: - Parses `identifier`. - As a side effect, it sets the identifier with the name `Id` to contain the {{% docref "lexy::lexeme" %}} also produced by the {{% docref "lexy::dsl::identifier" %}} rule. -Errors:: - All errors raised by parsing `identifier`. - The rule then fails if `identifier` has failed. -Values:: - The value produced by parsing `identifier`, which is the same as the one stored in the variable. - -=== Rule `.rematch()` - -{{% interface %}} ----- -struct _rematch-dsl_ // models _branch-rule_ -{ - template - static constexpr _rematch-dsl_ auto error; -}; - -constexpr _rematch-dsl_ rematch() const; ----- - -[.lead] -`.rematch()` returns a {{% branch-rule %}} that matches the stored identifier again.. - -Requires:: - The identifier with the name `Id` has been created in the current context, - i.e. `.create()` has been parsed earlier. -Parsing:: - Parses `identifier` and checks it against the one stored in the variable. -Branch parsing:: - Parses `identifier` and backtracks when that fails. - Also backtracks when the new identifier does not match the old one. -Errors:: - * All errors raised by parsing `identifier`. - The rule then fails if `identifier` has failed. - * A generic error with the specified `Tag` or `lexy::different_identifier` if the new identifier does not match the identifier stored in the variable with name `Id` of the current context. - Its range covers everything consumed by `identifier` and the rule then fails. -Values:: - None; discards the value produced by `identifier`. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/delimited.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/delimited.adoc deleted file mode 100644 index f6aad7b4c2..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/delimited.adoc +++ /dev/null @@ -1,303 +0,0 @@ ---- -header: "lexy/dsl/delimited.hpp" -entities: - "lexy::dsl::delimited": delimited - "lexy::dsl::quoted": delimited-predefined - "lexy::dsl::triple_quoted": delimited-predefined - "lexy::dsl::single_quoted": delimited-predefined - "lexy::dsl::backticked": delimited-predefined - "lexy::dsl::double_backticked": delimited-predefined - "lexy::dsl::triple_backticked": delimited-predefined - "lexy::dsl::escape": escape - "lexy::dsl::backslash_escape": escape-predefined - "lexy::dsl::dollar_escape": escape-predefined ---- -:toc: left - -[.lead] -Rules for parsing delimited/quoted strings with escape sequences. - -[#delimited] -== Rule DSL `lexy::dsl::delimited` - -{{% interface %}} ----- -namespace lexy -{ - struct missing_delimiter {}; -} - -namespace lexy::dsl -{ - struct _delimited-dsl_ // note: not a rule itself - { - constexpr _branch-rule_ auto open() const; - constexpr _branch-rule_ auto close() const; - - constexpr _delimited-dsl_ limit(_char-class-rule_ limit); - template - constexpr _delimited-dsl_ limit(_char-class-rule_ limit); - - //=== rules ===// - constexpr _rule_ auto operator()(_char-class-rule_ c) const; - constexpr _rule_ auto operator()(_char-class-rule_ c, _escape-dsl_ ... escapes) const; - }; - - constexpr _delimited-dsl_ delimited(_branch-rule_ auto open, - _branch-rule_ auto close); - - constexpr _delimited-dsl_ delimited(_branch-rule_ auto delim) - { - return delimited(delim, delim) - } -} ----- - -[.lead] -`delimited` is not a rule, but a DSL for specifying rules that all parse zero or more "characters" surrounded by delimiters, with optional escape sequences. - -It can be created using two overloads. -The first overload takes a {{% branch-rule %}} that matches the `open`(ing) delimiter and one that matches the `close`(ing) delimiter. -The second overload takes just one rule that matches both opening and closing delimiter. - -Common delimiters, like quotation marks, are predefined (see below). - -NOTE: See {{% docref "lexy::dsl::brackets" %}} if you want to parse an arbitrary rule surrounded by brackets. -This is one is designed for lists of characters. - -=== Branch rules `.open()` and `.close()` - -{{% interface %}} ----- -constexpr _branch-rule_ auto open() const; -constexpr _branch-rule_ auto close() const; ----- - -[.lead] -`.open()`/`.close()` returns the branch rules that were passed to the top-level `lexy::dsl::delimited()`. - -=== `.limit()` - -{{% interface %}} ----- -constexpr _delimited-dsl_ limit(_char-class-rule_ limit); - -template -constexpr _delimited-dsl_ limit(_char-class-rule_ limit); ----- - -[.lead] -Provide a limit to detect a missing closing delimiter. - -`delimited` only stops parsing once it matches `close`; -if `close` is missing in the input it will consume the entire input. -By specifying a limit, which is a {{% char-class-rule %}}, -it fails once it matches one of them before the closing delimiter. - -The second overload also specifies an `ErrorTag`, which is used instead of `lexy::missing_delimiter`. - -{{% playground-example "quoted_limit" "Detect missing closing delimiter" %}} - -CAUTION: The limit must be a character that must not be allowed inside the delimited. - -=== Rule `.operator()` - -{{% interface %}} ----- -constexpr _rule_ auto operator()(_char-class-rule_ c) const; -constexpr _rule_ auto operator()(_char-class-rule_ c, _escape-dsl_ ... escapes) const; ----- - -[.lead] -`.operator()` returns a rule that parses zero or more occurrences of the {{% char-class-rule %}} `c` inside the delimited, -with optional `escape` sequences. - -Requires:: - Each escape sequence `escapes` must begin with a distinct escape character (e.g. one with backslash and one with dollar). -Parsing:: - Parses `open()`, then enters a loop where it repeatedly does the following in order: - 1. Tries parsing `close()`. If that succeeds, finishes. - 2. Tries match any of the token rules provided as a limit, if there are any, - and tries to match {{% docref "lexy::dsl::eof" %}}. - If any of them match, fails with a missing delimiter. - 3. For the second overload, tries to parse all `escapes` (see below for what it does). - 4. Parses `c`. - While parsing the delimited, automatic whitespace skipping is disabled; - whitespace is only skipped after `close()`. -Branch parsing:: - Tries parsing `open()` and backtracks if that did not succeed. - Otherwise, parses the same loop as described above. -Errors:: - * All errors raised by parsing `open()`. - * `lexy::missing_delimiter` or a specified `ErrorTag`: if the limits match. - Its range covers everything since the opening delimiter. - The rule then fails. - * All errors raised by parsing `escape`. - Recovers by simply continuing with the next iteration of the loop at the position where `escape` has left of. - Note that no value of `escape` is produced. - * All errors raised by parsing `c`. - It can recover for by simply discarding the bad character and continuing after it. - Otherwise, it fails. -Values:: - It creates a sink of the current context. - The sink is invoked with a {{% docref "lexy::lexeme" %}} capturing everything consumed by `c`; - a sequence of contiguous characters is merged into a single lexeme. - It is also invoked with every value produced by `escape`. - The invocations happen separately in lexical order. - The rule then produces all values of `open()`, the final value of the sink, and all values of `close()`. -Parse tree:: - `delimited` does has any special parse tree handling: - it will create the nodes for `open()`, then the nodes for each `c` and `escape`, and the nodes for `close()`. - However, instead of creating separate token nodes for each `c`, adjacent token nodes are merged into a single one covering as much as possible. - A character that is skipped during error recovery will create a token node whose {{% docref "lexy::predefined_token_kind" %}} is `lexy::error_token_kind`. - -{{% playground-example "quoted" "Parse a quoted string" %}} - -{{% playground-example "quoted_error" "Parse a quoted string with custom error" %}} - -{{% playground-example "quoted_token" "Parse a quoted string with whitespace and token production" %}} - -TIP: Use the sink {{% docref "lexy::as_string" %}} to produce a `std::string` from the rule. - -[#delimited-predefined] -== Predefined delimited - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _delimited-dsl_ quoted = delimited(lit<"\"">); - constexpr _delimited-dsl_ triple_quoted = delimited(lit<"\"\"\"">); - - constexpr _delimited-dsl_ single_quoted = delimited(lit<"'">); - - constexpr _delimited-dsl_ backticked = delimited(lit<"`">); - constexpr _delimited-dsl_ double_backticked = delimited(lit<"\``">); - constexpr _delimited-dsl_ triple_backticked = delimited(lit<"```">); -} ----- - -[.lead] -ASCII quotation marks are pre-defined. - -WARNING: The naming scheme for `triple_quoted` and `single_quoted` is not consistent, -but the terminology is common else where. - -[#escape] -== Rule DSL `lexy::dsl::escape` - -{{% interface %}} ----- -namespace lexy -{ - struct invalid_escape_sequence {}; -} - -namespace lexy::dsl -{ - struct _escape-dsl_ // note: not a rule itself - { - constexpr _escape-dsl_ rule(_branch-rule_ auto r) const; - - constexpr _escape-dsl_ capture(_branch-rule_ auto r) const; - - template - constexpr _escape-dsl_ symbol(_token-rule_ auto t) const; - template - constexpr _escape-dsl_ symbol() const; - }; - - constexpr _escape-dsl_ escape(_token-rule_ auto escape_char); -} ----- - -[.lead] -`escape` is not a rule but a DSL for specifying escape sequences. - -It is created by giving it the `escape_char`, a {{% token-rule %}} that matches the initial escape characters. -Common escape characters are predefined. - -The various member functions all add potential rules that parse the part of an escape sequence after the initial escape character. -The resulting DSL can then only be used with `delimited`, where it is treated like a branch rule and as such documented like one. - -Branch parsing:: - Tries to match and consume `escape_char`, backtracks otherwise. - After `escape_char` has been consumed, tries to parse each escape sequence (see below) in order of the member function invocations, - like a {{% docref choice %}} would. -Errors:: - * All errors raised by each escape sequence. - `escape` then fails but `delimited` recovers (see above). - * `lexy::invalid_escape_sequence`: if none of the escape sequences match; its range covers the `escape_char`. - `escape` then fails but `delimited` recovers (see above). -Values:: - All values produced by the selected escape sequence. - `delimited` forwards them to the sink in one invocation. - -{{% godbolt-example "quoted_escape" "Parse a quoted string with escape sequences" %}} - -=== Escape sequence `.rule()` - -{{% interface %}} ----- -constexpr _escape-dsl_ rule(_branch-rule_ auto r) const; ----- - -[.lead] -`.rule()` specifies an escape sequence that simply tries to parse the {{% branch-rule %}} `r`. - -=== Escape sequence `.capture()` - -{{% interface %}} ----- -constexpr _escape-dsl_ capture(_branch-rule_ auto r) const -{ - return this->rule(lexy::dsl::capture(r)); -} ----- - -[.lead] -`.capture()` specifies an escape sequence that tries to parse the {{% branch-rule %}} `t` and produces a {{% docref "lexy::lexeme" %}}. - -It is equivalent to {{% docref "lexy::dsl::capture" %}}. - -=== Escape sequence `.symbol()` - -{{% interface %}} ----- -template -constexpr _escape-dsl_ symbol(_token-rule_ auto t) const -{ - return this->rule(lexy::dsl::symbol(t)); -} - -template -constexpr _escape-dsl_ symbol() const -{ - return this->rule(lexy::dsl::symbol); -} ----- - -[.lead] -`.symbol()` specifies an escape sequence that parses a symbol. - -The first overload forwards to argument version {{% docref "lexy::dsl::symbol" %}}: -it matches `t` and looks it up in the `SymbolTable` and corresponding value produced. -The second overload forwards to the non-argument version that immediately looks up a symbol of the `SymbolTable`. - -[#escape-predefined] -== Predefined escapes - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _escape-dsl_ backslash_escape = escape(lit_c<'\\'>); - constexpr _escape-dsl_ dollar_escape = escape(lit_c<'$'>); -} ----- - -[.lead] -Escape sequences beginning with common ASCII characters are pre-defined. - -NOTE: They don't actually define any escape sequences, just the initial character. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/digit.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/digit.adoc deleted file mode 100644 index 4609f095e9..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/digit.adoc +++ /dev/null @@ -1,202 +0,0 @@ ---- -header: "lexy/dsl/digit.hpp" -entities: - "bases": bases - "lexy::dsl::binary": bases - "lexy::dsl::octal": bases - "lexy::dsl::hex_lower": bases - "lexy::dsl::hex_upper": bases - "lexy::dsl::hex": bases - "lexy::dsl::zero": zero - "lexy::dsl::digit": digit - "lexy::dsl::digits": digits - "lexy::dsl::n_digits": n_digits - "lexy::dsl::digit_sep_underscore": digit-sep - "lexy::dsl::digit_sep_tick": digit-sep ---- -:toc: left - -[.lead] -Token rules that match individual digits or sequence of digits. - -[#bases] -== Bases - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct binary {}; - struct octal {}; - struct decimal {}; - - struct hex_lower {}; - struct hex_upper {}; - struct hex {}; -} ----- - -[.lead] -The tag types `binary`, `octal`, `decimal`, `hex_lower`, `hex_upper`, and `hex` indicate the base of a number and what digits are allowed. - -[%collapsible] -.The bases -==== -|=== -| Tag | Radix | Digits - -| `binary` | 2 | `01` -| `octal` | 8 | `01234567` -| `decimal` | 10 | `0123456789` -| `hex_lower` | 16 | `0123456789`, `abcdef` -| `hex_upper` | 16 | `0123456789`, `ABCDEF` -| `hex` | 16 | `0123456789`, `abcdef`, `ABCDEF` - -|=== -==== - -[#zero] -== Char class rule `lexy::dsl::zero` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _char-class-rule_ auto zero; -} ----- - -[.lead] -`zero` is a {{% char-class-rule %}} that matches `0`. - -Its name is `digit.zero`. -In the parse tree, it creates a single token node with the {{% docref "lexy::predefined_token_kind" %}} `lexy::digit_token_kind`. - -{{% playground-example zero "The number zero" %}} - -[#digit] -== Char class rule `lexy::dsl::digit` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template - constexpr _char-class-rule_ auto digit; -} ----- - -[.lead] -`digit` is a {{% char-class-rule %}} that matches one digit of the specified `Base`. - -Its name is `digit.`. -In the parse tree, it creates a single token node with the {{% docref "lexy::predefined_token_kind" %}} `lexy::digit_token_kind`. - -{{% playground-example digit "A hexadecimal digit, upper-case letters only" %}} - -NOTE: The only difference between `lexy::dsl::digit` and {{% docref "lexy::dsl::ascii::digit" %}} is the name of the char class. - -[#digits] -== Token rule `lexy::dsl::digits` - -{{% interface %}} ----- -namespace lexy -{ - struct forbidden_leading_zero {}; -} - -namespace lexy::dsl -{ - class _digits-dsl_ // models _token-rule_ - { - public: - constexpr _digit-dsl_ sep(_token-rule_ auto s) const; - - constexpr _digit-dsl_ no_leading_zero() const; - }; - - template - constexpr _digits-dsl_ auto digits; -} ----- - -[.lead] -`digits` is a {{% token-rule %}} that matches one or more digits of the specified `Base` with optional separator. - -Matching:: - Matches and consumes `digit` once, then tries to match and consume it again until it no longer matches. - If a separator has been specified using `.sep()`, it tries to match it after every digit. - If it succeeds, matches `digit` immediately afterwards. -Errors:: - * `lexy::forbidden_leading_zero`: if `.no_leading_zero()` was called and it matches `zero` as its first digit, which is then followed by a digit or separator. - The error is raised at the position of the zero. - The rule then fails without consuming additional input. - * All errors raised by matching the initial digit. - The rule then fails. - * All errors raised by matching a digit after a separator to prevent trailing separators. - The rule then fails. -Parse tree:: - Single token node with the {{% docref "lexy::predefined_token_kind" %}} `lexy::digit_token_kind`. - -{{% playground-example digits "Decimal digits with digit separator but without leading zeroes" %}} - -NOTE: If a digit separator is specified, it can be between any two digits. -lexy does not enforce the use of thousands separators only, or other conventions. - -NOTE: `digits` does not produce the value of the number it parsed. -Use {{% docref "lexy::dsl::integer" %}} for that. - -[#n_digits] -== Token rule `lexy::dsl::n_digits` - -{{% interface %}} ----- -namespace lexy::dsl -{ - class _n_digits-dsl_ // models _token-rule_ - { - public: - constexpr _n_digits-dsl_ sep(_token-rule_ auto s) const; - }; - - template - constexpr _n_digits-dsl_ auto n_digits; -} ----- - -[.lead] -`n_digits` is a {{% token-rule %}} that matches exactly `N` digits of the specified `Base` with optional separator. - -Matching:: - Matches and consumes `digit` `N` times; any additional trailing digits are ignored. - If a digit separator has been specified using `.sep()`, it tries to match it after every digit except the last one. - This does not count towards the number of digits. -Errors:: - All errors raised by matching `digit`. The rule then fails. -Parse tree:: - Single token node with the {{% docref "lexy::predefined_token_kind" %}} `lexy::digit_token_kind`. - -{{% playground-example n_digits "A `\x` escape sequence" %}} - -NOTE: If a digit separator is specified, it can be between any two digits. -lexy does not enforce the use of thousands separators only, or other conventions. - -NOTE: `n_digits` does not produce the value of the number it parsed. -Use {{% docref "lexy::dsl::integer" %}} or {{% docref "lexy::dsl::code_point_id" %}} for that. - -[#digit-sep] -== Pre-defined digit separators - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _token-rule_ auto digit_sep_underscore = lit_c<'_'>; - constexpr __token-rule__ auto digit_sep_tick = lit_c<'\''>; // note: single character -} ----- - -[.lead] -The {{% token-rule %}}s `digit_sep_underscore` and `digit_sep_tick` are two convenience aliases for {{% docref "lexy::dsl::lit_c" %}} that match common digit separators. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/eof.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/eof.adoc deleted file mode 100644 index 14d603846a..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/eof.adoc +++ /dev/null @@ -1,43 +0,0 @@ ---- -header: "lexy/dsl/eof.hpp" -entities: - "lexy::dsl::eof": eof ---- - -[#eof] -== Branch rule `lexy::dsl::eof` - -{{% interface %}} ----- -namespace lexy -{ - struct expected_eof {}; -} - -namespace lexy::dsl -{ - constexpr _branch-rule_ auto eof; -} ----- - -[.lead] -`eof` is a {{% branch-rule %}} that matches the end of input (EOF). - -(Branch) Parsing:: - Succeeds if the reader is at the end of the input, without consuming anything. -Errors:: - `lexy::expected_eof`: at the unchanged reader position. It then recovers immediately. -Parse tree:: - Single token node whose range is empty with the {{% docref "lexy::predefined_token_kind" %}} `lexy::eof_token_kind`. - -Parsing `eof` multiple times in sequence has no additional effect: -they all succeed if the first one succeeded and they all fail if the first one failed. - -{{% playground-example eof "Match the empty input" %}} - -{{% playground-example no_trailing "Prevent trailing characters" %}} - -CAUTION: Without `eof`, `lexy` will happily match the prefix of an input only, ignoring any junk characters after it is finished. - -NOTE: It does not skip whitespace before checking for EOF. Use {{% docref "whitespace" "`lexy::dsl::whitespace + eof`" %}} to do that. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/error.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/error.adoc deleted file mode 100644 index 56dce717e9..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/error.adoc +++ /dev/null @@ -1,108 +0,0 @@ ---- -header: "lexy/dsl/error.hpp" -entities: - "lexy::dsl::error": error - "lexy::dsl::must": must ---- -:toc: left - -[.lead] -Rules that generate errors. - -[#error] -== Rule `lexy::dsl::error` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template - constexpr _branch-rule_ auto error; - - template - constexpr _branch-rule_ auto error(_rule_ auto rule); -} ----- - -[.lead] -`error` is a rule that always fails and reports an error. - -Parsing:: - The first overload fails immediately without consuming anything. - The second overload first tries to match `rule` in a new context. - The rule then still fails unconditionally without consuming anything. -Branch parsing:: - In a branch, `error` fails in the same way, but the branch has been considered taken and no backtracking occurs. -Errors:: - A generic error with the specified `Tag`. - For the first overload, it is raised at the unchanged reader position. - For the second overload, its range covers everything matched by `rule`. - The rule then fails. -Values:: - None. - -{{% playground-example choice_error "Generate a custom error for an unknown greeting" %}} - -{{% playground-example choice_error_range "Generate a custom error for an unknown greeting with range" %}} - -TIP: Use `error` in error production: if a certain ill-formed input is common, create a separate rule for it. -If it is parsed, a custom error is always raised. - -NOTE: Automatic {{% docref whitespace %}} skipping is disabled while parsing `rule`. - -WARNING: `rule` does not have access to any context variables created by the context-sensitive parsing facilities and it can't use recursion. - -[#must] -== Branch rule `lexy::dsl::must` - -{{% interface %}} ----- -namespace lexy::dsl -{ - class _must-dsl_ // note: not a _rule_ itself - { - public: - template - static constexpr _branch-rule_ auto error; - - template - constexpr _branch-rule_ auto error(_rule_ auto capture); - }; - - constexpr _must-dsl_ must(_branch-rule_ auto rule); -} ----- - -[.lead] -`must` is a {{% branch-rule %}} that tries to parse another branch rule and raises a specific error if that backtracks. - -If `must(rule).error` is used, the associated error rule `e` is `lexy::dsl::error`. -Otherwise, if `must(rule).error(capture)` is used, the associated error rule `e` is `lexy::dsl::error(capture)`. - -Requires:: - `rule` is a branch rule that is not unconditionally taken (e.g. not {{% docref "lexy::dsl::else_" %}}). -Parsing:: - Parses the {{% docref choice %}} `rule | e`, where `e` is the associated error rule, - i.e. it tries to parse `rule` and raises a specific error if that fails. -Branch parsing:: - Tries to parse `rule` and produces the same result. -Errors:: - * All errors raised by branch parsing of `rule`. - The rule then fails if `rule` has failed. - * A generic error with the specified `Tag`: - if the rule backtracks during non-branch parsing. - Its range covers anything consumed by the optional `capture` rule, just like `lexy::dsl::error`. - -{{% playground-example must "Parse a very basic echo command" %}} - -NOTE: See {{< github-example shell >}} for a more complete shell parser. - -TIP: Use `must(rule).error` if you sometimes need to parse `rule` unconditionally with a specific error, and sometimes as a branch rule. - -NOTE: The difference between `must(rule).error` and the {{% docref choice %}} `rule | lexy::dsl::error` is that the former is still a branch condition. -The choice is not a branch condition, as it is unconditionally: it will either parse `rule` and succeed, or fail, but never backtrack. -`must` on the other hand will behave exactly the same as `rule` during branch parsing. -That way, something like {{% docref "lexy::dsl::if_" %}}`(must(rule).error)` is equivalent to `lexy::dsl::if_(rule)`. - -NOTE: If `rule` is a {{% token-rule %}}, `must(rule).error` is equivalent to `rule.error`. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/expression.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/expression.adoc deleted file mode 100644 index 946e15d1ca..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/expression.adoc +++ /dev/null @@ -1,321 +0,0 @@ ---- -header: "lexy/dsl/expression.hpp" -entities: - "expression": doc - "lexy::expression_production": expression_production - "lexy::dsl::atom": expression_production - "lexy::dsl::groups": groups - "lexy::dsl::infix_op_left": infix_op_left - "lexy::dsl::infix_op_right": infix_op_right - "lexy::dsl::infix_op_list": infix_op_list - "lexy::dsl::infix_op_single": infix_op_single - "lexy::dsl::postfix_op": postfix_op - "lexy::dsl::prefix_op": prefix_op ---- -:toc: left - -[.lead] -Support for operator precedence parsing. - -Some terminology: - -Operator:: - A {{% docref "lexy::dsl::op" %}} rule (or multiple composed with {{% docref "lexy::dsl::operator/ (operator)" %}}). -Operand:: - The objects manipulated by an operator. -Operation:: - An operator together with arity, associativity and operands. - Its binding power (precedence) is determined implicitly by its relation to other operations in its operand. -Chain:: - The same operation applied multiple times in direct sequence. -Expression:: - Multiple chains of different operations, potentially nested. - -[#expression_production] -== Class `lexy::expression_production` - -{{% interface %}} ----- -namespace lexy -{ - struct max_operator_nesting_exceeded {}; - struct operator_chain_error {}; - struct operator_group_error {}; - - struct expression_production - { - using operator_nesting_error = lexy::max_operator_nesting_exceeded; - using operator_chain_error = lexy::operator_chain_error; - using operator_group_error = lexy::operator_group_error; - - static constexpr std::size_t max_operator_nesting; - - static constexpr auto rule = _see-below_; - }; -} - -namespace lexy::dsl -{ - struct atom {}; -} ----- - -[.lead] -`expression_production` is a base class of a production that wants to parse an expression. - -[source,cpp,subs="+quotes"] ----- -struct _Operation_ : _operation-base_ -{ - static constexpr auto op = _operator-rule_; - using operand = _Operation-or-dsl::atom_; -}; - -struct _Expression_ : lexy::expression_production -{ - static constexpr auto atom = _rule_; - using operation = _Operation_; -}; ----- - -The derived class must have the same members as `Expression` shown above. -Optionally, it can shadow each member of `lexy::expression_production` indicated in the interface, except for `rule`, to override them to custom values. -`atom` specifies the rule that is used to parse an atomic operand, i.e. one that isn't another operation in turn. -`operation` specifies the top-level operation, i.e. the one with the lowest binding power. -It is a type with the same members as `Operation` shown above: -the operator rule ({{% docref "lexy::dsl::op" %}} or {{% docref "lexy::dsl::operator/ (operator)" %}}) and the operand, -which is either another `Operation`, {{% docref "lexy::dsl::groups" %}}, or `dsl::atom`, which indicates that the operand is the rule described in the `atom` member. - -The behavior of the generated `rule` of the production is as follows: - -Parsing:: - Parses an arbitrary operation chain consisting of the operators mentioned in the expression (by starting with the root `operation` and following the `operands`). - The rules for operation parsing are described in the individual base classes ({{% docref "lexy::dsl::infix_op_left" %}}, {{% docref "lexy::dsl::infix_op_right" %}}, {{% docref "lexy::dsl::infix_op_single" %}}, {{% docref "lexy::dsl::infix_op_list" %}}, {{% docref "lexy::dsl::postfix_op" %}}, {{% docref "lexy::dsl::prefix_op" %}}). - If the input does not contain any operator, parses a single `atom`. - If there is a trailing operator, it will attempt to parse a following operand greedily. -Errors:: - * All errors raised by parsing `atom` or an operator (only possible if the operator is a branch rule). - * `Expression::operator_nesting_error`: if the nesting level of operators exceeds `Expression::max_operator_nesting_exceeded`, at the location of the operator that first exceeds it. - The rule then fails. - * `Expression::operator_chain_error`: see {{% docref "lexy::dsl::infix_op_single" %}}. - * `Expression::operator_group_error`: see {{% docref "lexy::dsl::groups" %}}. -Values:: - As the rule is the only rule of the entire production, it does not lazily produce values like the other rules, but passes them directly to the callback of the production. - * For each instance of the atomic rule, all values it produces are passed to the callback. - * For an operation, the value of the operands and of the operator are passed to the callback. - The value of an operand is always the result of another callback invocation. -Parse tree:: - * An operation creates a production node labeled with the type of the operation, its children are the operands and operator nodes. - * The atomic operand creates its nodes as it normally would. - -{{% playground-example expr "Parse a simple mathematical expression" %}} - -{{% godbolt-example op-choice "Parse and evaluate an even simpler mathematical expression" %}} - -TIP: See {{< github-example calculator >}} for a bigger example. - -CAUTION: If two operators at different binding powers share a common prefix (e.g. `*` and `**` or `=` and `==`), -it might be necessary to use {{% docref "lexy::dsl::not_followed_by" %}}. - -[#groups] -== Operand specification `lexy::dsl::groups` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template <_Operation_... Operands> - struct groups - {}; -} ----- - -[.lead] -`groups` is an operand specification that indicates that the operand is one of the specified operations. - -Parsing:: - When attempting to parse an operand in the current operation, it will parse one of the specified `Operands` (a "group"), - which can be other operations with their own operators. - Parsing fails, if operators from distinct groups are mixed. -Errors:: - * All errors raised by regular expression parsing. - * `Expression::operator_group_error`: if an operator from group B was parsed after an operator from group 1, at the position of operator B. - -{{% playground-example expr_groups "Parse either a math or a bit operation" %}} - -[#infix_op_left] -== Operation base `lexy::dsl::infix_op_left` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct infix_op_left {}; -} ----- - -[.lead] -`infix_op_left` is an operation base that specifies a left-associative infix operator. - -Parsing:: - It will parse the chain `operand op operand`. - `a op b op c` is treated as `(a op b) op c`. -Errors:: - All errors raised by parsing the operand or operator. -Values:: - It will invoke the callback with the value of the left operand, followed by the values of the operator, followed by the value of the right operand. - In `a op b op c`, it will invoke `callback(callback(a, op, b), op, c)`. -Parse tree:: - A production node labeled with the type of the operation. - Its children are all nodes created from the left operand, followed by the nodes for the operator, followed by the nodes from the right operand. - -{{% playground-example infix_op_left "Parse a left-associative infix operator" %}} - -[#infix_op_right] -== Operation base `lexy::dsl::infix_op_right` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct infix_op_right {}; -} ----- - -[.lead] -`infix_op_right` is an operation base that specifies a right-associative infix operator. - -Parsing:: - It will parse the chain `operand op operand`. - `a op b op c` is treated as `a op (b op c)`. -Errors:: - All errors raised by parsing the operand or operator. -Values:: - It will invoke the callback with the value of the left operand, followed by the values of the operator, followed by the value of the right operand. - In `a op b op c`, it will invoke `callback(a, op, callback(b, op, c))`. -Parse tree:: - A production node labeled with the type of the operation. - Its children are all nodes created from the left operand, followed by the nodes for the operator, followed by the nodes from the right operand. - -{{% playground-example infix_op_right "Parse a right-associative infix operator" %}} - -[#infix_op_single] -== Operation base `lexy::dsl::infix_op_single` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct infix_op_single {}; -} ----- - -[.lead] -`infix_op_single` is an operation base that specifies a non-associative infix operator. - -Parsing:: - It will parse the chain `operand op operand`. - `a op b op c` is an error. -Errors:: - * All errors raised by parsing the operand or operator. - * `Expression::operator_chain_error`: if the operator occurs multiple times in the chain, at the second location. - It then recovers, treating it as a left-associative operator. -Values:: - It will invoke the callback with the value of the left operand, followed by the values of the operator, followed by the value of the right operand. -Parse tree:: - A production node labeled with the type of the operation. - Its children are all nodes created from the left operand, followed by the nodes for the operator, followed by the nodes from the right operand. - -{{% playground-example infix_op_single "Parse a non-associative infix operator" %}} - -[#infix_op_list] -== Operation base `lexy::dsl::infix_op_list` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct infix_op_list {}; -} ----- - -[.lead] -`infix_op_list` is an operation base that specifies an associative infix operator. - -Requires:: - The callback of the expression production is a sink. -Parsing:: - It will parse the chain `operand op operand`. - `a op b op c` is treated as `a op b op c`, i.e. no implicit grouping occurs. -Errors:: - All errors raised by parsing the operand or operator. -Values:: - It will use the callback as a sink. - The sink is passed the value of the initial operand, then it is passed all values of the first operator, - the value of the next operand, all values of the second operator, and so on. - In `a op b op c`, it will invoke `sink(a), sink(op), sink(b), sink(op), sink(c)`. -Parse tree:: - A production node labeled with the type of the operation. - Its children are all nodes created from the initial operand, followed by the nodes for the first operator, followed by the nodes from the next operand, - followed by all nodes from the second operator, and so on. - -{{% playground-example infix_op_list "Parse an associative infix operator" %}} - -TIP: This can be used to implement chained comparisons, as seen in {{< github-example calculator >}}. - -[#postfix_op] -== Operation base `lexy::dsl::postfix_op` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct postfix_op {}; -} ----- - -[.lead] -`postfix_op` is an operation base that specifies a postfix operator. - -Parsing:: - It will parse the chain `operand op`. - `a op op c` is treated as `(a op) op`. -Errors:: - All errors raised by parsing the operand or operator. -Values:: - It will invoke the callback with the value of the operand, followed by the values of the operator. - In `a op op`, it will invoke `callback(callback(a, op), op)`. -Parse tree:: - A production node labeled with the type of the operation. - Its children are all nodes created from the operand, followed by the nodes for the operator. - -{{% playground-example postfix_op "Parse a postfix operator" %}} - -[#prefix_op] -== Operation base `lexy::dsl::prefix_op` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct prefix_op {}; -} ----- - -[.lead] -`prefix_op` is an operation base that specifies a prefix operator. - -Parsing:: - It will parse the chain `op operand`. - `op op a` is treated as `op (op a)`. -Errors:: - All errors raised by parsing the operand or operator. -Values:: - It will invoke the callback with the value of the operator, followed by the value of the operand. - In `op op a`, it will invoke `callback(op, callback(op, a))`. -Parse tree:: - A production node labeled with the type of the operation. - Its children are the nodes for the operator, followed by the nodes from the operand. - -{{% playground-example prefix_op "Parse a prefix operator" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/follow.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/follow.adoc deleted file mode 100644 index 43e9c41638..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/follow.adoc +++ /dev/null @@ -1,77 +0,0 @@ ---- -header: "lexy/dsl/follow.hpp" -entities: - "lexy::dsl::followed_by": followed_by - "lexy::dsl::not_followed_by": not_followed_by ---- -:toc: left - -[.lead] -The `followed_by` and `not_followed_by` literal rules. - -[#followed_by] -== Literal rule `lexy::dsl::followed_by` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _literal-rule_ auto followed_by(_literal-rule_ lit, - _char-class-rule_ auto cc) - { - return not_followed_by(lit, -cc); - } - - constexpr _literal-rule_ auto followed_by(_literal-rule_ lit, - _literal-char-class-rule_ auto cc) - { - return not_followed_by(lit, -cc); - } -} ----- - -[.lead] -`followed_by` is a {{% literal-rule %}} that ensures another {{% literal-rule %}} is followed by a {{% char-class-rule %}}. - -It is just syntax sugar for the primary form, {{% docref "lexy::dsl::not_followed_by" %}}. - -[#not_followed_by] -== Literal rule `lexy::dsl::not_followed_by` - -{{% interface %}} ----- -namespace lexy -{ - struct follow_restriction - {}; -} - -namespace lexy::dsl -{ - constexpr _literal-rule_ auto not_followed_by(_literal-rule_ lit, - _char-class-rule_ auto cc); - constexpr _literal-rule_ auto not_followed_by(_literal-rule_ lit, - _literal-char-class-rule_ auto cc); -} ----- - -[.lead] -`not_followed_by` is a {{% literal-rule %}} that ensures another {{% literal-rule %}} is not followed by a {{% char-class-rule %}}. - -Requires:: - `lit` is not a {{% docref "lexy::dsl::keyword" %}} rule. -Matching:: - Matches and consumes `lit`. - Otherwise, tries to match `cc` without consuming it and fails if it does. - If `lit` uses case folding (e.g. {{% docref "lexy::dsl::ascii::case_folding" %}}), it also applies to `cc`. -Errors:: - * All errors raised by `lit` when it fails. - * `lexy::follow_restriction`: if `cc` matches; at the position where it matched. - The rule then fails. -Parse tree:: - The single token node created by `lit`. - -{{% playground-example not_followed_by "Match `=` but not `==`" %}} - -TIP: Use {{% docref "lexy::dsl::keyword" %}} for the common case of parsing a literal that is not a valid identifier. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/identifier.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/identifier.adoc deleted file mode 100644 index b26474c77d..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/identifier.adoc +++ /dev/null @@ -1,201 +0,0 @@ ---- -header: "lexy/dsl/identifier.hpp" -entities: - "lexy::dsl::identifier": identifier - "lexy::dsl::keyword": keyword - "LEXY_KEYWORD": keyword ---- -:toc: left - -[.lead] -The `identifier` and `keyword` rules. - -[#identifier] -== Rule `lexy::dsl::identifier` - -{{% interface %}} ----- -namespace lexy -{ - struct reserved_identifier {}; -} - -namespace lexy::dsl -{ - struct _identifier-dsl_ // models _branch-rule_ - { - //=== modifiers ===// - constexpr _identifier-dsl_ reserve(auto ... rules) const; - constexpr _identifier-dsl_ reserve_prefix(auto ... rules) const; - constexpr _identifier-dsl_ reserve_containing(auto ... rules) const; - constexpr _identifier-dsl_ reserve_suffix(auto ... rules) const; - - //=== sub-rules ===// - constexpr _token-rule_ auto pattern() const; - - constexpr _token-rule_ auto leading_pattern() const; - constexpr _token-rule_ auto trailing_pattern() const; - }; - - constexpr _identifier-dsl_ identifier(_char-class-rule_ auto leading, - _char-class-rule_ auto trailing); - - constexpr _identifier-dsl_ identifier(_char-class-rule_ auto c) - { - return identifier(c, c); - } - -} ----- - -[.lead] -`identifier` is a rule that parses an identifier. - -It can be created using two overloads. -The first overload takes a {{% char-class-rule %}} that matches the `leading` character of the identifier, -and one that matches all `trailing` characters after the first. -The second overload takes just one {{% char-class-rule %}} and uses it both as `leading` and `trailing` characters. - -Parsing:: - Matches and consumes the token `.pattern()` (see below). - Then verifies that the lexeme formed from `.pattern()` (excluding any trailing whitespace), is not reserved (see below). -Branch parsing:: - Tries to match and consume the token `.pattern()` (see below), backtracking if that fails. - Otherwise it checks for reserved identifiers and backtracks if it was reserved. - As such, branch parsing only raises errors due to the implicit whitespace skipping. -Errors:: - * All errors raised by `.pattern()`. The rule then fails if not during branch parsing. - * `lexy::reserved_identifier`: if the identifier is reserved; its range covers the identifier. - The rule then recovers. -Values:: - A single {{% docref "lexy::lexeme" %}} that is the parsed identifier (excluding any trailing whitespace). -Parse tree:: - The single token node created by `.pattern()` (see below). - Its kind cannot be overridden. - -{{% playground-example identifier "Parse a C-like identifier" %}} - -{{% playground-example identifier-unicode "Parse a Unicode-aware C-like identifier" %}} - -{{% godbolt-example identifier_case_folded "Parse a case-insensitive identifier" %}} - -TIP: Use the character classes from {{% docref "lexy::dsl::ascii" %}} for simple identifier matching as seen in the example. - -TIP: Use the callback {{% docref "lexy::as_string" %}} to convert the {{% docref "lexy::lexeme" %}} to a string. - -=== Reserving identifiers - -{{% interface %}} ----- -constexpr _identifier-dsl_ reserve(auto ... rules) const; <1> -constexpr _identifier-dsl_ reserve_prefix(auto ... rules) const; <2> -constexpr _identifier-dsl_ reserve_containing(auto ... rules) const; <3> -constexpr _identifier-dsl_ reserve_suffix(auto ... rules) const; <4> ----- - -[.lead] -Reserves an identifier. - -Initially, no identifier is reserved. -Identifiers are reserved by calling `.reserve()` or its variants passing it a {{% literal-rule %}} or {{% docref "lexy::dsl::literal_set" %}}. -If this has happened, parsing the `identifier` rule creates a partial input from the lexeme and matches it against the specified rules as follows: - -* (1) `.reserve()`: All rules specified here are matched against the partial input. - If they match the entire partial input, the identifier is reserved. -* (2) `.reserve_prefix()`: All rules specified here are matched against the partial input. - If they match a prefix of the partial input, the identifier is reserved. -* (3) `.reserve_containing()`: All rules specified here are matched against the partial input. - If they match somewhere in the partial input, the identifier is reserved. -* (4) `.reserve_suffix()`: All rules specified here are matched against the partial input. - If they match a suffix of the partial input, the identifier is reserved. - -If one `rule` passed to a `.reserve()` call or variant uses case folding (e.g. {{% docref "lexy::dsl::ascii::case_folding" %}}), all other rules in the same call also use that case folding, but not rules in a different call. -This is because internally each call creates a fresh {{% docref "lexy::dsl::literal_set" %}}, which has that behavior. - -{{% playground-example reserved_identifier "Parse a C like identifier that is not reserved" %}} - -{{% playground-example reserved_identifier_case_folding "Parse a C like identifier with case-insensitive keywords" %}} - -CAUTION: The `identifier` rule doesn't magically learn about the keywords you have created. -They are only reserved if you actually pass them to `.reserve()`. -This design allows you to use a different set of reserved identifiers in different places in the grammar. - -=== Token rule `.pattern()` - -{{% interface %}} ----- -constexpr _token-rule_ auto pattern() const; ----- - -[.lead] -`.pattern()` is a {{% token-rule %}} that matches the basic form of the identifier without checking for reserved identifiers. - -Matching:: - Matches and consumes `leading`, - then matches and consumes {{% docref "lexy::dsl::while_" %}}`(trailing)`, - where `leading` and `trailing` are the arguments passed to `identifier()`. - Whitespace skipping is disabled inside the `pattern()`, - but it will be skipped after `pattern()`. -Errors:: - All errors raised by matching `leading`. - The rule then fails. -Parse tree:: - A single token node whose range covers everything consumed. - Its {{% docref "lexy::predefined_token_kind" %}} is `lexy::identifier_token_kind`. - -=== Token rules `.leading_pattern()`, `.trailing_pattern()` - -{{% interface %}} ----- -constexpr _token-rule_ auto leading_pattern() const; -constexpr _token-rule_ auto trailing_pattern() const; ----- - -[.lead] -They simply return `leading`/`trailing` from the arguments passed to `identifier()`. - -[#keyword] -== Literal rule `lexy::dsl::keyword` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template - constexpr _literal-rule_ auto keyword(_identifier-dsl_ identifier); - template - constexpr _literal-rule_ auto keyword(_identifier-dsl_ identifier); -} - -#define LEXY_KEYWORD(Str, Identifier) lexy::dsl::keyword(identifier) ----- - -[.lead] -`keyword` is a {{% literal-rule %}} that matches a keyword. - -Matching:: - Tries to match and consume `identifier.pattern()`, - i.e. the basic pattern of an identifier ignoring any reserved identifiers. - Then creates a partial input that covers everything just consumed (without the trailing whitespace) - and matches {{% docref "lexy::dsl::lit" %}}`` on that input. - Succeeds only if that consumes the entire partial input. -Errors:: - {{% docref "lexy::expected_keyword" %}}: if either `identifier.pattern()` or the `lit` rule failed. - Its range covers the everything consumed by `identifier.pattern()` and its `.string()` is `Str`. -Parse tree:: - Single token node with the {{% docref "lexy::predefined_token_kind" %}} `lexy::literal_token_kind`. - -The macro `LEXY_KEYWORD(Str, Identifier)` is equivalent to `keyword(Identifier)`, -except that it also works on older compilers that do not support C++20's extended NTTPs. -Use this instead of `keyword(identifier)` if you need to support them. - -{{% playground-example keyword "Parse a keyword" %}} - -NOTE: While {{% docref "lexy::dsl::lit" %}}`<"int">` would happily consume a prefix of `"integer"`, `keyword<"int">(id)`, for a matching `id`, would not. - -NOTE: A keyword does not necessarily need to be a reserved identifier or vice-versa. - -NOTE: The {{% encoding %}} caveats of {{% literal-rule %}}s apply here as well. - -TIP: Use {{% docref "lexy::dsl::ascii::case_folding" %}} or its Unicode variants to parse a case insensitive keyword. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/if.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/if.adoc deleted file mode 100644 index 97997595cd..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/if.adoc +++ /dev/null @@ -1,36 +0,0 @@ ---- -header: "lexy/dsl/if.hpp" -entities: - "lexy::dsl::if_": if_ ---- -:toc: left - -[#if_] -== Rule `lexy::dsl::if_` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto if_(_branch-rule_ auto branch); -} ----- - -[.lead] -`if_` is a rule that tries to parse a {{% branch-rule %}}. - -Parsing:: - Tries to parse `branch`. - If that backtracks, succeeds without consuming anything. -Errors:: - All errors raised by `branch` during branch parsing. - The rule then fails if `branch` has failed. -Values:: - All values produced by `branch`. - -{{% playground-example if "Only parse a fraction if preceded by a dot " %}} - -NOTE: `if_(branch)` is functionally equivalent to the {{% docref choice %}} `branch | lexy::dsl::else_`. - -TIP: Use {{% docref "lexy::dsl::opt" %}} if you need a value to indicate that `branch` was not parsed. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/integer.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/integer.adoc deleted file mode 100644 index af45582d52..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/integer.adoc +++ /dev/null @@ -1,175 +0,0 @@ ---- -header: "lexy/dsl/integer.hpp" -entities: - "lexy::integer_traits": integer_traits - "lexy::dsl::integer": integer - "lexy::dsl::code_point_id": code_point_id ---- -:toc: left - -[.lead] -The `integer` and `code_point_id` rules. - -[#integer_traits] -== `lexy::integer_traits` - -{{% interface %}} ----- -namespace lexy -{ - template - struct integer_traits; - - template - requires std::is_integral_v && !std::is_same_v - struct integer_traits { … }; - - template <> - struct integer_traits { … }; - - template - struct unbounded {}; - - template - struct integer_traits> { … }; -} ----- - -[.lead] -The class template `integer_traits` gives information about integers that are used to parse them. - -Every specialization must have members that look the following with the indicated semantic meaning: - -{{% interface %}} ----- -struct _integer-traits-specialization_ -{ - // The actual integer type that is being parsed; - // it is usually the template parameter itself. - // `type(0)` must be a valid expression that creates the zero integer. - using type = _some-type_; - - // If `true`, `type` has a maximal value it can store. - // If `false`, `type` is unbounded and range checks during parsing are disabled. - static constexpr bool is_bounded; - - // Precondition: `digit < Radix`. - // Effects: `result = result * Radix + digit` or equivalent. - template - static constexpr void add_digit_unchecked(type& result, unsigned digit); -}; ----- - -If `is_bounded == true`, it must also have the following additional members: - -{{% interface %}} ----- -struct _integer-traits-bounded-specialization_ -{ - // The number of digits necessary to write the maximal value of `type` in the given `Radix`. - template - static constexpr std::size_t max_digit_count; - - // Precondition: `digit < Radix`. - // Effects: `result = result * Radix + digit` or equivalent. - // Returns: `true` if the resulting value fits in `type`, `false` if an overflow occurred or would occurr. - template - static constexpr bool add_digit_checked(type& result, unsigned digit); -}; ----- - -The integer traits are specialized for the built-in integral types (except `bool`) with the expected semantics, -as well as {{% docref "lexy::code_point" %}}. -The specialization for `lexy::unbounded` behaves the same as the one for plain `T`, -except that `is_bounded == false`. - -TIP: Use `lexy::unbounded` when you know that overflow is impossible, -e.g. because you're parsing two hexadecimal digits as an `unsigned char`. - -[#integer] -== Rule `lexy::dsl::integer` - -{{% interface %}} ----- -namespace lexy -{ - struct integer_overflow {}; -} - -namespace lexy::dsl -{ - template - constexpr _branch-rule_ auto integer(_token-rule_ auto digits); - - template - constexpr _branch-rule_ auto integer(_digits-dsl_ digits); - template - constexpr _branch-rule_ auto integer(_ndigits-dsl_ digits); - - template - constexpr auto integer = integer(digits<>); - template - constexpr auto integer = integer(digits); -} ----- - -[.lead] -`integer` is a {{% branch-rule %}} that parses a sequence of digits as an integer. - -Requires:: - * `T` is a type with a specialization of <>. - * `Base` is one of the supported {{% docref bases %}}. - If `digits` is some instantiation of {{% docref "lexy::dsl::digits" %}} or {{% docref "lexy::dsl::n_digits" %}}, - `Base` is deduced and must not be specified. -Parsing:: - Parses `digits`, which defaults to {{% docref "lexy::dsl::digits" %}}, with the base defaulting to `lexy::dsl::decimal`. -Branch parsing:: - Tries to parse `digits`, backtracks if that backtracks. - It will not backtrack on integer overflow. -Errors:: - * `lexy::integer_overflow`: if converting the consumed digits to an integer leads to overflow. - Its range covers everything consumed by `digits`. - The rule then recovers without consuming additional input; - the integer value produced is the last value it had before the overflow occurred. - * All errors raised by parsing `digits`. - The rule then recovers by consuming as much additional digits of the `Base` as possible. - If `digits` is a known instantiation with a separator, it will also skip separators. - This happens without any validation for trailing separators or leading zeros. - Recovery fails if `digits` and this recovery process combined haven't consumed any input. - Otherwise, it converts everything consumed and recovery succeeds. -Values:: - First produces all values from parsing `digits`. - Then produces the integer of type `T` by iterating over the code units consumed by `digits` and handling them as follows: - If a code unit is a valid digit of `Base`, its numerical value is determined and the resulting digit added to the result using <>. - Otherwise, the code unit is ignored without any additional validation. - -{{% godbolt-example integer "Parse an `int`" %}} - -[#code_point_id] -== Rule `lexy::dsl::code_point_id` - -{{% interface %}} ----- -namespace lexy -{ - struct invalid_code_point {}; -} - -namespace lexy::dsl -{ - template - constexpr _branch-rule_ auto code_point_id; -} ----- - -[.lead] -`code_point_id` is a {{% branch-rule %}} that parses a sequence of `N` digits as a {{% docref "lexy::code_point" %}}. - -`code_point_id` behaves almost exactly like `integer(n_digits)`. -The only difference is that integer overflows raises a generic error with tag `lexy::invalid_code_point` as opposed to `lexy::integer_overflow`. - -{{% godbolt-example code_point_id "Parse a code point value" %}} - -CAUTION: The rule still recovers from a `lexy::invalid_code_point`. -The `lexy::code_point` produced might be invalid in that case, i.e. `.is_invalid() == true`. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/list.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/list.adoc deleted file mode 100644 index 655da211ba..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/list.adoc +++ /dev/null @@ -1,82 +0,0 @@ ---- -header: "lexy/dsl/list.hpp" -entities: - "lexy::dsl::list": list ---- - -[#list] -== Rule `lexy::dsl::list` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _branch-rule_ auto list(_branch-rule_ auto item); - - constexpr _rule_ auto list(_rule_ auto item, - _separator_ auto sep); - constexpr _branch-rule_ auto list(_rule_ auto item, - _separator_ auto sep); -} ----- - -[.lead] -`list` is a rule that parses a non-empty list of `item`, optionally separated by `sep`. - -Requires:: - If the {{% docref separator %}} `sep` is {{% docref "lexy::dsl::trailing_sep" %}}, - `item` is a {{% docref branch-rule %}}; - i.e. the second overload must not be called. -Parsing:: - It first parses `item` once. - Then there are four cases to consider: - 1. First overload, no separator. - Then it repeatedly tries to parse `rule`. - It finishes when `rule` backtracks. - 2. Second overload, {{% docref "lexy::dsl::sep" %}}. - Then it repeatedly tries to parse `sep`. - If that backtracks, it is finished. - Otherwise, it parses `item` and repeats. - 3. Third overload, {{% docref "lexy::dsl::sep" %}}. - Then it repeatedly tries to parse `sep`. - If that backtracks, it is finished. - Otherwise, it tries to parse `item`. - If that backtracks, it has an unexpected trailing separator. - Otherwise, it repeats. - 4. Third overload, {{% docref "lexy::dsl::trailing_sep" %}}. - Then it repeatedly tries to parse `sep`. - If that backtracks, it is finished. - Otherwise, it tries to parse `item`. - If that backtracks, it has an allowed trailing separator and finishes. - Otherwise, it repeats. -Branch parsing:: - The first and third overloads where `item` is a branch rule, are also a branch rules. - They try to parse the initial `item` and backtrack if that backtracks. - Otherwise, they continues with normal parsing. -Errors:: - * All errors raised by (branch) parsing `item` or `sep`. - It then fails if they failed. - * `lexy::unexpected_trailing_separator`: in case 2, at the position of the trailing separator. - It then recovers by simply consuming the separator and continues. -Values:: - It creates a sink of the current context. - All values produced by `item` and `sep` are forwarded to it; - there are separate calls for every iteration and for `item` and `sep`. - The value of the finished sink is produced as the only value of the `list` rule. - -{{% godbolt-example list "Parse a list of letters (first overload)" %}} - -{{% godbolt-example list_sep "Parse a list of letters separated by commas (second overload, case 2)" %}} - -NOTE: `lexy::dsl::list(item)` matches the same input as {{% docref "lexy::dsl::while_one" %}}`(item)`; -`lexy::dsl::list(item, sep)` (case 2) matches the same input as {{% docref "lexy::dsl::do_while" %}}`(item, sep)`. - -TIP: If your list is always followed by a certain token or surrounded in parenthesis, -you can use {{% docref "lexy::dsl::terminator" %}} and {{% docref "lexy::dsl::brackets" %}}, -which do not require a branch rule as arguments. - -TIP: Use {{% docref "lexy::dsl::opt" %}}`(lexy::dsl::list(...))` to parse a list that might be empty; -this requires a branch condition. - -TIP: Use {{% docref "lexy::as_list" %}} for the callback to create e.g. a `std::vector`. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/literal.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/literal.adoc deleted file mode 100644 index 61049896e2..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/literal.adoc +++ /dev/null @@ -1,194 +0,0 @@ ---- -header: "lexy/dsl/literal.hpp" -entities: - "literal-rule": doc - "lexy::dsl::lit": lit - "LEXY_LIT": lit - "lexy::dsl::lit_c": lit_c - "lexy::dsl::lit_b": lit_b - "lexy::dsl::lit_cp": lit_cp - "lexy::dsl::literal_set": literal_set - "LEXY_LITERAL_SET": literal_set - "lexy::dsl::operator/ (literal)": literal_set ---- -:toc: left - -[.lead] -Token rules that match exact characters. - -{{% interface %}} ----- -template -concept _literal-rule_ = _token-rule_ && …; ----- - -A _literal rule_ is a special {{% token-rule %}} that matches a specified sequence of code units. -They include {{% docref "lexy::dsl::lit" %}} and variants, but also {{% docref "lexy::dsl::keyword" %}}. - -Each literal rule has the same parsing behavior, unless otherwise specified: - -Requires:: - * The {{% encoding %}} of the input must be compatible with the char type of the rule: - Either the char type is the same as the char type of the encoding, or the literal rule matches only ASCII characters. - * If it attempts to match a non-ASCII character, the encoding must be UTF-8, UTF-16, or UTF-32. -Matching:: - * If the char type of the rule is the same as the char type of the encoding, - compares each code unit in the sequence with the current code unit of the input in order. - If they match, one code unit is consumed and the process is repeated. - * If the char type of the rule is not the same as the char type of the encoding, - all code units in the sequence are ASCII characters. - They are transcoded to the target encoding by a `static_cast`, then it behaves the same as in the case above. -Errors:: - {{% docref "lexy::expected_literal" %}}: if one code unit did not compare equal or the reader reached the end of the input. - Its `.string()` is the code unit sequence, its `.index()` is the index of the code unit where the mismatch/missing one occurred, and its `.position()` is the reader position where it started to match the literal. -Parse tree:: - Single token node with the {{% docref "lexy::predefined_token_kind" %}} `lexy::literal_token_kind`. - -NOTE: As they are token rule, literal rules try to skip whitespace directly following the literal. -Use {{% docref "lexy::dsl::no_whitespace" %}} to prevent that. - -CAUTION: It is not checked whether the code unit sequence is a well-formed string (e.g. that it contains no https://en.wikipedia.org/wiki/UTF-8#Invalid_sequences_and_error_handling[ill-formed UTF-8]), and no https://en.wikipedia.org/wiki/Unicode_equivalence#Normalization[normalization] or other https://en.wikipedia.org/wiki/Unicode_equivalence[equivalence checking] is done while matching. -It is also not checked whether the input contains actual well-formed code units, they are simply compared one by one. - -[#lit_c] -== Literal rule `lexy::dsl::lit_c` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template - constexpr _literal-rule_ auto lit_c; -} ----- - -[.lead] -`lit_c`, where `C` is a character type, is a {{% literal-rule %}} that matches the single code unit `C`. - -TIP: Literals that match common {{% docref punctuators %}} are pre-defined. - -[#lit] -== Literal rule `lexy::dsl::lit` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template - constexpr _literal-rule_ auto lit; -} - -#define LEXY_LIT(Str) lexy::dsl::lit ----- - -[.lead] -`lit` is a {{% literal-rule %}} that matches the specified sequence of code units. - -The macro `LEXY_LIT(Str)` is equivalent to `lit`, except that it also works on older compilers that do not support C++20's extended NTTPs. -Use this instead of `lit` if you need to support them. - -{{% playground-example lit "Hello World!" %}} - -{{% playground-example lit_ascii "A different character type, but only ASCII characters" %}} - -{{% playground-example lit_utf8 "UTF-8 encoded string literal" %}} - -TIP: When using non-ASCII characters in a `lit` rule, it is best to specify code points with the `\uXXXX` escape sequences and normalize the input before passing it to `lexy`. - -NOTE: While `lit<"int">` would happily consume a prefix of `"integer"`, {{% docref "lexy::dsl::keyword" %}}`<"int">(id)`, for a matching `id`, would not. -Similar, `lit<"=">` would also consume a prefix of `==`, {{% docref "lexy::dsl::not_followed_by" %}} can be used to prevent that. - -[#lit_b] -== Literal rule `lexy::dsl::lit_b` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template - constexpr _literal-rule_ auto lit_b; -} ----- - -[.lead] -`lit_b` is a {{% literal-rule %}} that matches the specified sequence of bytes. - -Unless all bytes are also valid ASCII characters, it requires that the input {{% encoding %}} is {{% docref "lexy::byte_encoding" %}}. - -TIP: Use {{% docref "lexy::dsl::bom" %}} to match a byte-order mark. - -[#lit_cp] -== Literal rule `lexy::dsl::lit_cp` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template - constexpr _literal-rule_ auto lit_cp; -} ----- - -[.lead] -`lit_cp` is a {{% literal-rule %}} that matches the specific `CodePoint` sequences expressed as a sequence of code units in the {{% encoding %}} of the input. - -It behaves identical to {{% docref "lexy::dsl::lit" %}} where `Str` is determined by encoding all `CodePoint`s in the encoding of the input. - -{{% playground-example "lit_cp" "Match a smiley face" %}} - -[#literal_set] -== Token rule `lexy::dsl::literal_set` - -{{% interface %}} ----- -namespace lexy -{ - struct expected_literal_set {}; -} - -namespace lexy::dsl -{ - constexpr _literal-set_ literal_set(_literal-rule_ auto ... literals); - - template - constexpr _literal-set_ literal_set(_symbol-table_ symbols); - - constexpr _literal-set_ operator/(_literal-set_ lhs, _literal-rule_ auto rhs); - constexpr _literal-set_ operator/(_literal-set_ lhs, _literal-set_ auto rhs); -} - -#define LEXY_LITERAL_SET(...) ----- - -[.lead] -`literal_set` is a {{% token-rule %}} that matches one of the specified literals. - -Requires:: - * Each argument is a {{% literal-rule %}}. - * If one literal rule uses case folding (e.g. {{% docref "lexy::dsl::ascii::case_folding" %}}), - the other rules either do not use it, or use the same case folding rule; - different case foldings cannot be mixed. -Matching:: - Tries to match each literal rule. - If case folding is used, it applies to *all* rules in the set. - Succeeds, if one of the matched, consuming the longest one. -Errors:: - `lexy::expected_literal_set`: if none of the literal rules matched; at the original reader position. - The rule then fails without consuming anything. -Parse tree:: - Single token node with the {{% docref "lexy::predefined_token_kind" %}} `lexy::literal_token_kind`. - -The second overload creates a literal set that matches all the symbols of the specified {{% docref "lexy::symbol_table" %}}. -It ignores their respective values. - -`operator/` can be used to extend a literal set and add more literal rules to it. -The resulting literal set matches everything already matched by `lhs`, as well as `rhs`. - -The macro `LEXY_LITERAL_SET(args)` is equivalent to `literal_set(args)`, except the type of the individual rules is erased. -This can shorten type names in error messages. - -{{% playground-example literal_set "Match one of the given literals" %}} - -NOTE: The implementation uses a https://en.wikipedia.org/wiki/Trie[trie] to match them efficiently, -instead of trying one after the other. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/lookahead.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/lookahead.adoc deleted file mode 100644 index 08e30bf1c7..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/lookahead.adoc +++ /dev/null @@ -1,52 +0,0 @@ ---- -header: "lexy/dsl/lookahead.hpp" -entities: - "lexy::dsl::lookahead": lookahead ---- - -[#lookahead] -== Branch rule `lexy::dsl::lookahead` - -{{% interface %}} ----- -namespace lexy -{ - struct lookahead_failure {}; -} - -namespace lexy::dsl -{ - struct lookahead // models _branch-rule_ - { - template - static constexpr _lookahead_ error; - }; - - constexpr _lookahead_ lookahead(auto needle, auto end); -} ----- - -[.lead] -`lookahead` is a {{% branch-rule %}} that checks if `needle` is found before `end`. - -Requires:: - `needle` and `end` are {{% literal-rule %}}s or {{% docref "lexy::dsl::literal_set" %}}. -Parsing:: - If it can match `needle` before `end` is matched or before EOF is reached, the branch is taken without having consumed any input. - Otherwise, it raises an error. -Branch parsing:: - Same as parsing, but backtracks instead of raising an error. -Errors:: - A generic error with the specified `Tag` or `lexy::lookahead_failure` at the position where it started to match the lookahead rule. - It then recovers without consuming additional input. -Values:: - None. - -{{% godbolt-example lookahead "Look for an `=` sign before deciding on a branch" %}} - -NOTE: Automatic {{% docref whitespace %}} skipping is disabled while parsing `needle` or `end`. - -CAUTION: This rule requires backtracking, which can slow down parsing. - -TIP: Use {{% docref "lexy::dsl::peek" %}} if you want to check that `needle` matches at the current position. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/loop.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/loop.adoc deleted file mode 100644 index 4a3dbd7ff5..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/loop.adoc +++ /dev/null @@ -1,154 +0,0 @@ ---- -header: "lexy/dsl/loop.hpp" -entities: - "lexy::dsl::loop": loop - "lexy::dsl::break_": break_ - "lexy::dsl::while_": while_ - "lexy::dsl::while_one": while_one - "lexy::dsl::do_while": do_while ---- -:toc: left - -[.lead] -Rules that loop. - -[#loop] -== Rule `lexy::dsl::loop` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto loop(_rule_ auto rule); -} ----- - -[.lead] -`loop` is a rule that matches `rule` repeatedly. - -Requires:: - `rule` does not produce any values. -Parsing:: - Parses `rule` repeatedly until it either fails or `break_` is parsed. -Errors:: - All errors raised by `rule`. - It then fails if `rule` has failed. -Values:: - None. - -{{% playground-example loop "Repeatedly match a choice" %}} - -TIP: Use {{% docref "lexy::dsl::while_" %}} if there is a simple exit condition, -{{% docref "lexy::dsl::list" %}} if the rule should produce values. - -WARNING: You must not use {{% docref "lexy::dsl::return_" %}} to exit from a loop. - -[#break_] -== Branch rule `lexy::dsl::break_` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _branch-rule_ auto break_; -} ----- - -[.lead] -`break_` is a rule that exits from a `loop`. - -Requires:: - It is used inside a `loop` rule. -(Branch) Parsing:: - Matches everything without consuming anything. - Exits the loop. -Errors:: - None. -Values:: - None. - -[#while_] -== Rule `lexy::dsl::while_` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto while_(_branch-rule_ auto rule) - { - return loop(rule | break_); - } -} ----- - -[.lead] -`while_` is a rule that parses the {{% branch-rule %}} `rule` as often as possible. - -It is entirely equivalent to `loop(rule | break_)`. -It can only fail, if `rule` can fail after it decided to select the branch. -It can accept the empty string if `rule` backtracks on the first iteration. - -{{% playground-example while "Parse a word, which can be empty" %}} - -TIP: Use {{% docref "lexy::dsl::opt" %}} and {{% docref "lexy::dsl::list" %}} if `rule` produces values. - -WARNING: If `rule` does not consume any characters, `while_` will loop forever. - -CAUTION: If {{% docref whitespace %}} skipping is enabled, `while_` will skip whitespace after every token of `rule`. - -[#while_one] -== Rule `lexy::dsl::while_one` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _branch-rule_ auto while_one(_branch-rule_ auto rule) - { - return rule >> while_(rule); - } -} ----- - -[.lead] -`while_one` is a rule that parses `rule` repeatedly, but at least once. - -It is entirely equivalent to `rule >> while_(rule)`. - -{{% playground-example while_one "Parse a word, which cannot be empty" %}} - -TIP: Use {{% docref "lexy::dsl::list" %}} if `rule` produces values. - -CAUTION: If {{% docref whitespace %}} skipping is enabled, `while_one` will skip whitespace after every token of `rule`. -Consider {{% docref "lexy::dsl::identifier" %}}, which does not do that. - -[#do_while] -== Rule `lexy::dsl::do_while` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto do_while(_rule_ auto then, _branch-rule_ auto condition) - { - return then + while_(condition >> then); - } - - constexpr _branch-rule_ auto do_while(_branch-rule_ auto then, - _branch-rule_ auto condition) - { - return then >> while_(condition >> then); - } -} ----- - -[.lead] -`do_while` is a rule that parses `then` while `condition` matches, but checks `condition` after `then`. - -It is entirely equivalent to `then + while_(condition >> then)` if `then` is not a branch, -and `then >> while_(condition >> then)` otherwise. - -{{% playground-example do_while "Parse a list of non-empty words separated by spaces" %}} - -TIP: Use {{% docref "lexy::dsl::list" %}} if `then` produces values with `condition` as separator. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/member.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/member.adoc deleted file mode 100644 index d117ebcf2f..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/member.adoc +++ /dev/null @@ -1,66 +0,0 @@ ---- -header: "lexy/dsl/member.hpp" -entities: - "lexy::dsl::member": member - "lexy::member": member - "LEXY_MEM": member ---- -:toc: left - -[#member] -== Rule `lexy::dsl::member` - -{{% interface %}} ----- -namespace lexy -{ - template - struct member {}; -} - -namespace lexy::dsl -{ - class _member-dsl_ // note: not a _rule_ itself - { - public: - constexpr _rule_ auto operator=(_rule_ auto rule); - constexpr _branch-rule_ auto operator=(_branch-rule_ auto rule); - }; - - template - constexpr _member-dsl_ member; -} - -#define LEXY_MEM(Name) lexy::dsl::member<...> ----- - -[.lead] -`member` is a rule that can be used to specify a member of an aggregate that will receive the resulting value a rule. - -A rule is formed by writing `member = rule`. - -Requires:: - * `MemberPtr` is a member point of some aggregate type `Aggregate`. - * `rule` produces exactly one value. -(Branch) Parsing:: - Parses `rule`. -Errors:: - All errors raised by `rule`. - The rule then fails if `rule` has failed. -Values:: - Two values. - The first is a value of type `lexy::member{}`. - Here, `Fn` is a default constructible function object that takes two arguments: - a reference to an `Aggregate` object and the value of `rule`. - When invoked, it will set the member described `MemberPtr` of the `Aggregate` object to the value of `rule`. - The second is the value `rule` has produced. - -The macro version `LEXY_MEM(member) = rule` behaves identical, except that `member` is not a member pointer but the name of a member. -The resulting `Fn` can take an arbitrary aggregate type and will assign the member with that name. - -It is designed to be used with {{% docref "lexy::as_aggregate" %}} as the callback. - -{{% godbolt-example member "Parse a point" %}} - -TIP: The `member` rule works good in combination with {{% docref "lexy::dsl::combination" %}} where rules are parsed in an arbitrary order. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/newline.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/newline.adoc deleted file mode 100644 index fb42eff5f4..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/newline.adoc +++ /dev/null @@ -1,68 +0,0 @@ ---- -header: "lexy/dsl/newline.hpp" -entities: - "lexy::dsl::newline": newline - "lexy::dsl::eol": eol ---- -:toc: left - -[.lead] -The `newline` and `eol` token rules. - -[#newline] -== Token rule `lexy::dsl::newline` - -{{% interface %}} ----- -namespace lexy -{ - struct expected_newline {}; -} - -namespace lexy::dsl -{ - constexpr _token-rule_ auto newline; -} ----- - -[.lead] -`newline` is a {{% token-rule %}} that matches a newline. - -It is entirely equivalent to {{% docref "lexy::dsl::literal_set" %}}` containing of the literals `"\r\n"` and `"\n"`, -where the error has been overridden to `lexy::expected_newline`. - -{{% playground-example newline "Match a newline at the end" %}} - -CAUTION: As a token rule, it matches {{% docref whitespace %}} immediately following the newline. -As such, the rule is best used in contexts where automatic whitespace skipping is disabled, -or where it doesn't include newline characters. - -CAUTION: Differentiate between {{% docref "lexy::dsl::ascii::newline" %}}, which matches `\r` or `\n`, and `lexy::dsl::newline`, which matches `\r\n` or `\n`! - -[#eol] -== Branch rule `lexy::dsl::eol` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _branch-rule_ auto eol; -} ----- - -[.lead] -`eol` is a {{% branch-rule %}} that matches the end of a line. - -(Branch) Parsing:: - If at EOF, succeeds without consuming anything. - Otherwise, forwards to {{% docref "lexy::dsl::newline" %}} -Errors:: - `lexy::expected_newline`: if it could match neither EOF nor a newline; at the starting reader position. -Parse tree:: - If at EOF, single token node with the {{% docref "lexy::predefined_token_kind" %}} `lexy::eof_token_kind` whose range is empty. - Otherwise, the token node created by {{% docref "lexy::dsl::newline" %}}. - -{{% playground-example eol "Match a newline or EOF at the end" %}} - -CAUTION: The same caveat about {{% docref whitespace %}} as for `newline` applies here as well. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/operator.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/operator.adoc deleted file mode 100644 index bb6fadbf8b..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/operator.adoc +++ /dev/null @@ -1,89 +0,0 @@ ---- -header: "lexy/dsl/operator.hpp" -entities: - "lexy::dsl::op": op - "lexy::dsl::operator/ (operator)": choice ---- -:toc: left - -[.lead] -Define operators of an {{% docref "expression" %}}. - -[#op] -== Branch rule `lexy::dsl::op` - -{{% interface %}} ----- -namespace lexy -{ - template - using op = _see-below_; -} - -namespace lexy::dsl -{ - constexpr _operator-rule_ auto op(_branch-rule_ auto r); <1> - - template - constexpr _operator-rule_ auto op(_branch-rule_ auto r); <2> - - template - constexpr _operator-rule_ auto op(_branch-rule_ auto r); <3> -} ----- - -[.lead] -`op` is a {{% branch-rule %}} that parses an operator. - -Requires:: - `r` is either a {{% literal-rule %}} or a {{% docref "branch" %}} whose condition is a {{% literal-rule %}}. -(Branch) parsing:: - Parses `r`. -Errors:: - All errors raised by (branch) parsing `r`. -Values:: - A single value describing the operator that was just parsed (the tag), followed by all values produced by `r`. - The type of the tag value is given by `lexy::op`, it is: - * For overload 1, a unique type computed from the rule `r`. - * For overload 2 and `Tag != void`, an object of the specified `Tag` type. - If `Tag` is constructible from the iterator type of the input, it constructs it giving it the start position of the operator. - Otherwise, it uses the default constructor. - * For overload 2 and `Tag == void`, no tag value is produced. - * For overload 3, an object of implementation-defined type that is implicitly convertible to the type of `Tag`, returning that value. - -{{% godbolt-example op-basic "By default, operators produce a unique tag type" %}} - -{{% godbolt-example op-custom "Operator with custom type to get position information" %}} - -TIP: Use a branch rule as operators to parse a ternary operator, as seen in {{< github-example calculator >}}. - -[#choice] -== Branch rule `lexy::dsl::operator/ (operator)` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _operator-rule_ auto operator/(_operator-rule_ auto lhs, - _operator-rule_ auto rhs); -} ----- - -[.lead] -`operator/` is a {{% branch-rule %}} that parses one of multiple operators. - -Branch parsing:: - Let `lset` be the {{% docref "lexy::dsl::literal_set" %}} created by collecting all initial {{% literal-rule %}}s of `lhs` and `rhs`, - possibly recursively if they themselves are created using `operator/`. - Tries to match and consume `lset`, backtracks if that fails. - Otherwise, it has selected the initial operator of a {{% docref "lexy::dsl::op" %}} rule, parses the remainder of the rule without backtracking. -Parsing:: - Same as branch parsing, but fails instead of backtracking. -Errors:: - * `lexy::expected_literal_set`: if no initial literal rule matched, at the initial position. - * All errors raised by parsing the selected operator. -Values:: - All values produced by the selected operator, including the tag. - -{{% godbolt-example op-choice "Match plus or minus" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/option.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/option.adoc deleted file mode 100644 index 2d0bba74e1..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/option.adoc +++ /dev/null @@ -1,95 +0,0 @@ ---- -header: "lexy/dsl/option.hpp" -entities: - "lexy::nullopt": nullopt - "lexy::dsl::nullopt": nullopt - "lexy::dsl::opt": opt ---- -:toc: left - -[.lead] -The `nullopt` and `opt()` rules. - -[#nullopt] -== Rule `lexy::dsl::nullopt` - -{{% interface %}} ----- -namespace lexy -{ - template - concept _optional-like_ - = std::is_default_constructible_v - && requires(T t) { - *t; - !t; - }; - - struct nullopt - { - template - requires _optional-like_ - constexpr operator T() const; - }; -} - -namespace lexy::dsl -{ - constexpr _rule_ auto nullopt; -} ----- - -[.lead] -`nullopt` is a rule that produces a value of type `lexy::nullopt` without consuming anything. - -Parsing:: - Always succeeds without consuming anything. -Errors:: - None. -Values:: - A single object of the tag type `lexy::nullopt`. - This type is implicitly convertible to any type that is `_optional-like_` by constructing a default constructible instance of it. - -{{% godbolt-example try "Recover from missing version numbers" %}} - -NOTE: See {{< github-example tutorial >}} for a more complete version number parser. - -{{% godbolt-example lookahead "Create an empty optional if we're not having the key" %}} - -CAUTION: If `lexy::nullopt` is combined with a type that has a constructor accepting `lexy::nullopt` (e.g. because it is templated), -it will use that constructor instead of the default constructor. -For example, `std::optional>(lexy::nullopt{})` will contain a default-constructed `std::optional`, -and is not empty itself. -This is not the same behavior as `std::optional>(std::nullopt{})`, which will create a `std::optional>` containing nothing. - -[#opt] -== Rule `lexy::dsl::opt` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto opt(_branch-rule_ auto branch); -} ----- - -[.lead] -`opt` is a rule that tries to parse a {{% branch-rule %}}, producing a `lexy::nullopt` otherwise. - -Parsing:: - Tries to parse `branch`. - If that backtracks, succeeds without consuming anything. -Errors:: - All errors raised by `branch` during branch parsing. - The rule then fails if `branch` has failed. -Values:: - If `branch` was parsed, all values produced by it. - Otherwise, a single object of the tag type `lexy::nullopt` (see above). - -{{% godbolt-example opt "Only parse a fraction if preceded by a dot " %}} - -NOTE: `opt(branch)` is functionally equivalent to the {{% docref choice %}} `branch | lexy::dsl::else_ >> lexy::dsl::nullopt`, -and it parses the same as {{% docref "lexy::dsl::if_" %}}. - -TIP: Use {{% docref "lexy::bind" %}} with {{% docref "lexy::nth_value" %}} and `or` to pass a different value than `lexy::nullopt` to the callback. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/peek.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/peek.adoc deleted file mode 100644 index ce59e7756a..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/peek.adoc +++ /dev/null @@ -1,101 +0,0 @@ ---- -header: "lexy/dsl/peek.hpp" -entities: - "lexy::dsl::peek": peek - "lexy::dsl::peek_not": peek_not ---- -:toc: left - -[.lead] -The `peek` and `peek_not` branch rules. - -[#peek] -== Branch rule `lexy::dsl::peek` - -{{% interface %}} ----- -namespace lexy -{ - struct peek_failure {}; -} - -namespace lexy::dsl -{ - struct _peek_ // models _branch-rule_ - { - template - static constexpr _peek_ error; - }; - - constexpr _peek_ peek(_rule_ auto rule); -} ----- - -[.lead] -`peek` is a {{% branch-rule %}} that checks if `rule` matches without consuming anything. - -Parsing:: - Tries to match `rule` in a new context. - If that succeeds, the branch is taken without consuming anything. - Otherwise, it raises an error. -Branch parsing:: - Same as parsing, but backtracks instead of raising an error. -Errors:: - A generic error with the specified `Tag` or `lexy::peek_failure` at the position where it started to match rule. - It then recovers without consuming additional input. -Values:: - None. - -{{% playground-example peek "Parse an optional number" %}} - -NOTE: Automatic {{% docref whitespace %}} skipping is disabled while parsing `rule`. - -WARNING: `rule` does not have access to any context variables created by the context-sensitive parsing facilities and it can't use recursion. - -CAUTION: This rule requires backtracking, which can slow down parsing. - -[#peek_not] -== Branch rule `lexy::dsl::peek_not` - -{{% interface %}} ----- -namespace lexy -{ - struct unexpected {}; -} - -namespace lexy::dsl -{ - struct _peek_not_ // models _branch-rule_ - { - template - static constexpr _peek_not_ error; - }; - - constexpr _peek_not_ peek_not(_rule_ auto rule); -} ----- - -[.lead] -`peek_not` is a {{% branch-rule %}} that checks if `rule` does not match without consuming anything. - -Parsing:: - Tries to match `rule` in a new context. - If that does not succeed, the branch is taken without consuming anything. - Otherwise, it raises an error. -Branch parsing:: - Same as parsing, but backtracks instead of raising an error. -Errors:: - A generic error with the specified `Tag` or `lexy::unexpected` covering everything `rule` would have consumed. - It then recovers without having consumed any input. -Values:: - None. - -{{% playground-example peek_not "Explicitly prohibit trailing spaces" %}} - -NOTE: Automatic {{% docref whitespace %}} skipping is disabled while parsing `rule`. - -WARNING: `rule` does not have access to any context variables created by the context-sensitive parsing facilities and it can't use recursion. - -CAUTION: This rule requires backtracking, which can slow down parsing. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/position.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/position.adoc deleted file mode 100644 index 0f828789a3..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/position.adoc +++ /dev/null @@ -1,36 +0,0 @@ ---- -header: "lexy/dsl/position.hpp" -entities: - "lexy::dsl::position": position ---- -:toc: left - -[#position] -== Rule `lexy::dsl::position` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto position; -} ----- - -[.lead] -`position` is a rule that produces the current input position without consuming anything. - -Parsing:: - Always succeeds without consuming anything. -Errors:: - None. -Values:: - An iterator to the current position of the reader. -Parse tree:: - A single token node, whose range is begins and ends at its position, with the {{% docref "lexy::predefined_token_kind" %}} `lexy::position_token_node`. - -{{% playground-example position "Determine the position of a function declaration" %}} - -NOTE: As a rule, `position` does not do {{% docref whitespace %}} skipping. -If used immediately before a {{% token-rule %}} it will produce the position that is the beginning of this token, -because whitespace skipping is done _after_ token rules. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/production.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/production.adoc deleted file mode 100644 index 5c3633747b..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/production.adoc +++ /dev/null @@ -1,155 +0,0 @@ ---- -header: "lexy/dsl/production.hpp" -entities: - "lexy::dsl::inline_": inline_ - "lexy::dsl::p": p - "lexy::dsl::recurse": recurse - "lexy::dsl::recurse_branch": recurse ---- -:toc: left - -[.lead] -The `inline_`, `p`, and `recurse` rules. - -[#inline_] -== Rule `lexy::dsl::inline_` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template <_production_ P> - constexpr _rule_ auto inline_; - - template <_production_ P> - requires _token-rule_> - constexpr _token-rule_ auto inline_; - - template <_production_ P> - requires _branch-rule_> - constexpr _branch-rule_ auto inline_; -} ----- - -[.lead] -`inline_` is a rule that parses the rule of production `P` as part of the current production. - -Requires:: - `P` is a complete type, i.e. `p` cannot be used for recursion. -Matching:: - Matches `P::rule`. -(Branch) Parsing:: - Parses `P::rule`. -Errors:: - All errors raised by `P::rule`. - The rule then fails if `P::rule` has failed. -Values:: - All values produced by `P::rule`. - -{{% playground-example inline "Parse a child production inline" %}} - -TIP: Use `inline_` when you need to parse a production as part of the whitespace rule. - -[#p] -== Rule `lexy::dsl::p` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template <_production_ P> - constexpr _rule_ auto p; - - template <_production_ P> - requires _branch-rule_> && !_defines-whitespace_

` - constexpr _branch-rule_ auto p; -} ----- - -[.lead] -`p` is a rule that parses the production `P`. - -Requires:: - `P` is a complete type, i.e. `p` cannot be used for recursion. -(Branch) Parsing:: - Parses `P::rule` in a new context for `P`, potentially after skipping initial {{% docref "whitespace" %}} if `P::whitespace` has been defined. -Errors:: - All errors raised by parsing `P::rule`, but forwarded to the new context for `P`. - The rule fails if `P::rule` has failed. -Values:: - All values produced by `P::rule` are forwarded to the new context, e.g. to `P::value`. - The final value of the context is produced as the single value for `p`. -Parse tree:: - * If `P` inherits from {{% docref "lexy::transparent_production" %}}, the nodes generated by `P::rule` are added to the parse tree as if they were added by `p` itself. - * Otherwise, it creates a single production node for `P`. - Its children are all the nodes generated by `P::rule`. - -{{% playground-example default "Parse a child production" %}} - -{{% playground-example choice_production "Productions with branches" %}} - -NOTE: The `p` rule cannot handle direct or indirect recursion, as `P` must be a complete type. - -CAUTION: While parsing `P::rule`, the {{% docref "whitespace" "current whitespace rule" %}} can be different. -If whitespace parsing has been disabled using {{% docref "lexy::dsl::no_whitespace" %}}, -it is temporarily re-enabled while parsing `P::rule`. -If whitespace parsing has been disabled because the current production inherits from {{% docref "lexy::token_production" %}}, -it is still disabled, unless the current production explicitly defines a new whitespace rule. - -[#recurse] -== Rule `lexy::dsl::recurse` - -{{% interface %}} ----- -namespace lexy -{ - struct max_recursion_depth_exceeded {}; -} - -namespace lexy::dsl -{ - struct _recurse_ // models _rule_ or _branch-rule_ - { - template - static constexpr _recurse_ max_depth_error; - }; - - template <_production_ P> - constexpr _recurse_ auto recurse; // _rule_ - template <_production_ P> - constexpr _recurse_ auto recurse_branch; // _branch-rule_ -} ----- - -[.lead] -`recurse` is a rule that parses the production `P` but supports recursion. - -It behaves similar to the `p` rule, but `P` does not need to a be a complete type, which allows recursion. -For the same reason, `recurse

` is never a branch rule: it can't know whether `P` is a branch. -Use `recurse_branch

` if you know that `P` is a branch; it will cause a delayed `static_assert` if it isn't. - -Parsing:: - Checks whether the current depth of recursive production call exceeds the maximum parse depth, - which is determined by {{% docref "lexy::max_recursion_depth" %}}. - Fails, if that is the case. - Otherwise, parses `p

`, i.e. the production `P`. -Branch parsing:: - Branch parses `p

`, i.e. the production `P`. - The recursive depth check is done after the branch condition has matched. - It will not backtrack if the condition matches but the depth is exceeded. -Errors:: - * A generic error with the specified `Tag` or `lexy::max_recursion_depth_exceeded` if the recursive depth is exceeded, - at the position where it would have started to match the production. - It then fails without recovering. - * All errors raised by parsing `p

`. - -{{% playground-example recurse "Parse a parenthesized expression" %}} - -{{% playground-example recurse_limit "Parse a parenthesized expression with a recursion limit" %}} - -WARNING: Left recursion will create a max recursion error. -Use {{% docref "lexy::dsl::loop" %}} or {{% docref "lexy::dsl::list"%}} instead. - -NOTE: The recursion depth only counts productions parsed by `recurse`; intermediate productions parsed using `p` are ignored. -In particular, the nesting level of `p` rules, which is statically determined by the grammar and not by the input, is allowed to exceed the maximum recursion depth. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/punctuator.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/punctuator.adoc deleted file mode 100644 index 7722a110a5..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/punctuator.adoc +++ /dev/null @@ -1,71 +0,0 @@ ---- -header: "lexy/dsl/punctuator.hpp" -entities: - punctuators: doc - "lexy::dsl::period": doc - "lexy::dsl::comma": doc - "lexy::dsl::colon": doc - "lexy::dsl::double_colon": doc - "lexy::dsl::semicolon": doc - "lexy::dsl::exclamation_mark": doc - "lexy::dsl::question_mark": doc - "lexy::dsl::hyphen": doc - "lexy::dsl::slash": doc - "lexy::dsl::backslash": doc - "lexy::dsl::apostrophe": doc - "lexy::dsl::ampersand": doc - "lexy::dsl::caret": doc - "lexy::dsl::asterisk": doc - "lexy::dsl::tilde": doc - "lexy::dsl::vbar": doc - "lexy::dsl::hash_sign": doc - "lexy::dsl::dollar_sign": doc - "lexy::dsl::at_sign": doc - "lexy::dsl::percent_sign": doc - "lexy::dsl::equal_sign": doc ---- -:toc: left - -[.lead] -Predefined punctuators. - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _token-rule_ auto period = lit<".">; - constexpr _token-rule_ auto comma = lit<",">; - constexpr _token-rule_ auto colon = lit<":">; - constexpr _token-rule_ auto double_colon = lit<"::">; - constexpr _token-rule_ auto semicolon = lit<";">; - - - constexpr _token-rule_ auto exclamation_mark = lit<"!">; - constexpr _token-rule_ auto question_mark = lit<"?">; - - constexpr _token-rule_ auto hyphen = lit<"-">; - constexpr _token-rule_ auto slash = lit<"/">; - constexpr _token-rule_ auto backslash = lit<"\\">; // note: single character - constexpr _token-rule_ auto apostrophe = lit<"'">; - constexpr _token-rule_ auto ampersand = lit<"&">; - constexpr _token-rule_ auto caret = lit<"^">; - constexpr _token-rule_ auto asterisk = lit<"*">; - constexpr _token-rule_ auto tilde = lit<"~">; - constexpr _token-rule_ auto vbar = lit<"|">; - - constexpr _token-rule_ auto hash_sign = lit<"#">; - constexpr _token-rule_ auto dollar_sign = lit<"$">; - constexpr _token-rule_ auto at_sign = lit<"@">; - constexpr _token-rule_ auto percent_sign = lit<"%">; - constexpr _token-rule_ auto equal_sign = lit<"=">; -} ----- - -[.lead] -The various punctuator {{% literal-rule %}}s are convenience aliases for {{% docref "lexy::dsl::lit" %}}. - -**** -A _punctuator_ is a token that is used as a delimiter in the grammar without having any actual meaning in the program, like an operator (e.g. `+`) would. -In lexy, they are limited to ASCII punctuation characters that are not only used as operators and aren't quotation or brackets. -**** - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/recover.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/recover.adoc deleted file mode 100644 index 080d98eb52..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/recover.adoc +++ /dev/null @@ -1,154 +0,0 @@ ---- -header: "lexy/dsl/recover.hpp" -entities: - "error recovery": doc - "lexy::dsl::try_": try_ - "lexy::dsl::recover": recover - "lexy::dsl::find": find ---- -:toc: left - -[.lead] -The `try_`, `recover` and `find` rules for error recovery. - -Unless otherwise specified, lexy will cancel parsing on the first error. -This cancellation propagates outward until either the entire parsing fails, or a `try_` rule is reached. -This is similar to how an exception will perform stack unwinding until the entire program is terminated or a `try` block reached. -`try_` allows recovering from the error so parsing can continue after the first error. - -[#try_] -== Rule `lexy::dsl::try_` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto try_(_rule_ auto rule); - constexpr _rule_ auto try_(_rule_ auto rule, _rule_ auto recovery_rule); - - constexpr _branch-rule_ auto try_(_branch-rule_ auto rule); - constexpr _branch-rule_ auto try_(_branch-rule_ auto rule, _rule_ auto recovery_rule); -} ----- - -[.lead] -`try` is a rule that catches any errors raised during parsing of `rule` and recovers from them, so parsing can continue. - -Parsing:: - Parses `rule`. -Branch parsing:: - Tries to parse `rule` and succeeds if that succeeds. - If `rule` backtracks, this is not considered a situation where recovery needs to happen, and it also backtracks. - Only recovers if `rule` fails, failure of recovery (see below) do not lead to a backtrack; - at this point the branch has been committed. -Errors:: - All errors raised by `rule`. - If `rule` has not already recovered, recovers for it: - * The single argument overload does it by consuming nothing, - parsing then simply continues as if nothing happened. - * The two argument overload does it by parsing `recovery_rule`. - If that succeeds, recovery is finished. - Otherwise, raises all errors from it unchanged and cancels. -Values:: - If `rule` succeeded, all values produced by `rule`. - Otherwise, all values produced by `recovery_rule`. - In particular, the values of `rule` are _not_ produced in that case. - -The single argument overload useful if `rule` matches something that is not technically necessary for parsing, but just there for redundancy. -The two argument overload accepts a `recovery_rule` whose purpose is to bring the parser into a known state. -This is useful to skip bad input until a well-known synchronization point is reached, like a statement separator. -If `recovery_rule` fails, it requires a `try_` rule at a higher level. - -The behavior of `try_` is analogous to a C++ `try` block. -If an error is raised during `rule`, it is caught by the `recovery_rule`, which corresponds to a `catch (...)` block. -If `recovery_rule` succeeds, this corresponds to a `catch` block that is executed without error. -If `recovery_rule` raises an error, this corresponds to a `catch` block whose execution raises another exception. -`recovery_rule` can also fail without raising an error; this corresponds to a `throw;` statement that re-throws the exception. - -{{% godbolt-example try "Recover from missing version numbers" %}} - -NOTE: See {{< github-example tutorial >}} for a more complete version number parser. - -[#find] -== Rule `lexy::dsl::find` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct _find-dsl_ // models _rule_ - { - _rule_ auto limit(auto ... limits); - }; - - constexpr _find-dsl_ find(auto ... literals); -} ----- - -[.lead] -`find` is a recovery rule that skips input until a synchronization {{% token-rule %}} is reached. - -Requires:: - `literals` and `limits` are {{% literal-rule %}}s or {{% docref "lexy::dsl::literal_set" %}}. -Parsing:: - Tries to match {{% docref "lexy::dsl::lookahead" %}}`(literal_set, limit_set)`, - where `literals` and `limits` have been collected into a single literal set. - If that was successful, consumes everything until the beginning of the found literal and succeeds. - Otherwise, fails after consuming everything until the beginning of the found limit (or EOF). -Errors:: - None. It can fail, but does so without raising errors. -Values:: - None. -Parse tree:: - A single token node whose range covers everything consumed before the token that was found. - Its {{% docref "lexy::predefined_token_kind" %}} is `lexy::error_token_kind`. - -If recovery is successful, the reader has been advanced to the position just before the first of the `tokens`. -Parsing can then continue from this known state, e.g. from a statement separator. -If recovery fails, no additional error is raised but parsing is canceled, to try recovery at a higher level. - -{{% playground-example find "Parse a list of declarations with error recovery using `find()`" %}} - -[#recover] -== Rule `lexy::dsl::recover` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct _recover-dsl_ // models _rule_ - { - _rule_ auto limit(auto ... limits); - }; - - constexpr _recover-dsl_ find(_branch-rule_ auto ... branches); -} ----- - -[.lead] -`recover` is a recovery rule that skip input until a follow-up {{% branch-rule %}} can be parsed. - -Requires:: - `limits` are {{% literal-rule %}}s or {{% docref "lexy::dsl::literal_set" %}}. -Parsing:: - Tries to parse any of `branches` anywhere in the remaining input; - consumes everything before the selected branch and then the branch itself. - Fails if EOF is reached first or one of `limits` matches, - if they were specified. -Errors:: - * All errors raised by parsing the selected branch. - The rule fails if the selected branch fails. - * A failed recovery does not raise an error. -Values:: - All values produced by the selected branch. -Parse tree:: - A single token node whose range covers everything consumed before the token. - Its {{% docref "lexy::predefined_token_kind" %}} is `lexy::error_token_kind`. - -Unlike `find`, `recover` directly continues with one rule. -If recovery has been successful, it has parsed the selected rule. -Parsing can then continue as it would normally do a after that rule. -If recovery fails, no additional error is raised but parsing is canceled, to try recovery at a higher level. - -{{% playground-example recover "Parse a list of declarations with error recovery using `recover()`" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/repeat.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/repeat.adoc deleted file mode 100644 index 7ba212f835..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/repeat.adoc +++ /dev/null @@ -1,69 +0,0 @@ ---- -header: "lexy/dsl/repeat.hpp" -entities: - "lexy::dsl::repeat": repeat ---- - -[#repeat] -== Rule DSL `lexy::dsl::repeat` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct _repeat-dsl_ // note: not a rule itself - { - constexpr _rule_ auto operator()(_rule_ auto item); - constexpr _rule_ auto operator()(_rule_ auto item, _separator_ auto sep); - - constexpr _rule_ auto capture(_rule_ auto item); - constexpr _rule_ auto capture(_rule_ auto item, _separator_ auto sep); - - constexpr _rule_ auto list(_rule_ auto item); - constexpr _rule_ auto list(_rule_ auto item, _separator_ auto sep); - }; - - constexpr _repeat-dsl_ repeat(_rule_ auto count); -} ----- - -[.lead] -`repeat` is not a rule, but a DSL for parsing something `N` times in sequence with optional separator in between, -where `N` is determined as the result of parsing a `count` rule. - -The actual rule is obtained by calling `operator()`, `capture()`, or `list()` on the result of `repeat()`. -All three have the same parsing behavior and differ only in the values they produce. -The resulting rule is a branch rule, if `count` is a branch rule. - -Requires:: - * `count` must produce a value convertible to `std::size_t` when parsed with the parse action {{% docref "lexy::parse" %}}. - * If `operator()` or `capture()` is used, `item` and `sep` must not produce any values. -Parsing:: - Parses `count` as if the parse action {{% docref "lexy::parse" %}} was used; the result is a `std::size_t` `n`. - Then parses `item` `n` times in sequence. - If `sep` has been specified, parses it in between. - After the last rule, handles a trailing separator as necessary. -Branch parsing:: - Same as above, but branch parses `count`. - If `count` backtracks, backtracks as well. - Otherwise, does not backtrack anymore. -Errors:: - * All errors raised by parsing `count`. The rule then fails. - * All errors raised by parsing `item` or `sep` in any iteration. - The rule then fails. - * `lexy::unexpected_trailing_separator`: if a trailing separator can be matched after the last item and that is not allowed; - at the position of the separator. - It then recovers by simply consuming the separator. -Values:: - * If `operator()` is used, does not produce any values. - * If `capture()` is used, produces a single value: a {{% docref "lexy::lexeme" %}} spanning everything consumed by parsing `rule` and `sep` `n` times. - This is like the behavior of {{% docref "lexy::dsl::capture" %}} except that `count` is not captured. - * If `list()` is used, creates a sink of the current context. - All values produced by `item` and `sep` are forwarded to it; there are separate calls for every iteration and for `item` and `sep`. - The value of the finished sink is produced as the only value. - This is like the behavior of {{% docref "lexy::dsl::list" %}}. - -{{% playground-example repeat "Parse an integer and then that many 'a's" %}} - -NOTE: Use {{% docref "lexy::dsl::times" %}} if the number of repetitions is hard-coded into the grammar. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/return.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/return.adoc deleted file mode 100644 index fe184121d9..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/return.adoc +++ /dev/null @@ -1,35 +0,0 @@ ---- -header: "lexy/dsl/return.hpp" -entities: - "lexy::dsl::return_": return_ ---- - -[#return_] -== Rule `lexy::dsl::return_` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto return_; -} ----- - -[.lead] -`return_` is a rule that terminates parsing of the current production early. - -Requires:: - It is not used inside loops (e.g. {{% docref "lexy::dsl::loop" %}}, {{% docref "lexy::dsl::while_" %}}, {{% docref "lexy::dsl::list" %}}). -Parsing:: - Always succeeds without consuming any input. - Parsing of the current production is then finished. -Errors:: - None. -Values:: - None; but all existing values are immediately parsed to the context, - e.g. the callback is immediately invoked if `lexy::parse()` is used. - -{{% playground-example return "Parse a (simplified) XML element, which can be empty" %}} - -NOTE: See {{< github-example xml >}} for a more complete XML parser. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/scan.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/scan.adoc deleted file mode 100644 index 47b4fc986f..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/scan.adoc +++ /dev/null @@ -1,101 +0,0 @@ ---- -header: "lexy/dsl/scan.hpp" -entities: - "lexy::rule_scanner": scan - "lexy::dsl::scan": scan - "lexy::scan_production": scan_production ---- -:toc: left - -[.lead] -Manually parse input. - -[#scan] -== Rule `lexy::dsl::scan` - -{{% interface %}} ----- -namespace lexy -{ - template - class rule_scanner - : public _scanner-common_ - { - public: - using production = _current-production_; - - // Current recursion depth. - constexpr std::size_t recursion_depth() const noexcept; - - // Position where `dsl::scan` was reached. - constexpr auto begin() const noexcept -> typename Reader::iterator; - }; -} - -namespace lexy::dsl -{ - constexpr _rule_ auto scan; -} ----- - -[.lead] -Parses input using a user-defined function. - -Requires:: - The current production `P` has a `static` member function that returns a {{% docref "lexy::scan_result" %}}, - It must take at least one argument, which is a reference to a `lexy::rule_scanner`. - It can optionally take a second argument, which is a reference to the parse state passed to the top-level action. -Parsing:: - Invokes `P::scan()`, passing it an object of type `lexy::rule_scanner` starting at the current reader position, and optionally the parse state, followed by all values already produced by previous rules. - Then parses and consumes everything parsed and consumed by `P::scan()`. - Succeeds, if `P::scan()` returns a {{% docref "lexy::scan_result" %}} that contains a value. - Fails otherwise. -Errors:: - All errors raised by `P::scan()`, either directly by calling `.error()` or indirectly by parsing a rule that fails. - Recovers if `P::scan()` recovers and is able to return a value. -Values:: - If the `value_type` of the returned {{% docref "lexy::scan_result" %}} is non-void, returns that value. - Otherwise, produces no value. - Values produced by previous rules are discarded. -Parse tree:: - Creates all nodes created from the rules parsed by `P::scan()` as if those rules were parsed directly. - -`lexy::rule_scanner` implements {{% docref "lexy::scanner-common" %}}. -While parsing a rule, everything is forwarded to the top-level parse action, and it has access to the same context: -The use of `dsl::scan` is a complete implementation detail of a production; it cannot be observed by the parse action in any way. -Regardless of the top-level parse action, the overloads of `.parse()` and `.branch()` taking a {{% docref "lexy::scan_result" %}} ensure that values are produced. - -{{% playground-example "scan" "Parse a Rust-style raw string literal" %}} - -TIP: Use {{% docref "lexy::scan_production" %}} to remove boilerplate for a production whose rule is entirely `dsl::scan`. - -TIP: Use `condition >> dsl::scan` to turn a scanner into a branch. -The values produced by condition are available in the scan function to consume. - -NOTE: Use {{% docref "lexy::scan" %}} if you want to manually parse the root production. - -CAUTION: If `P::scan()` only provides the overload that takes a specific parse state, -this parse state must be passed to all actions that are used with the grammar. - -[#scan_production] -== Class `lexy::scan_production` - -{{% interface %}} ----- -namespace lexy -{ - template - struct scan_production - { - // The return type of the scan() function. - using scan_result = lexy::scan_result; - - static constexpr auto rule = dsl::scan; - static constexpr auto value = lexy::forward; - }; -} ----- - -[.lead] -Convenience class for productions that are parsed entirely manually producing a value of type `T`. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/separator.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/separator.adoc deleted file mode 100644 index 34a7f712d8..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/separator.adoc +++ /dev/null @@ -1,93 +0,0 @@ ---- -header: "lexy/dsl/separator.hpp" -entities: - "separator": doc - "lexy::dsl::sep": sep - "lexy::dsl::trailing_sep": trailing_sep ---- -:toc: left - -[.lead] -The `sep` and `trailing_sep` separators. - -They are used with {{% docref "lexy::dsl::times" %}} and {{% docref "lexy::dsl::list" %}} (and variants thereof) and are not actually rules themselves. - -[#sep] -== Separator `lexy::dsl::sep` - -{{% interface %}} ----- -namespace lexy -{ - struct unexpected_trailing_separator {}; -} - -namespace lexy::dsl -{ - struct _sep-dsl_ // models _separator_ - { - template - static constexpr _separator_ auto trailing_error; - }; - - constexpr _sep-dsl_ auto sep(_branch-rule_ rule); -} ----- - -[.lead] -`sep` indicates a separator between two items. - -If specified as a separator, it will parse `rule` between two items, -but it is an error if `rule` is after the last item. -In that case, a generic error with tag `lexy::unexpected_trailing_separator` is raised at the position where the separator begins. -This tag can be overridden by specifying a different tag via `.trailing_error`. - -{{% godbolt-example list_sep "Parse a list of letters separated by commas" %}} - -NOTE: It is not always possible to check for the existence of a trailing separator. -If it is not possible, parsing will continue as normal and (presumably) the next rule will fail due to the unexpected separator. - -[#trailing_sep] -== Separator `lexy::dsl::trailing_sep` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _separator_ auto trailing_sep(_branch-rule_ rule); -} ----- - -[.lead] -`trailing_sep` indicates a separator between two items and optionally after the last item. - -If specified as a separator, it will parse `rule` between two items, -or after the last item. -If no separator is present after the last item, it is not an error. - -{{% godbolt-example times_tsep "Parse three integers separated by comma" %}} - -TIP: To create a separator that _must_ be present after every the last item (and every item before that), -simply add the separator to the item itself. - -[#ignore_trailing_sep] -== Separator `lexy::dsl::ignore_trailing_sep` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _separator_ auto ignore_trailing_sep(_branch-rule_ rule); -} ----- - -[.lead] -`ignore_trailing_sep` indicates a separator between two items and it can be ignored after the last item. - -It can only be used with {{% docref "lexy::dsl::times" %}}. -If specified as a separator, it will parse `rule` between two items, but makes no attempt to parse it after the last item. - -{{% godbolt-example times_isep "Parse three integers separated by comma, twice" %}} - -TIP: Use it if the separator can also legally occur after the list. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/sequence.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/sequence.adoc deleted file mode 100644 index 92c84bed13..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/sequence.adoc +++ /dev/null @@ -1,31 +0,0 @@ ---- -header: "lexy/dsl/sequence.hpp" -entities: - "lexy::dsl::operator+": sequence - "sequence": sequence ---- - -[#sequence] -== Rule `lexy::dsl::operator+` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto operator+(_rule_ auto lhs, _rule_ auto rhs); -} ----- - -[.lead] -`operator+` (sequence) is a rule that parses multiple rules one after the other. - -Parsing:: - Parses `lhs`, then parses `rhs`. -Errors:: - All errors raised by `lhs` and/or `rhs`. - The rule fails if either of them has failed. -Values:: - All values produced from `rhs` followed by all values produced by `rhs`. - -{{% playground-example default "Sequence rule is used practically all the time" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/sign.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/sign.adoc deleted file mode 100644 index 23f8a0c176..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/sign.adoc +++ /dev/null @@ -1,119 +0,0 @@ ---- -header: "lexy/dsl/sign.hpp" -entities: - "lexy::dsl::plus_sign": plus_sign - "lexy::dsl::minus_sign": minus_sign - "lexy::dsl::sign": sign ---- -:toc: left - -[.lead] -The `plus_sign`, `minus_sign` and `sign` rules. - -== Tag types - -{{% interface %}} ----- -namespace lexy -{ - struct plus_sign - { - constexpr operator int() const - { - return +1; - } - }; - - struct minus_sign - { - constexpr operator int() const - { - return -1; - } - }; -} ----- - -[.lead] -The tag types `plus_sign` and `minus_sign` indicate a plus/minus sign. - -They are implicitly convertible to the integer `+1`/`-1`. - -TIP: The callback {{% docref "lexy::as_integer" %}} accepts an optional `plus_sign`/`minus_sign` object followed by an integer and returns the correctly signed integer. - -[#plus_sign] -== Rule `lexy::dsl::plus_sign` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto plus_sign; -} ----- - -[.lead] -`plus_sign` is a rule that parses an optional `+` sign. - -Parsing:: - Tries to match and consume {{% docref "lexy::dsl::lit_c" %}}`<'+'>`. - If that fails, succeeds without consuming anything. -Errors:: - None. -Values:: - If it matched a `+`, an object of type `lexy::plus_sign`. - Otherwise, no values. - -{{% playground-example plus_sign "A number with an optional plus sign" %}} - -[#minus_sign] -== Rule `lexy::dsl::minus_sign` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto minus_sign; -} ----- - -[.lead] -`minus_sign` is a rule that parses an optional `-` sign. - -Parsing:: - Tries to match and consume {{% docref "lexy::dsl::lit_c" %}}`<'-'>`. - If that fails, succeeds without consuming anything. -Errors:: - None. -Values:: - If it matched a `-`, an object of type `lexy::minus_sign`. - Otherwise, no values. - -{{% playground-example minus_sign "A number with an optional minus sign" %}} - -[#sign] -== Rule `lexy::dsl::sign` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto sign; -} ----- - -[.lead] -`sign` is a rule that parses an optional sign. - -Parsing:: - Tries to match and consume {{% docref "lexy::dsl::lit_c" %}}`<'+'>` or {{% docref "lexy::dsl::lit_c" %}}`<'-'>`. - If both fail, succeeds without consuming anything. -Errors:: - None. -Values:: - If it matched a `+`, an object of type `lexy::plus_sign`. - If it matched a `-`, an object of type `lexy::minus_sign`. - Otherwise, no values. - -{{% godbolt-example sign "A number with an optional plus/minus sign" %}} - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/symbol.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/symbol.adoc deleted file mode 100644 index dcfa837400..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/symbol.adoc +++ /dev/null @@ -1,296 +0,0 @@ ---- -header: "lexy/dsl/symbol.hpp" -entities: - "lexy::symbol_table": "symbol_table" - "lexy::dsl::symbol": "symbol" ---- -:toc: left - -[.lead] -The `symbol` rule. - -[#symbol_table] -== `lexy::symbol_table` - -{{% interface %}} ----- - namespace lexy -{ - template - class _symbol-table_ - { - public: - using char_type = ...; - using key_type = char_type; - using mapped_type = T; - - struct value_type - { - const char_type* symbol; - const mapped_type& value; - }; - - //=== modifiers ===// - template - consteval _symbol-table_ case_folding(CaseFoldingDSL) const; - - template - consteval _symbol-table_ map(Args&&... args) const; - - template - consteval _symbol-table_ map(Args&&... args) const; - - template - consteval _symbol-table_ map(_literal-rule_ auto lit, Args&& args) const; - - //=== access ===// - static constexpr bool empty() noexcept; - - static constexpr std::size_t size() noexcept; - - class iterator; - - constexpr iterator begin() const noexcept; - constexpr iterator end() const noexcept; - - class key_index; - - template - constexpr key_index try_parse(Reader& reader) const; - template <_input_ Input> - constexpr key_index parse(const Input& input) const; - - constexpr const T& operator[](key_index idx) const noexcept; - }; - - template - constexpr auto symbol_table = _symbol-table_(); -} ----- - -[.lead] -Defines a compile-time mapping of strings to objects of some type `T`. - -It is initially empty. - -=== Modifiers: `case_folding` - -{{% interface %}} ----- -template -consteval _symbol-table_ case_folding(CaseFoldingDSL) const; ----- - -[.lead] -Specifies case folding for the symbol table. - -`CaseFoldingDSL` is a function object that specifies a case folding like {{% docref "lexy::dsl::ascii::case_folding" %}} or {{% docref "lexy::dsl::unicode::simple_case_folding" %}}. -It will be used on the input to parse a symbol. - -CAUTION: As with the literal rules, the symbols in the symbol table must only contain lowercase characters if case folding is used. -This is because all input is case folded prior to matching which makes matching of uppercase characters impossible. - -=== Modifiers: `map` - -{{% interface %}} ----- -template -consteval _symbol-table_ map(Args&&... args) const; - -template -consteval _symbol-table_ map(Args&&... args) const; - -// `lit` must be a `dsl::lit` rule -template -consteval _symbol-table_ map(_literal-rule_ auto lit, Args&& args) const; ----- - -[.lead] -Adds a mapping to the symbol table. - -The result is a new symbol table that contains all the current mappings, -as well as a new mapping of `SymbolString`/`C` to `T(std::forward(args)...)`. - -If your compiler does not support C++20's extended NTTPs, -use `LEXY_SYMBOL("Str")` instead of `"Str"` as the template parameter for `SymbolString`. - -=== Access - -{{% interface %}} ----- -static constexpr bool empty() noexcept; <1> - -static constexpr std::size_t size() noexcept; <2> ----- -<1> Whether or not the table is empty. -<2> The number of mappings in the table. - -{{% interface %}} ----- -class iterator; - -constexpr iterator begin() const noexcept; -constexpr iterator end() const noexcept; ----- - -[.lead] -Iterates over all the mappings. - -`iterator` is a forward iterator whose value type is `value_type`. - -{{% interface %}} ----- -class key_index -{ -public: - constexpr key_index() noexcept; - constexpr explicit key_index(std::size_t idx) noexcept; - - constexpr explicit operator bool() const noexcept; - - friend constexpr bool operator==(key_index lhs, key_index rhs) noexcept; - friend constexpr bool operator!=(key_index lhs, key_index rhs) noexcept; -}; ----- - -[.lead] -An index into the table. - -It is a small wrapper over a `std::size_t`. -An index is valid if its less than `size()`, this can be checked with its `operator bool`. -Two indices can be compared for equality. - -{{% interface %}} ----- -template -constexpr key_index try_parse(Reader& reader) const; ----- - -[.lead] -Matches one of the strings in the table using a reader. - -If `reader` begins with one of the strings in the table, consumes them and returns a `key_index` to that entry. -Otherwise, returns an invalid key index and consumes nothing. - -{{% interface %}} ----- -template <_input_ Input> -constexpr key_index parse(const Input& input) const; ----- - -[.lead] -Matches one of the strings in the table against the input. - -If `input` is one of the strings, returns a `key_index` to that entry. -Otherwise, returns an invalid key index. - -If `input` only begins with one of the strings but then is followed by other characters, -it does not match. - -{{% interface %}} ----- -constexpr const T& operator[](key_index idx) const noexcept; ----- - -[.lead] -Returns the value of the entry at the `key_index`. - -Requires that `idx` is valid. - -[#symbol] -== Rule `lexy::dsl::symbol` - -{{% interface %}} ----- -namespace lexy -{ - struct unknown_symbol {}; -} - -namespace lexy::dsl -{ - struct _symbol-dsl_ // models _branch-rule_ - { - template - static constexpr _branch-rule_ auto error; - }; - - template - constexpr _symbol-dsl_ symbol; - - template - constexpr _symbol-dsl_ symbol(_token-rule_ auto token); - template - constexpr _symbol-dsl_ symbol(_identifier-dsl_ identifier); -} ----- - -[.lead] -`symbol` is a {{% branch-rule %}} that parses one symbol of `SymbolTable`. - -=== Version without argument - -{{% interface %}} ----- -template -constexpr _symbol-dsl_ symbol; ----- - -Parsing:: - Matches the longest symbol of the `SymbolTable` by consuming characters beginning at the current input. - If necessary, performs case folding on the input first. - Fails if no symbol matches. - It skips implicit whitespace afterwards. -Branch Parsing:: - As a branch, it parses exactly the same input as before. - However, instead of failing (for any reason), it backtracks without raising an error. -Errors:: - `lexy::unknown_symbol`: if it could not produce a symbol; - its range covers the entire partial input. - The rule then fails. - The tag can be overridden by specifying a different `Tag` with `.error`. -Values:: - The value of the symbol table that corresponds to the partial input. -Parse tree:: - A single token node covering the symbol. - Its {{% docref "lexy::predefined_token_kind" %}} is `lexy::identifier_token_kind`, which cannot be overridden. - -NOTE: This version behaves like the other version if passed a non-deterministic token rule that always consumes as much input as is necessary to match the symbol. - -=== Version with argument - -{{% interface %}} ----- -template -constexpr _symbol-dsl_ symbol(_token-rule_ auto token); - -template -constexpr _symbol-dsl_ symbol(_identifier-dsl_ identifier); ----- - -Requires:: - The {{% docref "lexy::dsl::identifier" %}} of the second overload has no reserved identifiers. -Parsing:: - * The first overload parses the {{% token-rule %}} `token`. - * The second overload parses `identifier.pattern()`. - In either case, it then creates a partial input that covers the (non-whitespace) code units consumed by that parsing. - If necessary, performs case folding on the partial input. - If the contents of that partial input exactly matches one of the strings in the symbol table, - the rule succeeds. -Branch Parsing:: - As a branch, it parses exactly the same input as before. - However, instead of failing (for any reason), it backtracks without raising an error. -Errors:: - * All errors raised by parsing `token` or `identifier.pattern()`. - The rule then fails, as recovery cannot produce a valid symbol. - * `lexy::unknown_symbol`: if it could not produce a symbol; - its range covers the entire partial input. - The rule then fails. - The tag can be overridden by specifying a different `Tag` with `.error`. -Values:: - The value of the symbol table that corresponds to the partial input. - -{{% godbolt-example symbol "Parse one of the predefined XML entities" %}} - -NOTE: See {{< github-example xml >}} for an XML parser. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/terminator.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/terminator.adoc deleted file mode 100644 index d9f8656e2d..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/terminator.adoc +++ /dev/null @@ -1,231 +0,0 @@ ---- -header: "lexy/dsl/terminator.hpp" -entities: - "lexy::dsl::terminator": terminator ---- - -[#terminator] -== Rule DSL `lexy::dsl::terminator` - -{{% interface %}} ----- -namespace lexy::dsl -{ - struct _terminator-dsl // note: not a rule itself - { - constexpr _branch-rule_ auto terminator() const; - - constexpr _terminator-dsl_ limit(auto ... limit); - constexpr _rule_ auto recovery_rule() const; - - //=== rules ===// - constexpr _rule_ auto operator()(_rule_ auto rule) const; - constexpr _rule_ auto try_(_rule_ auto rule) const; - - constexpr _rule_ auto opt(_rule_ auto rule) const; - - constexpr _rule_ auto list(_rule_ auto item) const; - constexpr _rule_ auto list(_rule_ auto item, _separator_ auto sep) const; - - constexpr _rule_ auto opt_list(_rule_ auto item) const; - constexpr _rule_ auto opt_list(_rule_ auto item, _separator_ auto sep) const; - }; - - constexpr _terminator-dsl_ terminator(_branch-rule_ auto branch); -} ----- - -[.lead] -`terminator` is not a rule, but a DSL for specifying rules that all parse something followed by a terminator. - -Many rules require a {{% branch-rule %}} as argument, like {{% docref "lexy::dsl::list" %}}. -However, there isn't always an easy way to check for a branch condition and sometimes the rule in question is always terminated by a given token (e.g. a semicolon). -Then you can use `terminator`: -it specifies a {{% branch-rule %}} as the terminator and provides ways of building rules where any branch condition is just "the terminator hasn't been matched yet". -As such, you don't need to provide a branch condition anymore. - -NOTE: See {{% docref "lexy::dsl::brackets" %}} if you want to parse something that has not only a terminator but some prefix as well. - -=== Branch rule `.terminator()` - -{{% interface %}} ----- -constexpr _branch-rule_ auto terminator() const; ----- - -[.lead] -`.terminator()` returns the rule that was passed to the top-level `lexy::dsl::terminator()`. - -=== `.limit()` - -{{% interface %}} ----- -constexpr _terminator-dsl_ limit(auto ... limit); ----- - -[.lead] -Provide a limit for error recovery. - -`terminator` can also do error recovery after an error by discarding input until the terminator is reached. -Similar to {{% docref "lexy::dsl::find" %}} or {{% docref "lexy::dsl::recover" %}} one can provide a limit, which is a {{% literal-rule %}} or {{% docref "lexy::dsl::literal_set" %}}. -If the limit is reached before the terminator, error recovery fails. - -{{% playground-example terminator_recovery "Recover while parsing a list of statements" %}} - -=== `.recovery_rule()` - -{{% interface %}} ----- -constexpr _rule_ auto recovery_rule() const; ----- - -[.lead] -`.recovery_rule()` returns the rule that is used for the simple error recovery. - -It is equivalent to {{% docref "lexy::dsl::recover" %}}`(terminator()).limit(tokens...)`, -where `tokens` are all the tokens passed to every `.limit()` call. -This simply discards input until it can match `terminator()`. -Recovery fails when it reaches EOF or one of the limits, if any have been specified. - -=== Rule `.operator()` - -{{% interface %}} ----- -constexpr _rule_ auto operator()(_rule_ auto rule) const -{ - return rule + terminator(); -} -constexpr _branch-rule_ auto operator()(_branch-rule_ auto rule) const -{ - return rule >> terminator(); -} ----- - -[.lead] -`.operator()` returns a rule that parses `rule`, then parses the terminator. - -It behaves entirely equivalent to `rule + terminator()`. - -{{% playground-example terminator "Parse a statement" %}} - -=== Rule `.try_()` - -{{% interface %}} ----- -constexpr _rule_ auto try_(_rule_ auto rule) const; ----- - -[.lead] -`.try_()` returns a rule that parses `rule`, then parses the terminator, but recovers on failure. - -Parsing:: - Parses `rule` and `terminator()` in {{% docref sequence %}}. -Errors:: - All errors raised by `rule` and `terminator()`. - It can recover from a failed `rule` by parsing `recovery_rule()`. - It does not recover from a failed `terminator()`. -Values:: - All values produced by `rule` followed by all values produced by `terminator()`. - -{{% playground-example terminator_try "Parse a statement; recover on failure" %}} - -=== Rule `.opt()` - -{{% interface %}} ----- -constexpr _rule_ auto opt(_rule_ auto rule) const; ----- - -[.lead] -`.opt()` returns a rule that parses `rule` if it is there, then parses the terminator. - -Parsing:: - Tries to parse `terminator()` and succeeds if that is the case. - Otherwise, parses `rule` and `terminator()` in {{% docref sequence %}}. -Errors:: - All errors raised by (branch) parsing of `terminator()` and parsing of `rule`. - It can recover from a failed `rule` by parsing `recovery_rule()`. - It does not recover from a failed `terminator()`. -Values:: - * An object of type {{% docref "lexy::dsl::nullopt" "`lexy::nullopt`" %}} followed by all values produced by `terminator()` in the first case. - * All values produced by `rule` followed by all values produced by `terminator()` in the second case. - -{{% playground-example terminator_opt "Parse a (null) statement" %}} - -NOTE: `.opt(rule)` consumes the same input as {{% docref "lexy::dsl::opt" %}}`(` {{% docref "lexy::dsl::peek_not" %}}`(terminator()) >> rule ) + terminator()`, but more efficiently. - -=== Rule `.list()` - -{{% interface %}} ----- -constexpr _rule_ auto list(_rule_ auto item) const; -constexpr _rule_ auto list(_rule_ auto item, _separator_ auto sep) const; ----- - -[.lead] -`.list()` returns a rule that parses a non-empty list of `item`, optionally separated by `sep`, followed by the terminator. - -Parsing:: - It first parses `item` once, recovers if necessary. - Then it enters the main loop of parsing the rest of the list. - 1. It first tries to parse `terminator()`. - If that succeeds, finishes parsing. - Otherwise, it continues with step 2. - 2. If no {{% docref separator %}} was specified, immediately continues with step 4. - Otherwise, tries to parse `sep`. - On success, it continues with step 3. - If the separator was missing, immediately recovers by going to step 4. - Otherwise, recovers as described below. - 3. Tries to parse `terminator()` again. - On success, handles a trailing separator by raising an error if necessary. - It then immediately recovers and succeeds. - 4. Parses `item`. On success, repeats everything by going back to step 1. - Otherwise, recovers as described below. -Errors:: - * All errors raised by branch parsing of `terminator()`. - The rule then fails if `terminator()` has failed and never tries to recover. - * `lexy::unexpected_trailing_separator`: if a trailing separator was parsed but is not allowed; at the position of the trailing separator. - It then recovers without consuming additional input. - * All errors raised by branch parsing of `sep` and parsing `item`. - It then recovers by discarding input until it either matches `sep`, - if `sep` was specified, or until it reaches `item`, if no `sep` was specified. - The latter is only possible if `item` is a branch rule. - If `sep`/`item` was matched, continues in the appropriate step from the parsing algorithm. - If recovery reaches `terminator()`, parses it and finishes. - If recovery reaches the end of the input, or a limit, if one was specified, recovery fails. -Values:: - It creates a sink of the current context. - All items produced by `item` and `sep` are forwarded to it; - there are separate calls for every iteration and for `item` and `sep`. - The value of the finished sink is then produced followed by all values of `terminator()`. - -{{% playground-example terminator_list "Parse a list of things terminated by a period" %}} - -NOTE: `.list(rule, sep)` consumes the same input as {{% docref "lexy::dsl::list" %}}`(` {{% docref "lexy::dsl::peek_not" %}}`(terminator()) >> rule, sep ) + terminator()`, but more efficiently. - -=== Rule `.opt_list()` - -{{% interface %}} ----- -constexpr _rule_ auto opt_list(_rule_ auto item) const; -constexpr _rule_ auto opt_list(_rule_ auto item, _separator_ auto sep) const; ----- - -[.lead] -`.opt_list()` returns a rule that parses a (possibly empty) list of `item`, optionally separated by `sep`, followed by the terminator. - -Parsing:: - Tries to parse `terminator()` and succeeds if that is the case. - Otherwise, it parses the corresponding `.list()` rule. -Errors:: - All errors raised by branch parsing of `terminator()` or parsing of `.list()`. - It never recovers from the terminator, and recovers from `.list()` as described there. -Values:: - The first argument is: - * a `lexy::nullopt` object in the first case, - * The result of the `.list()` rule in the second case. - It is then followed by all values produced by `terminator()`. - -NOTE: This is different from `term.opt(term.list(r))` as that would parse the terminator twice: once by `.list()` and once by `.opt()`. -Apart from that, it behaves identically. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/times.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/times.adoc deleted file mode 100644 index 0106cd7ad5..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/times.adoc +++ /dev/null @@ -1,68 +0,0 @@ ---- -header: "lexy/dsl/times.hpp" -entities: - "lexy::dsl::times": times - "lexy::dsl::twice": twice ---- -:toc: left - -[.lead] -The `times` and `twice` rules. - -[#times] -== Rule `lexy::dsl::times` - -{{% interface %}} ----- -namespace lexy::dsl -{ - template - constexpr _rule_ auto times(_rule_ auto rule); - - template - constexpr _rule_ auto times(_rule_ auto rule, _separator_ auto sep); -} ----- - -[.lead] -`times` is a rule that parses `rule` exactly `N` times in sequence, with an optional separator in between. - -Parsing:: - Parses `rule` exactly `N` times in {{% docref sequence %}}. - If a {{% docref separator %}} has been specified, parses it in between. - After the last rule, handles a trailing separator as necessary. -Errors:: - * All errors raised by parsing `rule` or `sep`. - The rule then fails. - * `lexy::unexpected_trailing_separator`: if a trailing separator can be matched after the last item and that is not allowed; - at the position of the separator. - It then recovers by simply consuming the separator. -Values:: - All values produced by each `rule` invocation in order. - -{{% godbolt-example times_tsep "Parse and sum three integers separated by comma" %}} - -NOTE: See {{% docref "lexy::dsl::repeat" %}} if the number of repetitions should be determined by the input. - -[#twice] -== Rule `lexy::dsl::twice` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ auto twice(_rule_ auto rule) - { - return times<2>(rule); - } - - constexpr _rule_ auto twice(_rule_ auto rule, _separator_ auto sep) - { - return times<2>(rule, sep); - } -} ----- - -[.lead] -`twice` is a rule that is an alias for `times` where `N == 2`. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/token.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/token.adoc deleted file mode 100644 index d9d8043430..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/token.adoc +++ /dev/null @@ -1,120 +0,0 @@ ---- -header: "lexy/dsl/token.hpp" -entities: - "token-rule": doc - ".error": error - ".kind": kind - "lexy::dsl::token": token ---- -:toc: left - -[.lead] -The basic token interface as well as the `token` token rule. - -{{% interface %}} ----- -template -concept _token-rule_ = _rule_ && …; ----- - -A _token_ is an atomic element of the input, which can be parsed by a token rule. -_Token rules_ are special rules that do not produce any values and can be matched efficiently. -As such, every token rule is also a branch rule. - -In a parse tree, every token rule produces a token node which directly captures a substring of the input, the part consumed by the rule. -The token node also has a token kind, which identifies a token rule. - -As token rules are the atomic elements, they also serve the basis for {{% docref whitespace %}} handling: -if automatic whitespace skipping has been enabled, it is skipped after every token rule. - -[#error] -== Token interface `.error` - -{{% interface %}} ----- -class _token-rule_ -{ -public: - template - static constexpr _token-rule_ auto error; - - … -}; ----- - -[.lead] -Every token rule `token` has a `.error` member that overrides the error raised when `token` does not match. - -Matching:: - Matches and consumes `token`. -Errors:: - `Tag`: if matching `token` fails. - Its range covers everything already consumed by `token`. - The rule then fails as well. - -{{% playground-example quoted_error "A string literal with a nice error" %}} - -CAUTION: `.error` overrides _all_ errors raised by a token rule to the same error. -If a token can fail with different kinds of errors, this information is lost. - -[#kind] -== Token interface `.kind` - -{{% interface %}} ----- -class _token-rule_ -{ -public: - template - static constexpr _token-rule_ auto kind; - - … -}; ----- - -[.lead] -Every token rule `token` has a `.kind` member that overrides the token kind of its node in the parse tree. - -Matching:: - Matches and consumes `token`. -Errors:: - All errors raised by `token`. - The rule then fails. -Parse tree:: - A single token whose range covers everything consumed by `token`. - However, its kind is now `Kind`. - -[#token] -== Token rule `lexy::dsl::token` - -{{% interface %}} ----- -namespace lexy -{ - struct missing_token {}; -} - -namespace lexy::dsl -{ - constexpr _token-rule_ auto token(_rule_ auto rule); -} ----- - -[.lead] -`token` is a rule that converts an arbitrary `rule` into a token rule. - -Matching:: - Matches and consumes `rule` in a new context. -Errors:: - `lexy::missing_token`: if matching of `rule` has failed for any reason; - its range covers everything `rule` has already consumed. - The rule then fails. - -NOTE: {{% docref whitespace "Whitespace skipping" %}} is disabled while parsing `rule`, -but it is skipped at the end, as it is a token rule. - -CAUTION: While `token` is optimized itself, parsing `rule` can be arbitrarily expensive. -As such, it should only be used when absolutely required. - -WARNING: `rule` does not have access to any context variables created by the context-sensitive parsing facilities and it can't use recursion. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/unicode.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/unicode.adoc deleted file mode 100644 index ea6e6434fc..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/unicode.adoc +++ /dev/null @@ -1,137 +0,0 @@ ---- -header: "lexy/dsl/unicode.hpp" -entities: - "lexy::dsl::unicode": doc - "lexy::dsl::unicode::control": class - "lexy::dsl::unicode::blank": class - "lexy::dsl::unicode::newline": class - "lexy::dsl::unicode::other_space": class - "lexy::dsl::unicode::space": class - "lexy::dsl::unicode::digit": class - "lexy::dsl::unicode::lower": class - "lexy::dsl::unicode::upper": class - "lexy::dsl::unicode::alpha": class - "lexy::dsl::unicode::alpha_digit": class - "lexy::dsl::unicode::alnum": class - "lexy::dsl::unicode::word": class - "lexy::dsl::unicode::graph": class - "lexy::dsl::unicode::print": class - "lexy::dsl::unicode::character": class - "lexy::dsl::unicode::xid_start": identifier - "lexy::dsl::unicode::xid_start_underscore": identifier - "lexy::dsl::unicode::xid_continue": identifier ---- -:toc: left - -[.lead] -Char class rules for matching Unicode char classes. - -[#class] -== Unicode char classes - -{{% interface %}} ----- -namespace lexy::dsl -{ - namespace unicode - { - constexpr _char-class-rule_ auto control; - - constexpr _char-class-rule_ auto blank; - constexpr _char-class-rule_ auto newline; - constexpr _char-class-rule_ auto other_space; - constexpr _char-class-rule_ auto space; - - constexpr _char-class-rule_ auto digit; - - constexpr _char-class-rule_ auto lower; - constexpr _char-class-rule_ auto upper; - constexpr _char-class-rule_ auto alpha; - - constexpr _char-class-rule_ auto alpha_digit; - constexpr _char-class-rule_ auto alnum = alpha_digit; - - constexpr _char-class-rule_ auto word; - - constexpr _char-class-rule_ auto graph; - constexpr _char-class-rule_ auto print; - - constexpr _char-class-rule_ auto character; - } -} ----- - -[.lead] -These {{% char-class-rule %}}s match one Unicode code point from a char class, as specified in the table below. - -Each class is a superset of the corresponding rule in {{% docref "lexy::dsl::ascii" %}}. -They require the Unicode database. - -[%collapsible] -.The char classes -==== -|=== -| Token Rule | Char Class - -| `control` | link:https://unicode.org/reports/tr18/#cntrl[`Cc` (Other, control)] -| `blank` | link:https://unicode.org/reports/tr18/#blank[`Zs` (Separator, space) or `\t`] -| `newline` | `\r`, `\n`, `NEL`, `LINE SEPARATOR`, or `PARAGRAPH SEPARATOR` -| `other_space` | `\f` or `\v` -| `space` | link:https://unicode.org/reports/tr18/#space[`Whitespace`], which is `blank`, `newline` or `other_space` -| `digit` | link:https://unicode.org/reports/tr18/#digit[`Nd` (Number, decimal digit)] -| `lower` | link:https://unicode.org/reports/tr18/#lower[`Lowercase`] -| `upper` | link:https://unicode.org/reports/tr18/#upper[`Uppercase`] -| `alpha` | link:https://unicode.org/reports/tr18/#alpha[`Alphabetic`] -| `alpha_digit` | link:https://unicode.org/reports/tr18/#alnum[`alpha`, `digit`] -| `word` | link:https://unicode.org/reports/tr18/#word[`alpha`, `digit`, `M` (Mark), `Pc` (Punctuation, connector), join control] -| `graph` | link:https://unicode.org/reports/tr18/#graph[everything but `space`, `control`, `Cs` (Other, surrogate), `Cn` (Other, not assigned)] -| `print` | link:https://unicode.org/reports/tr18/#graph[`graph` or `blank` but without `control`] -| `character` | any code point that is assigned (i.e. not `Cn` (Other, not assigned)) -|=== -==== - -CAUTION: Unlike in the ASCII case, `alpha` is *not* `lower` or `upper`: there are alphabetic characters that don't have a case. - -CAUTION: Differentiate between `lexy::dsl::unicode::newline`, which matches `\r` or `\n` and others, and {{% docref "lexy::dsl::newline" %}}, which matches `\r\n` or `\n`! - -CAUTION: As token rules, they match {{% docref whitespace whitespace %}} immediately following the character. -As such, the rule is best used in contexts where automatic whitespace skipping is disabled. -They can safely be used as part of the whitespace definition. - -NOTE: There is no `dsl::unicode::punct`. -The Unicode standard defines it as general category `P` (Punctuation), which is unsatisfactory as it does not include e.g. `$` unlike `dsl::ascii::punct` (it's a currency symbol instead). -POSIX includes `$` as well as other non-alphabetic symbols, which is unsatisfactory as `dsl::unicode::punct` would include characters Unicode does not consider punctuation. - -[#identifier] -== Unicode identifier classes - -{{% interface %}} ----- -namespace lexy::dsl -{ - namespace unicode - { - constexpr _char-class-rule_ auto xid_start; - constexpr _char-class-rule_ auto xid_start_underscore; - constexpr _char-class-rule_ auto xid_continue; - } -} ----- - -[.lead] -These {{% char-class-rule %}}s match one Unicode code point from the link:https://unicode.org/reports/tr31/[`XID_Start`/`XID_Continue`] character classes. -They are used to parse Unicode-aware {{% docref "lexy::dsl::identifier" %}}. - -* `xid_start` matches any Unicode character that can occur at the beginning of an identifier. - It is a superset of {{% docref "lexy::dsl::ascii::alpha" %}}. -* `xid_start_underscore` matches `xid_start` or `_` (underscore. - It is a superset of {{% docref "lexy::dsl::ascii::alpha_underscore" %}}. -* `xid_continue` matches any Unicode character that can occur after the initial character of an identifier. - It is a superset of {{% docref "lexy::dsl::ascii::alpha_digit_underscore" %}}. - -They require the Unicode database. - -{{% playground-example identifier-unicode "Parse a Unicode-aware C-like identifier" %}} - -WARNING: `xid_start` does not include `_` (underscore)! - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/until.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/until.adoc deleted file mode 100644 index 4538737799..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/until.adoc +++ /dev/null @@ -1,55 +0,0 @@ ---- -header: "lexy/dsl/until.hpp" -entities: - "lexy::dsl::until": until ---- -:toc: left - -[#until] -== Token rule `lexy::dsl::until` - -{{% interface %}} ----- -namespace lexy::dsl -{ - class _until-dsl_ // models _token-rule_ - { - public: - constexpr _token-rule_ auto or_eof() const; - }; - - constexpr _until-dsl_ until(_token-rule_ auto condition); -} ----- - -[.lead] -`until` is a {{% token-rule %}} that matches all input until and including a terminating condition. - -Matching:: - Tries to match `condition` anywhere in the remaining input, then consumes it. - If `.or_eof()` has been used, succeeds when it reaches EOF without matching `condition`. - Otherwise, fails when it reaches EOF. -Errors:: - All errors raised by matching `condition` at EOF, if `.or_eof()` has not been used. - It then fails. - If `.or_eof()` has been used, it can never fail. -Parse tree:: - A single token node that contains everything consumed before `condition` and everything consumed by `condition`. - It has the {{% docref "lexy::predefined_token_kind" %}} `lexy::any_token_kind`. - -`until(condition)` aggressively discards input to find a match for `condition`. -It doesn't matter what the input is. -`until(condition).or_eof()` behaves just like `until(condition /` {{% docref "lexy::dsl::eof" %}} `)`, -i.e. the end of the input is also considered to be a terminating condition. -If `.or_eof()` was used, the rule never fails, but it may consume the rest of the input. - -{{% playground-example cpp_comment "A C++-style comment" %}} - -CAUTION: `until()` does not care what input it consumes to find `condition`; it can be {{% docref "lexy::dsl::any" %}}thing, including ill-formed Unicode. -To restrict the input that is allowed before `condition`, use {{% docref "lexy::dsl::terminator" %}}`(condition).while_(before)`. - -WARNING: If the `condition` is missing, `until(condition).or_eof()` will happily discard the rest of the input. -This is similar to the behavior of an unterminated `/*` comment. - -NOTE: `until` will include `condition`. - diff --git a/assembler/ext/src/lexy/docs/content/reference/dsl/whitespace.adoc b/assembler/ext/src/lexy/docs/content/reference/dsl/whitespace.adoc deleted file mode 100644 index 62ca8b857d..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/dsl/whitespace.adoc +++ /dev/null @@ -1,127 +0,0 @@ ---- -header: "lexy/dsl/whitespace.hpp" -entities: - "whitespace": doc - "lexy::dsl::whitespace": whitespace - "lexy::dsl::no_whitespace": no_whitespace ---- -:toc: left - -[.lead] -Facilities for skipping whitespace. - -By default, lexy does not treat whitespace in any particular way and it has to be parsed just like anything else in the input. -However, as there are grammars that allow whitespace in a lot of places, it is often convenient to have it taken care of. -lexy can be instructed to handle whitespace, using either manual or automatic whitespace skipping. - -Manual whitespace skipping is done using {{% docref "lexy::dsl::whitespace" %}}. -It skips zero or more of whitespace defined by `ws` and can be inserted everywhere you want to skip over whitespace. -This method is recommended where whitespace is an essential part of the grammar. -See {{< github-example email >}} or {{< github-example xml >}} for examples of manual whitespace skipping. - -link:#whitespace-auto[Automatic whitespace] skipping is done by adding a `static constexpr auto whitespace` member to the root production. -This is a rule that defines default whitespace for the entire grammar, as the `ws` argument did in the manual example. -lexy then skips zero or more occurrences of whitespace after every token rule in the grammar, unless it has been manually disabled (see below). -This method is recommend where whitespace is not important and is just there to format the input nicely. -See {{< github-example tutorial >}} or {{< github-example json >}} for examples of automatic whitespace skipping. - -NOTE: "Whitespace" does not mean literal whitespace characters. It can also include comments (or whatever else you want). - -[#whitespace] -== Rule `lexy::dsl::whitespace` - -{{% interface %}} ----- -namespace lexy::dsl -{ - class _ws-rule_ // models _rule_ - {}; - - constexpr _ws-rule_ whitespace(_rule_ auto ws); - - constexpr _ws-rule_ operator|(_ws-rule_ rhs, _rule_ auto lhs) const; - constexpr _ws-rule_ operator|(_rule_ auto rhs, _ws-rule_ lhs) const; -} ----- - -[.lead] -The manual `whitespace` overload is a rule that skips whitespace as defined by its argument. - -Requires:: - * `ws` is either a {{% branch-rule %}} or a {{% docref choice %}} that does not produce any values. - * `ws` does not contain {{% docref "lexy::dsl::p" %}} or {{% docref "lexy::dsl::recurse" %}} rule. -Parses:: - Parses {{% docref "lexy::dsl::loop" %}}`(ws | lexy::dsl::else_ >> lexy::dsl::break_)` in a context where whitespace skipping is disabled. -Errors:: - All errors raised during parsing of `ws | lexy::dsl::else_ >> lexy::dsl::break_`. - The rule then fails if `ws` has failed; even if in a branch context. -Parse tree:: - A single token node with the {{% docref "lexy::predefined_token_kind" %}} `lexy::whitespace_token_kind` whose range covers everything consumed; - all individual token nodes of the whitespace rules are merged into this one. - It is only added to the parse tree if it is not empty. - -For convenience, `operator|` are overloaded for the whitespace rule. -Here, `whitespace(a) | b` is entirely equivalent to `whitespace(a | b)`, and likewise for the other overloads. -They simply allow adding more whitespace to a rule after it has already been wrapped in `whitespace`. - -{{% playground-example manual_whitespace "Simple manual whitespace skipping" %}} - -TIP: Use {{% docref "lexy::dsl::ascii::space" %}} to skip all ASCII whitespace characters. - -[#whitespace-auto] -== Automatic whitespace skipping - -For automatic whitespace skipping lexy inserts a {{% docref "lexy::dsl::whitespace" %}}`(ws)` rule after every {{% token-rule %}}, a {{% docref "lexy::dsl::p" %}} or {{% docref "lexy::dsl::recurse" %}} rule that parses a production inheriting from {{% docref "lexy::token_production" %}}, or after a {{% docref "lexy::dsl::no_whitespace" %}} rule; -or when starting to parse a production that defines a new whitespace rule. - -Here `ws` is determined as follows: - -1. If automatic whitespace skipping has been disabled (e.g. by using `lexy::dsl::no_whitespace()`), - `ws` is the rule that matches the empty string. - As such, no automatic whitespace skipping takes place. -2. If {{% docref "lexy::production_whitespace" %}} for the current production and the whitespace production is non-void, `ws` is that rule. - Here, the whitespace production is determined by following any `lexy::dsl::p` or `lexy::dsl::recurse` calls backwards, - until a production that defines a `::whitespace` member, the top-level production originally passed to a parse function, or a production inheriting from {{% docref "lexy::token_production" %}} is reached. -3. Otherwise (if it is `void`), `ws` is the rule that matches the empty string and no whitespace skipping takes place. - -{{% playground-example whitespace "Simple automatic whitespace skipping" %}} - -{{% playground-example whitespace_comment "Comments can be whitespace too" %}} - -{{% playground-example whitespace_determination "How whitespace is determined" true %}} - -CAUTION: If e.g. a token production defines a new whitespace rule, this is skipped after the last token of the production. -Then the whitespace rule of the parent production is skipped as well, as seen in the example. - -TIP: Use {{% docref "lexy::dsl::ascii::space" %}} to skip all ASCII whitespace characters. - -[#no_whitespace] -== Rule `lexy::dsl::no_whitespace` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _rule_ no_whitespace(_rule_ auto rule); - constexpr _branch-rule_ no_whitespace(_branch-rule_ auto rule); -} ----- - -[.lead] -`no_whitespace` is a rule that parses `rule` without automatic whitespace skipping. - -(Branch) Parsing:: - Parses `rule` in a context where there is no current whitespace rule and link:#whitespace-automatic[`lexy::dsl::whitespace`] does nothing. -Errors:: - All errors raised by `rule`. - The rule then fails if `rule` has failed. -Values:: - All values produced by `rule`. - -{{% playground-example no_whitespace "Disable whitespace between two tokens" %}} - -TIP: In most situations, you should prefer a {{% docref "lexy::token_production" %}} instead. -`no_whitespace` is mostly used as implementation detail for rules that should never have whitespace skipping, like {{% docref "lexy::dsl::delimited" %}}. - -CAUTION: When `r` contains a {{% docref "lexy::dsl::p" %}} or {{% docref "lexy::dsl::recurse" %}} rule, whitespace skipping is re-enabled while parsing the production. - diff --git a/assembler/ext/src/lexy/docs/content/reference/encoding.adoc b/assembler/ext/src/lexy/docs/content/reference/encoding.adoc deleted file mode 100644 index d56f86b00e..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/encoding.adoc +++ /dev/null @@ -1,157 +0,0 @@ ---- -header: "lexy/encoding.hpp" -entities: - "encoding": doc - "lexy::default_encoding": encoding - "lexy::ascii_encoding": encoding - "lexy::utf8_encoding": encoding - "lexy::utf16_encoding": encoding - "lexy::utf32_encoding": encoding - "lexy::byte_encoding": encoding - "lexy::deduce_encoding": deduce_encoding - "lexy::encoding_endianness": encoding_endianness ---- -:toc: left - -[.lead] -Facilities for handling the encoding of an input. - -[source,cpp] ----- -template -concept encoding = …; ----- - -An _encoding_ determines how characters are encoded in the input by defining the type of individual code units and how they are used to form Unicode code points, if applicable. -Its _primary character type_ `::char_type` is the actual character type an input gives you, -but it can also have _secondary character types_ which are also accepted but then internally normalized to the primary character type. -Its _integer type_ `::int_type` is an integer type which can store any valid character type or a special EOF value. -If this is the same type as the primary character type, some optimizations are possible. - -Some {{% docref "rule" %}}s require a certain encoding. -For example, {{% docref "lexy::dsl::code_point" %}} does not work with {{% docref "lexy::default_encoding" %}}. - -[#encoding] -== Supported encodings - -{{% interface %}} ----- -namespace lexy -{ - struct default_encoding {}; // any 8-bit encoding - - struct ascii_encoding {}; // ASCII - struct utf8_encoding {}; // UTF-8 - struct utf16_encoding {}; // UTF-16 - struct utf32_encoding {}; // UTF-32 - - struct byte_encoding {}; // not text -} ----- - -[.lead] -Tag types for the encodings supported by lexy. - -[%collapsible] -.The character types -==== -|=== -| Encoding | Primary character type | Secondary character type(s) - -| `default_encoding` | `char` | none -| `ascii_encoding` | `char` | none -| `utf8_encoding` | `char8_t` | `char` -| `utf16_encoding` | `char16_t` | `wchar_t` (Windows only) -| `utf32_encoding` | `char32_t` | `wchar_t` (Linux and related systems) -| `byte_encoding` | `unsigned char` | `char`, `std::byte` -|=== -==== - -Each tag type corresponds to the encoding indicated and it uses the character types defined in the table above. -If an encoding is specified, lexy assumes that the input is valid for this encoding and will not perform any checking unless otherwise indicated. -If the input contains invalid code units or invalid sequences of code units, -lexy may or may not generate bogus parse errors. - -NOTE: For example, if the input contains the byte sequence lexy uses to encode EOF, -which is never a valid code unit for the encoding, lexy will raise an unexpected EOF error before the actual end of the input. - -`default_encoding` is used as fallback if no encoding is specified or could be deduced. -This encoding works with any 8-bit encoding where the code units `0x00-0x7F` correspond to the ASCII characters (ASCII, UTF-8, Windows code pages, etc.). -Rules that require knowledge about the actual encoding like {{% docref "lexy::dsl::code_point" %}} do not work and some optimizations are impossible, as lexy has to assume that every 8-bit value is valid code unit. - -TIP: If you know that your input is ASCII or UTF-8, use `ascii_encoding`/`utf8_encoding` instead. - -`byte_encoding` is used to indicate that the input does not contain actual text but arbitrary bytes. -It can also be used if you're parsing text consisting of a mix of different encodings. - -[#deduce_encoding] -== Alias template `lexy::deduce_encoding` - -{{% interface %}} ----- -namespace lexy -{ - template - using deduce_encoding = …; -} ----- - -[.lead] -Deduces an encoding from the character type of a string. - -[%collapsible] -.Deduced encoding -==== -|=== -| Character type | Encoding - -| `char` | `lexy::default_encoding` -| `char8_t` | `lexy::utf8_encoding` -| `char16_t` | `lexy::utf16_encoding` -| `char32_t` | `lexy::utf32_encoding` -| `unsigned char`| `lexy::byte_encoding` -| `std::byte` | `lexy::byte_encoding` -|=== -==== - -What encoding is deduced from a character type is specified in the table above. -If `CharT` is not listed there, the alias is ill-formed. - -The encoding corresponding to `char` can be overridden by defining the macro `LEXY_ENCODING_OF_CHAR` to one of `lexy::default_encoding`, `lexy::ascii_encoding` and `lexy::utf8_encoding`. - -[#encoding_endianness] -== Enum class `lexy::encoding_endianness` - -{{% interface %}} ----- -namespace lexy -{ - enum class encoding_endianness - { - little, - big, - bom, - }; -} ----- - -[.lead] -Defines the endianness of a multi-byte encoding when necessary. - -In memory, UTF-16 and UTF-32 can be either encoded in big or little endian. -If raw bytes need to be interpreted as code units in those encodings, -as is necessary by `lexy::read_file`, the desired endianness can be specified using `encoding_endianness`. - -`little`:: - The input is stored in little endian. For single-byte encodings, this has no effect. -`big`:: - The input is stored in big endian. For single-byte encodings, this has no effect. -`bom`:: - The input is stored in the endianness specified by the link:https://en.wikipedia.org/wiki/Byte_order_mark[byte order mark (BOM)] at the beginning of the input. - This option has an effect only for UTF-8, UTF-16, and UTF-32. - For UTF-8, it will skip an optional BOM, but it has otherwise no effect. - If no BOM is present, it defaults to big endian. - -{{% docref "lexy::make_buffer_from_raw" %}} and {{% docref "lexy::read_file" %}} use this enum to handle the endianness of the raw memory, -and the rule {{% docref "lexy::dsl::bom" %}} uses it to specify a given BOM. - diff --git a/assembler/ext/src/lexy/docs/content/reference/error.adoc b/assembler/ext/src/lexy/docs/content/reference/error.adoc deleted file mode 100644 index 12cd1421bf..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/error.adoc +++ /dev/null @@ -1,238 +0,0 @@ ---- -header: "lexy/error.hpp" -entities: - "lexy::error": error - "lexy::error_for": error - "lexy::expected_literal": expected_literal - "lexy::expected_keyword": expected_keyword - "lexy::expected_char_class": expected_char_class - "lexy::error_context": error_context ---- -:toc: left - -[.lead] -Classes to store information about parse errors. - -[#error] -== Class `lexy::error` - -{{% interface %}} ----- -namespace lexy -{ - template <_reader_ Reader, typename Tag> - class error; - - struct expected_literal {}; - template <_reader_ Reader> - class error; - - struct expected_keyword {}; - template <_reader_ Reader> - class error; - - struct expected_char_class {}; - template <_reader_ Reader> - class error; - - template <_input_ Input, typename Tag> - using error_for = error, Tag>; -} ----- - -[.lead] -Represents a parse error. - -Different kinds of errors are identified by the `Tag`, which is an empty tag type. -The error type is specialized for three tags. - -=== Generic error (primary template) - -{{% interface %}} ----- -template <_reader_ Reader, typename Tag> -class error -{ - using _iterator_ = typename Reader::iterator; - -public: - constexpr explicit error(_iterator_ begin, _iterator_ end) noexcept; - constexpr explicit error(_iterator_ pos) noexcept - : error(pos, pos) - {} - - constexpr _iterator_ position() const noexcept - { - return begin(); - } - - constexpr _iterator_ begin() const noexcept; - constexpr _iterator_ end() const noexcept; - - constexpr const char* message() const noexcept; -}; ----- - -[.lead] -A generic error without additional data. - -`position()` is the position where the error occurred, while `begin()` and `end()` return the entire range. -For some errors, this range is empty. - -`message()` is determined by `Tag`. -By default, it is the type name of `Tag` after removing the top-level namespace. -This can be overridden by `Tag::name()` or `Tag::name`. - -{{% playground-example "exhausted_choice" "Choice raises generic error at a single position" %}} - -{{% playground-example "reserved_identifier" "Identifier rules raise a generic error spanning a sub-range" %}} - -[#expected_literal] -=== `lexy::expected_literal` error - -{{% interface %}} ----- -struct expected_literal {}; - -template <_reader_ Reader> -class error -{ - using _iterator_ = typename Reader::iterator; - using _char_type_ = typename Reader::encoding::char_type; - -public: - constexpr explicit error(_iterator_ pos, - const _char_type_* string, - std::size_t index, std::size_t length) noexcept; - - constexpr _iterator_ position() const noexcept; - - constexpr const _char_type_* string() const noexcept; - constexpr std::size_t index() const noexcept; - constexpr std::size_t length() const noexcept; - - constexpr _char_type_ character() const noexcept - { - return string()[index()]; - } -}; ----- - -[.lead] -An error where a given literal string was expected. - -The error can be raised while trying to parse `string()` with `length()` beginning at `position()`; -the code unit at `std::next(position(), index())` did not match `character()`. -If the remaining input contained fewer code units than `string()`, `index()` indicates the first code unit that was missing. - -It is raised by {{% docref "lexy::dsl::lit" %}} and related rules. - -{{% playground-example "expected_literal" "`LEXY_LIT()` raises an expected literal error" %}} - -[#expected_keyword] -=== `lexy::expected_keyword` error - -{{% interface %}} ----- -struct expected_keyword {}; - -template <_reader_ Reader> -class error -{ - using _iterator_ = typename Reader::iterator; - using _char_type_ = typename Reader::encoding::char_type; - -public: - constexpr explicit error(_iterator_ begin, _iterator_ end, - const _char_type_* string, std::size_t length) noexcept; - - constexpr _iterator_ position() const noexcept; - - constexpr _iterator_ begin() const noexcept; - constexpr _iterator_ end() const noexcept; - - constexpr const _char_type_* string() const noexcept; - constexpr std::size_t length() const noexcept; -}; ----- - -[.lead] -An error where a given keyword was expected. - -The error can be raised while trying to parse the keyword `string()` with `length()` against the identifier `[begin(), end())`, -but it was a different identifier. -The `position()` is also `begin()`. - -It is raised by {{% docref "lexy::dsl::keyword" %}}. - -{{% playground-example "keyword" "`LEXY_KEYWORD()` raises an expected keyword error" %}} - -[#expected_char_class] -=== `lexy::expected_char_class` error - -{{% interface %}} ----- -struct expected_char_class {}; - -template <_reader_ Reader> -class error -{ - using _iterator_ = typename Reader::iterator; - -public: - constexpr explicit error(_iterator_ pos, const char* name) noexcept; - - constexpr _iterator_ position() const noexcept; - - constexpr const char* name() const noexcept; -}; ----- - -[.lead] -An error where one character from a character class was expected. - -The error can be raised while trying to parse the character class with the human-readable name `character_class()` at `position()`. -This happens in rules like {{% docref "lexy::dsl::ascii" %}} or {{% docref "lexy::dsl::digit" %}}. - -{{% playground-example "expected_char_class" "`dsl::digit` raises an expected char class error" %}} - -[#error_context] -== Class `lexy::error_context` - -{{% interface %}} ----- -namespace lexy -{ - template <_production_ Production, _input_ Input> - class error_context - { - using _iterator_ = typename input_reader::iterator; - - public: - constexpr explicit error_context(const Input& input, - _iterator_ pos) noexcept; - constexpr explicit error_context(Production, - const Input& input, - _iterator_ pos) noexcept; - - static consteval const char* production() noexcept; - - constexpr const Input& input() const noexcept; - - constexpr _iterator_ position() const noexcept; - }; -} ----- - -[.lead] -Contains additional information about an error. - -`input()`:: - The entire input where the error occurred; all positions are iterators into that input. - If the input is {{% docref "lexy::lexeme_input" %}}, returns the parent input instead. - This allows correct computation of the {{% docref "lexy::input_location" %}}. -`production()`:: - The name of the production where the error occurred, i.e. {{% docref "lexy::production_name" %}}. -`position()`:: - The position where it started to parse `Production`. - diff --git a/assembler/ext/src/lexy/docs/content/reference/grammar.adoc b/assembler/ext/src/lexy/docs/content/reference/grammar.adoc deleted file mode 100644 index bff240eac9..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/grammar.adoc +++ /dev/null @@ -1,215 +0,0 @@ ---- -header: "lexy/grammar.hpp" -entities: - "lexy::production_name": production_name - "lexy::production_rule": production_rule - "lexy::production_whitespace": production_whitespace - "lexy::production_value_callback": production_value_callback - "lexy::token_production": token_production - "lexy::transparent_production": transparent_production - "lexy::max_recursion_depth": max_recursion_depth ---- -:toc: left - -[.lead] -Traits and definitions for the grammar. - -== Grammar traits - -{{% interface %}} ----- -namespace lexy -{ - template - constexpr bool is_production; <1> - - template - constexpr bool is_rule; <2> - template - constexpr bool is_branch_rule; <3> - template - constexpr bool is_unconditional_branch_rule; <4> - template - constexpr bool is_token_rule; <5> - - template - constexpr bool is_literal_rule; <6> - template - constexpr bool is_literal_set_rule; <7> - template - constexpr bool is_char_class_rule; <8> - - template - constexpr bool is_separator; <9> -} ----- -<1> Whether or not `T` is a production, i.e. it has a `::rule` member. -<2> Whether or not `T` is a {{% rule %}}. -<3> Whether or not `T` is a {{% branch-rule %}}. -<4> Whether or not `T` is an unconditional {{% branch-rule %}} (e.g. {{% docref "lexy::dsl::else_" %}}). -<5> Whether or not `T` is a {{% token-rule %}}. -<6> Whether or not `T` is a {{% literal-rule %}}. -<7> Whether or not `T` is a {{% docref "lexy::dsl::literal_set" %}} rule. -<8> Whether or not `T` is a {{% char-class-rule %}}. -<9> Whether or not `T` is a separator ({{% docref "lexy::dsl::sep" %}} and {{% docref "lexy::dsl::trailing_sep" %}}). - -[#production_name] -== Function `lexy::production_name` - -{{% interface %}} ----- -namespace lexy -{ - template <_production_ Production> - consteval const char* production_name(); -} ----- - -[.lead] -Returns the name of the production. - -By default, it is the type name of `Production` after removing the top-level namespace. -This can be overridden by `Production::name()` or `Production::name`. - -[#production_rule] -== Trait `lexy::production_rule` - -{{% interface %}} ----- -namespace lexy -{ - template <_production_ Production> - using production_rule = std::decay_t; -} ----- - -[.lead] -Returns the type of the {{% rule %}} of production, i.e. the type of `Production::rule`. - -[#production_whitespace] -== Trait `lexy::production_whitespace` - -{{% interface %}} ----- -namespace lexy -{ - template <_production_ Production, _production_ WhitespaceProduction> - using production_whitespace = _see-below_; -} ----- - -[.lead] -Returns the type of the {{% docref "whitespace" %}} rule of `Production` given its last parent `WhitespaceProduction`. - -It is determined as follows: - -1. If `Production::whitespace` is valid, returns the decayed type of that. -2. If `WhitespaceProduction::whitespace` is valid, returns the decayed type of that. -3. Otherwise, returns `void`. - -This is used by {{% docref "lexy::dsl::whitespace" %}} during automatic whitespace skipping. - -[#production_value_callback] -== Callback `lexy::production_value_callback` - -{{% interface %}} ----- -namespace lexy -{ - template <_production_ Production, typename ParseState = void> - class production_value_callback - { - public: - constexpr explicit production_value_callback(const ParseState&); - - using return_type = _see-below_; - - constexpr _sink_ auto sink() const; - - template - constexpr return_type operator()(Args&&... args); - }; -} ----- - -[.lead] -A callback and sink for the specified `Production`. - -It wraps an underlying callback/sink, which is determined as follows: - -1. `ParseState` is non-void and the call `state.value_of(Production{})` is well-formed. - It will use the result as the underlying callback/sink. -2. `ParseState` is non-void but `state.value_of(Production{})` is ill-formed. - It will use `Production::value` as the underlying callback/sink, passing the parse state to `.sink()` and as state parameter to the callback. -3. `ParseState` is void. - It will use `Production::value` as the underlying callback/sink. - -The behavior of the member functions depends on three cases: - -1. If the underlying callback/sink is a link:{{< relref "callback#callback" >}}[callback], `return_type` is its return type, `.sink()` is ill-formed and `operator()` forwards to `Production::value.operator()`. -2. If the underlying callback/sink is a link:{{< relref "callback#sink" >}}[sink], -`return_type` is its return type, `.sink()` forwards to `Production::value.sink()`, and `operator()` accepts the return type of the sink and forwards it unchanged. -3. If the underlying callback/sink is both a callback and a sink, `return_type` is the return type of the callback, `.sink()` forwards to the sink, and `operator()` to the callback. - -TIP: Use {{% docref "lexy::operator>>" %}} to combine a sink and a callback in one `Production::value`. - -[#max_recursion_depth] -== Function `lexy::max_recursion_depth` - -{{% interface %}} ----- -namespace lexy -{ - template <_production_ EntryProduction> - consteval std::size_t max_recursion_depth(); -} ----- - -[.lead] -Returns the maximum recursion depth of a grammar given its entry production. - -If the entry production has a `static std::size_t` member named `max_recursion_depth` (i.e. `EntryProduction::max_recursion_depth` is well-formed), returns that value. -Otherwise returns an implementation-defined "big" value (currently 1024). - -If the recursion depth of {{% docref "lexy::dsl::recurse" %}} exceeds this value, an error is raised. - -[#token_production] -== Class `lexy::token_production` - -{{% interface %}} ----- -namespace lexy -{ - struct token_production - {}; - - template <_production_ Production> - constexpr bool is_token_production = std::is_base_of_v; -} ----- - -[.lead] -Base class to indicate that a production is conceptually a token. -This inhibits whitespace skipping (directly) inside the production. - -[#transparent_production] -== Class `lexy::transparent_production` - -{{% interface %}} ----- -namespace lexy -{ - struct transparent_production - {}; - - template <_production_ Production> - constexpr bool is_transparent_production = std::is_base_of_v; -} ----- - -[.lead] -Base class to indicate that this production should not show up in the parse tree. - -In the parse tree, there will be no separate node for `Production`. -Instead, all child nodes of `Production` are added to its parent node. - diff --git a/assembler/ext/src/lexy/docs/content/reference/input/argv_input.adoc b/assembler/ext/src/lexy/docs/content/reference/input/argv_input.adoc deleted file mode 100644 index d21bcdda75..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/input/argv_input.adoc +++ /dev/null @@ -1,128 +0,0 @@ ---- -header: "lexy/input/argv_input.hpp" -entities: - "lexy::argv_iterator": range - "lexy::argv_sentinel": range - "lexy::argv_begin": range - "lexy::argv_end": range - "lexy::argv_input": argv_input - "lexy::argv_lexeme": typedefs - "lexy::argv_error": typedefs - "lexy::argv_error_context": typedefs - "lexy::dsl::argv_separator": argv_separator ---- -:toc: left - -[.lead] -An input that uses the command line arguments. - -[#range] -== Range `lexy::argv_begin`/`lexy::argv_end` - -{{% interface %}} ----- -namespace lexy -{ - class argv_sentinel; - class argv_iterator; - - constexpr argv_iterator argv_begin(int argc, char* argv[]) noexcept; - constexpr argv_iterator argv_end(int argc, char* argv[]) noexcept; -} ----- - -[.lead] -An iterator range over the characters of the command-line arguments. - -`argv_iterator` is a bidirectional iterator with value type `const char` that iterates over the characters of the command-line arguments. -It includes the null character as separator between two arguments, but not after the last argument. -`argv_sentinel` is its corresponding sentinel. - -`argv_begin` returns an iterator to the first character of the first command-line argument after the executable name (i.e. `argv[1][0]`), -`argv_end` returns an iterator one past the last character of the last argument (i.e. `argv[argc - 1] + std::strlen(argv[argc - 1])`). - -{{% godbolt-example "argv_iterator" "Print the command-line arguments" %}} - -[#argv_input] -== Input `lexy::argv_input` - -{{% interface %}} ----- -namespace lexy -{ - template <_encoding_ Encoding = default_encoding> - class argv_input - { - public: - using encoding = Encoding; - using char_type = typename encoding::char_type; - - constexpr argv_input(); - - constexpr argv_input(argv_iterator begin, argv_iterator end) noexcept; - constexpr argv_input(int argc, char* argv[]) noexcept - : argv_input(argv_begin(argc, argv), argv_end(argc, argv)) - {} - - constexpr _reader_ auto reader() const& noexcept; - }; -} ----- - -[.lead] -The class `argv_input` is an input that uses the command-line arguments as input. - -Its {{% encoding %}} must have `char` as primary or secondary character type. -The range `[begin, end)` of the {{% docref "lexy::argv_iterator" %}} will be used as input. - -{{% godbolt-example "argv_input" "Use the command-line arguments as input" %}} - -NOTE: The input will contain `\0` as separator between two command-line arguments. -Use the rule {{% docref "lexy::dsl::argv_separator" %}} to match it. - -[#typedefs] -== Convenience typedefs - -{{% interface %}} ----- -namespace lexy -{ - template <_encoding_ Encoding = default_encoding> - using argv_lexeme = lexeme_for>; - - template - using argv_error = error_for, Tag>; - - template - using argv_error_context = error_context>; -} ----- - -[.lead] -Convenience typedefs for the command-line argument input. - -[#argv_separator] -== Token rule `lexy::dsl::argv_separator` - -{{% interface %}} ----- -namespace lexy::dsl -{ - constexpr _token-rule_ auto argv_separator; -} ----- - -[.lead] -`argv_separator` is a {{% token-rule %}} that matches the separator between two command-line arguments. - -Matching:: - Matches and consumes the separator between two command-line arguments. -Errors:: - {{% docref "lexy::expected_char_class" %}} (`"argv-separator"`): at the unchanged reader position. - The rule then fails. -Parse tree:: - Single token node with the {{% docref "lexy::predefined_token_kind" %}} `lexy::literal_token_kind`. - -The rule can only succeed on a {{% docref "lexy::argv_input" %}}. -There is no argument separator before the first command-line argument, or after the last one. - diff --git a/assembler/ext/src/lexy/docs/content/reference/input/buffer.adoc b/assembler/ext/src/lexy/docs/content/reference/input/buffer.adoc deleted file mode 100644 index 486747ebfa..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/input/buffer.adoc +++ /dev/null @@ -1,222 +0,0 @@ ---- -header: "lexy/input/buffer.hpp" -entities: - "lexy::buffer": buffer - "lexy::make_buffer_from_raw": make_buffer_from_raw - "lexy::buffer_lexeme": typedefs - "lexy::buffer_error": typedefs - "lexy::buffer_error_context": typedefs ---- -:toc: left - -[.lead] -Inputs that read from a buffer in memory. - -[#buffer] -== Input `lexy::buffer` - -{{% interface %}} ----- -namespace lexy -{ - template <_encoding_ Encoding = default_encoding, - typename MemoryResource = _default-resource_> - class buffer - { - public: - using encoding = Encoding; - using char_type = typename encoding::char_type; - - //=== construction ===// - class builder; - - constexpr buffer() noexcept; - constexpr explicit buffer(MemoryResource* resource) noexcept; - - template - explicit buffer(const CharT* data, std::size_t size, - MemoryResource* resource = _default-resource_); - template - explicit buffer(const CharT* begin, const CharT* end, - MemoryResource* resource = _default-resource_); - template - explicit buffer(const View& view, - MemoryResource* resource = _default-resource_); - - buffer(const buffer& other, MemoryResource* resource); - - //=== access ===// - const char_type* data() const noexcept; - std::size_t size() const noexcept; - - _reader_ auto reader() const& noexcept; - }; -} ----- - -[.lead] -The class `buffer` is an immutable, owning variant of {{% docref "lexy::string_input" %}}. - -All memory allocation is done via a `MemoryResource` object, -which must be a class with the same interface as `std::pmr::memory_resource`. -By default, it uses `new` and `delete`. -The memory resource object passed to the constructor does not propagate during copy/move/swap. - -{{% godbolt-example "buffer" "Build a buffer that contains the input" %}} - -TIP: As the buffer owns the input, it can terminate it with the EOF character for encodings that have the same character and integer type. -This eliminates a branch during parsing, because there is no need to check for the end of the buffer. - -=== Empty constructors - -{{% interface %}} ----- -constexpr buffer() noexcept; -constexpr explicit buffer(MemoryResource* resource) noexcept; ----- - -Both overloads construct an empty buffer. -The first one requires that `MemoryResource` is the `_default-resource_` and uses that one; -the second one uses the specified `resource`. - -Once the resource is set, it cannot be changed; -assignment will only update the memory contents, not the resource. - -=== Pointer constructors - -{{% interface %}} ----- -template -explicit buffer(const CharT* data, std::size_t size, - MemoryResource* resource = _default-resource_); <1> -template -explicit buffer(const CharT* begin, const CharT* end, - MemoryResource* resource = _default-resource_); <2> - -template -buffer(const CharT* data, std::size_t size) - -> buffer>; -template -buffer(const CharT* begin, const CharT* end) - -> buffer>; ----- -<1> Use the contiguous range `[data, data + size)` as input. -<2> Use the contiguous range `[begin, end)` as input. - -`CharT` must be the primary or secondary character type of the {{% encoding %}}. -Both overloads use `resource` for memory allocation. -CTAD can be used to deduce the encoding from the character type. - -=== View constructor - -{{% interface %}} ----- -template - requires requires (View view) { - view.data(); - view.size(); - } -explicit buffer(const View& view, - MemoryResource* resource = _default-resource_); - -template -buffer(const View&) - -> buffer<_deduce-encoding_>; ----- - -Use the contiguous range `[view.data(), view.data() + view.size())` as input. -Its character type must be the primary or secondary character type of the {{% encoding %}}. -It uses `resource` for memory allocation. -CTAD can be used to deduce the encoding from the character type. - -=== Builder - -{{% interface %}} ----- -class buffer::builder -{ -public: - explicit builder(std::size_t size, - MemoryResource* resource = _default-resource_); - - char_type* data() const noexcept; - std::size_t size() const noexcept; - - buffer finish() && noexcept; -}; ----- - -[.lead] -Write the buffer contents incrementally. - -The constructor allocates memory for `size` code units using `resource`, but does not initialize them. -Content can then be written into the memory range `[data(), data() + size())`. -Once everything has been initialized, `finish()` returns the finalized (and from now on immutable) buffer. - -[#make_buffer_from_raw] -== Function `lexy::make_buffer_from_raw` - -{{% interface %}} ----- -namespace lexy -{ - template <_encoding_ Encoding, encoding_endianness Endianness> - struct _make-buffer-from-raw_ - { - auto operator()(const void* memory, std::size_t size) const - -> buffer; - - template - auto operator()(const void* memory, std::size_t size, - MemoryResource* resource) const - -> buffer; - }; - - template <_encoding_ Encoding, encoding_endianness Endianness> - constexpr auto make_buffer_from_raw = _make-buffer-from-raw_{}; -} ----- - -[.lead] -Create a buffer from raw memory, handling endianness conversion if necessary. - -It returns a buffer object that contains the input of the range `[memory, memory + size)`, allocated using `resource`, -but reinterpreted as code units of the specified {{% encoding %}} and in the specified {{% docref "lexy::encoding_endianness" %}}: - -* If `Endianness` is `lexy::encoding_endianness::little`/`lexy::encoding_endianness::big`, - it will reinterpret the memory as an array of code units of `Encoding`, performing a byte swap if necessary. - For single byte encodings, this doesn't do anything special. -* If `Endianness` is `lexy::encoding_endianness::bom`, - `Encoding` must be UTF-8, UTF-16, or UTF-32. - It will skip an optional BOM to determine the endianness, defaulting to big, if none was specified. - Then behaves like the other overload. - -{{% godbolt-example "make_buffer" "Treat a memory mapped file as little endian UTF-16" %}} - -[#typedefs] -== Convenience typedefs - -{{% interface %}} ----- -namespace lexy -{ - template <_encoding_ Encoding = default_encoding, - typename MemoryResource = _default-resource_> - using buffer_lexeme = lexeme_for>; - - template - using buffer_error = error_for, Tag>; - - template - using buffer_error_context = error_context>; -} ----- - -[.lead] -Convenience typedefs for buffer. - diff --git a/assembler/ext/src/lexy/docs/content/reference/input/file.adoc b/assembler/ext/src/lexy/docs/content/reference/input/file.adoc deleted file mode 100644 index e5cfc85c40..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/input/file.adoc +++ /dev/null @@ -1,135 +0,0 @@ ---- -header: "lexy/input/file.hpp" -entities: - "lexy::file_error": read_file_result - "lexy::read_file_result": read_file_result - "lexy::read_file": read_file - "lexy::read_stdin": read_stdin ---- -:toc: left -:experimental: - -[.lead] -Read from files or stdin. - -[#read_file_result] -== Class `lexy::read_file_result` - -{{% interface %}} ----- -namespace lexy -{ - enum class file_error - { - os_error, - file_not_found, - permission_denied, - }; - - template - class read_file_result - { - public: - using encoding = Encoding; - using char_type = typename encoding::char_type; - - explicit operator bool() const noexcept; - - file_error error() const noexcept; - - const lexy::buffer& buffer() const& noexcept; - lexy::buffer&& buffer() && noexcept; - }; - -} ----- - -[.lead] -The result of reading a file or from stdin. - -It is a union of the error code `lexy::file_error` and {{% docref "lexy::buffer" %}}: - -* If it contains an error code, `operator bool()` returns `false`, `error()` returns the error code, - and `buffer()`. -* If it contains a buffer, `operator bool()` returns `true`, `buffer()` returns the buffer, - and `error()` must not be called. - -[#read_file] -== Input `lexy::read_file` - -{{% interface %}} ----- -namespace lexy -{ - template <_encoding_ Encoding = default_encoding, - encoding_endianness Endian = encoding_endianness::bom, - typename MemoryResource> - auto read_file(const char* path, - MemoryResource* resource = _default-resource_) - -> read_file_result; -} ----- - -[.lead] -The function `read_file` reads the contents of the file and makes it available as an input. - -`read_file` tries to read the file at `path` into a buffer whose memory is allocated using the specified `resource` -and whose contents are interpreted as code units of the {{% encoding %}} `Encoding` with the specified {{% docref "lexy::encoding_endianness" %}}, -as if {{% docref "lexy::make_buffer_from_raw" %}} is used. -If this is successful, the returned {{% docref "lexy::read_file_result" %}} will contain the {{% docref "lexy::buffer" %}}. - -Otherwise, it will contain a {{% docref "lexy::file_error" %}}: - -* `file_error::file_not_found` if the `path` did not resolve to a file, -* `file_error::permission_denied` if the `path` resolved to a file that cannot be read by the process, -* or `file_error::os_error` if any other error occurred. - -.Read UTF-32 from a file with a BOM. -==== -[source,cpp] ----- -// Read the file encoded in UTF-32. -auto file = lexy::read_file("input.txt"); -if (!file) - throw my_file_read_error_exception(result.error()); - -// Use the file's buffer as input. -auto result = lexy::match(file.buffer()); -… ----- -==== - -[#read_stdin] -== Input `lexy::read_stdin` - -{{% interface %}} ----- -namespace lexy -{ - template <_encoding_ Encoding = default_encoding, - encoding_endianness Endian = encoding_endianness::bom, - typename MemoryResource> - auto read_stdin(MemoryResource* resource = _default-resource_) - -> read_file_result; -} ----- - -[.lead] -The function `read_stdin` eagerly reads `stdin` and makes it available as an input. - -It will repeatedly read data from `stdin`, until EOF is reached. -If `stdin` is a terminal, this will prompt the user for input until they've closed `stdin` by typing kbd:[Ctrl+D] on Linux or kbd:[Ctrl+Z] on Windows. - -The read data is interpreted as code units of the {{% encoding %}} `Encoding` with the specified {{% docref "lexy::encoding_endianness" %}}, -as if {{% docref "lexy::make_buffer_from_raw" %}} is used. -If this is successful, the returned {{% docref "lexy::read_file_result" %}} will contain the {{% docref "lexy::buffer" %}}, -whose memory is allocated using the given `resource`. - -Otherwise, it will contain a {{% docref "lexy::file_error" %}}. -The only error code used is `file_error::os_error`, if reading has failed. - -CAUTION: After a call to `read_stdin`, all further reads from `stdin` will fail. - -NOTE: If `stdin` is a terminal, `Encoding` and `Endian` must match the encoding used by the terminal. - diff --git a/assembler/ext/src/lexy/docs/content/reference/input/lexeme_input.adoc b/assembler/ext/src/lexy/docs/content/reference/input/lexeme_input.adoc deleted file mode 100644 index 064bf83b6e..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/input/lexeme_input.adoc +++ /dev/null @@ -1,52 +0,0 @@ ---- -header: "lexy/input/lexeme_input.hpp" -entities: - "lexy::lexeme_input": lexeme_input ---- - -[#lexeme_input] -== Input `lexy::lexeme_input` - -{{% interface %}} ----- -namespace lexy -{ - template <_input_ auto ParentInput> - class lexeme_input - { - using _lexeme-type_ = lexeme_for; - - public: - using encoding = typename _lexeme-type_::encoding; - using char_type = typename _lexeme-type_::char_type; - using iterator = typename _lexeme-type_::iterator; - - //=== constructor ===// - explicit lexeme_input(const ParentInput& input, _lexeme-type_ lexeme); - - explicit lexeme_input(const ParentInput& input, iterator begin, iterator end); - - //=== access ===// - const ParentInput& parent_input() const; - _lexeme-type_ lexeme() const; - - //=== input ===// - _reader_ auto reader() const& noexcept; - }; -} ----- - -[.lead] -The class `lexy::lexeme_input` uses a {{% docref "lexy::lexeme" %}} as the input. - -A lexeme is a subset of an existing input, the parent input, which must be provided as well. -If the parent input is a view-like input (e.g. {{% docref "lexy::string_input" %}} or {{% docref "lexy::range_input" %}}, -it stores a copy. -Otherwise, if the parent input owns the input (e.g. {{% docref "lexy::buffer" %}}), it stores a pointer to the parent input. - -If an error is generated on a lexeme input, {{% docref "lexy::error_context" %}} will return the parent input. -That way, any calls to {{% docref "lexy::get_input_location" %}} will result in the correct line/column information for the entire input, -and don't start at the partial input. - -TIP: Use `lexy::lexeme_input` if the input is parsed in multiple passes. - diff --git a/assembler/ext/src/lexy/docs/content/reference/input/range_input.adoc b/assembler/ext/src/lexy/docs/content/reference/input/range_input.adoc deleted file mode 100644 index e579420cac..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/input/range_input.adoc +++ /dev/null @@ -1,55 +0,0 @@ ---- -header: "lexy/input/range_input.hpp" -entities: - "lexy::range_input": range_input ---- - -[#range_input] -== Input `lexy::range_input` - -{{% interface %}} ----- -namespace lexy -{ - template <_encoding_ Encoding, - typename Iterator, typename Sentinel = Iterator> - class range_input - requires std::forward_iterator - && std::sentinel_for - { - public: - using encoding = Encoding; - using char_type = typename encoding::char_type; - - using iterator = Iterator; - using sentinel = Sentinel; - - //=== constructors ===// - constexpr range_input() noexcept; - constexpr range_input(iterator begin, sentinel end) noexcept; - - //=== access ===// - constexpr iterator begin() const noexcept; - constexpr iterator end() const noexcept; - - constexpr _reader_ auto reader() const& noexcept; - }; - - template - range_input(Iterator begin, Sentinel end) - -> range_input<_deduce-encoding_, Iterator, Sentinel>; -} ----- - -[.lead] -The class `range_input` uses the forward range `[begin, end)` as input. - -It is a lightweight view and does not own any data. -If no template arguments are specified, CTAD is used to deduce the encoding from the value type of the iterator. - -{{% godbolt-example "range_input" "Use a `std::list` as input" %}} - -TIP: If the iterators are pointers, use {{% docref "lexy::string_input" %}} instead. - -TIP: If you're parsing a subset of an input, use `lexy::lexeme_input` instead. - diff --git a/assembler/ext/src/lexy/docs/content/reference/input/string_input.adoc b/assembler/ext/src/lexy/docs/content/reference/input/string_input.adoc deleted file mode 100644 index d6ee2941a2..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/input/string_input.adoc +++ /dev/null @@ -1,145 +0,0 @@ ---- -header: "lexy/input/string_input.hpp" -entities: - "lexy::string_input": string_input - "lexy::zstring_input": zstring_input - "lexy::string_lexeme": typedefs - "lexy::string_error": typedefs - "lexy::string_error_context": typedefs ---- -:toc: left - -[.lead] -Inputs that read a string. - -[#string_input] -== Input `lexy::string_input` - -{{% interface %}} ----- -namespace lexy -{ - template <_encoding_ Encoding = default_encoding> - class string_input - { - public: - using encoding = Encoding; - using char_type = typename encoding::char_type; - - //=== constructors ===// - constexpr string_input() noexcept; - - template - constexpr string_input(const CharT* data, std::size_t size) noexcept; - template - constexpr string_input(const CharT* begin, const CharT* end) noexcept; - template - constexpr explicit string_input(const View& view) noexcept; - - //=== access ===// - constexpr const char_type* data() const noexcept; - constexpr std::size_t size() const noexcept; - - constexpr _reader_ auto reader() const& noexcept; - }; -} ----- - -[.lead] -The class `string_input` uses a string as input. - -It is a lightweight view and does not own any of the data. -Use {{% docref "lexy::buffer" %}} if you need to own the contents of the string. - -{{% godbolt-example "string_input" "Use a byte array as input" %}} - -=== Pointer constructors - -{{% interface %}} ----- -template -constexpr string_input(const CharT* data, std::size_t size) noexcept; <1> -template -constexpr string_input(const CharT* begin, const CharT* end) noexcept; <2> - -template -string_input(const CharT* data, std::size_t size) - -> string_input>; -template -string_input(const CharT* begin, const CharT* end) - -> string_input>; ----- -<1> Use the contiguous range `[data, data + size)` as input. -<2> Use the contiguous range `[begin, end)` as input. - -`CharT` must be the primary or secondary character type of the {{% encoding %}}. -CTAD can be used to deduce the encoding from the character type. - -=== View constructor - -{{% interface %}} ----- -template - requires requires (View view) { - view.data(); - view.size(); - } -constexpr explicit string_input(const View& view) noexcept; - -template -string_input(const View&) - -> string_input<_deduce-encoding_>; ----- - -Use the contiguous range `[view.data(), view.data() + view.size())` as input. -Its character type must be the primary or secondary character type of the {{% encoding %}}. -CTAD can be used to deduce the encoding from the character type. - -[#zstring_input] -== Input `lexy::zstring_input` - -{{% interface %}} ----- -namespace lexy -{ - template <_encoding_ Encoding, typename CharT> - constexpr auto zstring_input(const CharT* str) noexcept - -> string_input; - - template - constexpr auto zstring_input(const CharT* str) noexcept - -> string_input>; -} ----- - -[.lead] -The function `zstring_input` uses a null-terminated string as input. - -It returns the {{% docref "lexy::string_input" %}} for the range `[str, str + std::strlen(str))`. -The second overload deduces the {{% encoding %}} from the character type. - -{{% godbolt-example "zstring_input" "Use a string literal as input" %}} - -TIP: This input is useful for testing your grammar. - -[#typedefs] -== Convenience typedefs - -{{% interface %}} ----- -namespace lexy -{ - template <_encoding_ Encoding = default_encoding> - using string_lexeme = lexeme_for>; - - template - using string_error = error_for, Tag>; - - template - using string_error_context = error_context>; -} ----- - -[.lead] -Convenience typedefs for string inputs. - diff --git a/assembler/ext/src/lexy/docs/content/reference/input_location.adoc b/assembler/ext/src/lexy/docs/content/reference/input_location.adoc deleted file mode 100644 index 78b698154c..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/input_location.adoc +++ /dev/null @@ -1,189 +0,0 @@ ---- -header: "lexy/input_location.hpp" -entities: - "lexy::input_location": input_location - "lexy::input_location_anchor": get_input_location - "lexy::get_input_location": get_input_location - "lexy::code_unit_location_counting": counting - "lexy::code_point_location_counting": counting - "lexy::byte_location_counting": counting - "lexy::input_line_annotation": input_line_annotation - "lexy::get_input_line_annotation": input_line_annotation ---- -:toc: left - -[.lead] -Converts a position (iterator) into a human readable location (line/column number). - -[#input_location] -== Class `lexy::input_location` - -{{% interface %}} ----- -namespace lexy -{ - template <_input_ Input, typename Counting = _see-below_> - class input_location - { - public: - constexpr input_location_anchor anchor() const; - - constexpr unsigned line_nr() const; - constexpr unsigned column_nr() const; - - constexpr auto position() const - -> lexy::input_reader::iterator; - - // operator==, operator!=, operator<, operator<=, operator>=, operator> - }; -} ----- - -[.lead] -A human readable location in the input. - -It combines the iterator based position with line/column number, according to some `Counting` strategy. -The `Counting` strategy defaults to {{% docref "lexy::code_unit_location_counting" %}} for text and {{% docref "lexy::byte_location_counting" %}} for bytes. - -`anchor()` returns the latest anchor before that location to start the search. - -NOTE: Use {{% docref "lexy::get_input_location" %}} to create location objects. - -[#get_input_location] -== Function `lexy::get_input_location` - -{{% interface %}} ----- -namespace lexy -{ - template <_input_ Input> - class input_location_anchor - { - public: - // Anchor to the beginning. - constexpr explicit input_location_anchor(const Input& input); - }; - - template - constexpr auto get_input_location(const _input_ auto& input, - lexy::input_reader<_input_>::iterator position, - input_location_anchor<_input_> anchor = _see-below_) - -> input_location; -} ----- - -[.lead] -Gets the {{% docref "lexy::input_location" %}} for a position. - -This is a linear search over the input that starts at the `anchor`. -If none is provided, it starts at the beginning. -As an optimization, pass an anchor of an existing location that is before `position`. - -The result will be the location for the position as determined by the `Counting` strategy. -The `Counting` strategy defaults to {{% docref "lexy::code_unit_location_counting" %}} for text and {{% docref "lexy::byte_location_counting" %}} for bytes. -Calling `position()` on the resulting location will be the beginning of the last column before `position`. - -NOTE: If `position` points inside a `\r\n` sequence, for example, the resulting `position()` will point to the initial `\r`. - -[#counting] -== Counting strategies `lexy::{zwsp}code{zwsp}_unit{zwsp}_location{zwsp}_counting`, `lexy::{zwsp}code{zwsp}_point{zwsp}_location{zwsp}_counting`, `lexy::{zwsp}byte{zwsp}_location{zwsp}_counting` - -{{% interface %}} ----- -namespace lexy -{ - struct code_unit_location_counting {}; - struct code_point_location_counting {}; - - template - struct byte_location_counting {}; -} ----- - -[.lead] -Strategies for counting column and line numbers. - -`code_unit_location_counting`:: - Increments the column for every code unit; increments the line for every {{% docref "lexy::dsl::newline" %}}. - For example, UTF-8 encoded `"abä"` is a single line with four columns (two for each code unit of `ä`). - This is the default for text. -`code_point_location_counting`:: - Increments the column for every {{% docref "lexy::dsl::code_point" %}}; increments the line for every {{% docref "lexy::dsl::newline" %}}. - For example, UTF-8 encoded `"abä"` is a single line with three columns. -`byte_location_counting`:: - Increments the column for every byte (requires {{% docref "lexy::byte_encoding" %}}); increments the line for every `LineWidth` bytes. - This is the default for byte input. - -See https://www.foonathan.net/2021/02/column/[my blog post] for an in-depth discussion about the choice of column units. - -[#input_line_annotation] -== Function `lexy::get_input_line_annotation` - -{{% interface %}} ----- -namespace lexy -{ - template <_input_ Input> - struct input_line_annotation - { - lexy::lexeme_for before; - lexy::lexeme_for annotated; - lexy::lexeme_for after; - - bool truncated_multiline; - bool rounded_end; - }; - - template <_input_ Input, typename Counting> - constexpr auto get_input_line_annotation(const Input& input, - const input_location& begin_location, - lexy::input_reader::iterator end) - -> input_line_annotation; - - template - constexpr auto get_input_line_annotation(const Input& input, - const input_location& location, - std::size_t size) - -> input_line_annotation; - { - auto end = std::next(location.position(), size); - return get_input_line_annotation(input, location, end); - } -} ----- - -[.lead] -Computes the part of the input referenced by a `[begin_location.position(), end)` with surrounding input. - -The result is an object of type `input_line_annotation` with the following values: - -`before`:: - A {{% docref "lexy::lexeme" %}} for the range `[line_begin, begin_location.position())`, - where `line_begin` is the beginning of the line of `begin_location`, as determined by `Counting`. - -`annotated`:: - A {{% docref "lexy::lexeme" %}} for the range `[begin_location.position(), modified_end)`. - If `begin_location.position() == end`, `modified_end` is an incremented `end`: - - * If `end` points to the beginning or inside of the newline, as determined by `Counting`, - it is set to the end of the newline. - * Otherwise, it is set to the end of the current code point. - -+ -If `end` is on a different line then `begin_location`, `modified_end` is the end of the newline, as determined by `Counting`. -Otherwise, `modified_end` is the end of the code point `end` points or multi character newline. - -`after`:: - A {{% docref "lexy::lexeme" %}} for the range `[modified_end, line_end)`, - where `line_end` is either the position of the newline or the end of the newline to ensure `modified_end <= line_end`, - as determined by `Counting`. - -`truncated_multiline`:: - `true` if `end` was on a different line than `begin_location`, `false` otherwise. -`rounded_end`:: - `true` if `end` points inside a code point and needed to be adjusted. - -TIP: Use this function for error message generation. -Use {{% docref "lexy::visualize" %}} to print `before`, `annotated`, `after`; -and {{% docref "lexy::visualization_display_width" %}} to compute the indent below `before` and the number of underline characters for `annotated`. - diff --git a/assembler/ext/src/lexy/docs/content/reference/lexeme.adoc b/assembler/ext/src/lexy/docs/content/reference/lexeme.adoc deleted file mode 100644 index 32cdd57713..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/lexeme.adoc +++ /dev/null @@ -1,82 +0,0 @@ ---- -header: "lexy/lexeme.hpp" -entities: - "lexy::lexeme": lexeme - "lexy::lexeme_for": lexeme ---- -:toc: left - -[#lexeme] -== Class `lexy::lexeme` - -{{% interface %}} ----- -namespace lexy -{ - template <_reader_ Reader> - class lexeme - { - public: - using encoding = typename Reader::encoding; - using char_type = typename encoding::char_type; - using iterator = typename Reader::iterator; - - //=== constructors ===// - constexpr lexeme() noexcept; - constexpr lexeme(iterator begin, iterator end) noexcept; - constexpr lexeme(iterator pos, std::size_t size) noexcept; - constexpr explicit lexeme(const Reader& reader, iterator begin) noexcept; - - //=== access ===// - constexpr bool empty() const noexcept; - - constexpr iterator begin() const noexcept; - constexpr iterator end() const noexcept; - - //=== iterator-specific access ===// - constexpr const char_type* data() const noexcept; - constexpr std::size_t size() const noexcept; - constexpr char_type operator[](std::size_t idx) const noexcept; - }; - - template <_input_ Input> - using lexeme_for = lexeme>; -} ----- - -[.lead] -The class `lexeme` represents a sub-range of the input. - -It is a lightweight, non-owning type. -It is templated on the reader of an input, which minimizes code bloat. -The alias `lexeme_for` instantiates the `lexeme` with the reader type of an input. - -=== Constructors - -{{% interface %}} ----- -constexpr lexeme() noexcept; <1> -constexpr lexeme(iterator begin, iterator end) noexcept; <2> - constexpr lexeme(iterator pos, std::size_t size) noexcept; <3> -constexpr explicit lexeme(const Reader& reader, iterator begin) noexcept; <4> ----- -<1> Creates a lexeme for the empty range. -<2> Creates a lexeme for the range `[begin, end)`. -<3> Creates a lexeme for the range `[pos, pos + size)` (even for forward iterators). -<4> Creates a lexeme for the range `[begin, reader.cur())`, i.e. from `begin` until the current position of the reader. - -=== Iterator-specific access - -{{% interface %}} ----- -constexpr const char_type* data() const noexcept; <1> -constexpr std::size_t size() const noexcept; <2> -constexpr char_type operator[](std::size_t idx) const noexcept; <3> ----- -<1> Returns a pointer to the first code unit of the range. - Requires that the iterator type is a pointer. -<2> Returns the size of the range. - Requires that the iterator type has an `operator-`. -<3> Returns the code unit at the specific index. - Requires that the iterator is a random access iterator. - diff --git a/assembler/ext/src/lexy/docs/content/reference/parse_tree.adoc b/assembler/ext/src/lexy/docs/content/reference/parse_tree.adoc deleted file mode 100644 index 7cbb664ae4..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/parse_tree.adoc +++ /dev/null @@ -1,504 +0,0 @@ ---- -header: "lexy/parse_tree.hpp" -entities: - "lexy::parse_tree": parse_tree - "lexy::parse_tree::builder": builder - "lexy::parse_tree::node_kind": node_kind - "lexy::parse_tree::node": node - "lexy::parse_tree_for": parse_tree ---- -:toc: left - -[#parse_tree] -== Class `lexy::parse_tree` - -{{% interface %}} ----- -namespace lexy -{ - template <_reader_ Reader, typename TokenKind = void, - typename MemoryResource = _default-resource_> - class parse_tree - { - public: - //=== construction ===// - class builder; - - constexpr parse_tree(); - constexpr explicit parse_tree(MemoryResource* resource); - - parse_tree(const parse_tree&) = delete; - parse_tree& operator=(const parse_tree&) = delete; - - parse_tree(parse_tree&&); - parse_tree& operator=(parse_tree&&); - - //=== container interface ===// - bool empty() const noexcept; - - std::size_t size() const noexcept; - std::size_t depth() const noexcept; - - void clear() noexcept; - - //=== nodes ===// - class node; - class node_kind; - - node root() const noexcept; - - //=== traversal ===// - class traverse_range; - - traverse_range traverse(node n) const noexcept; - traverse_range traverse() const noexcept; - }; - - template <_input_ Input, typename TokenKind = void, - typename MemoryResource = _default-resource_> - using parse_tree_for - = lexy::parse_tree, TokenKind, MemoryResource>; -} ----- - -[.lead] -A lossless, untyped, immutable parse tree. - -It is an ordered, rooted tree that represents the structure of the parsed inputs. -It has two kinds of nodes: token nodes and production nodes. -Token nodes represent individual tokens of the input: -they store the {{% docref "lexy::lexeme" %}} and the {{% docref "lexy::token_kind" %}} and do not have children. -Production nodes represent productions of the input: -they are identified by the {{% docref "lexy::production_name" %}} and have zero or more child nodes for the tokens and child productions of the production. -The root node of a non-empty tree is always the production node for the top-level production of the grammar. - -The tree is parametrized on the `Reader`, which determines the type of {{% docref "lexy::lexeme" %}} stored by token nodes, -and the `TokenKind` of {{% docref "lexy::token_kind" %}}. -The latter is `void` by default, which means integers are used to identify tokens. - -The tree is immutable: once constructed, the nodes cannot be modified in any way; -changing a tree is only possible by re-assigning it. -It is not copyable, but moveable. - -All memory allocation for the tree is done via a `MemoryResource` object, -which must be a class with the same interface as `std::pmr::memory_resource`. -By default, it uses `new` and `delete`. -The memory resource object passed to the constructor does not propagate during copy/move/swap. - -Internally, the nodes of the tree are stored in big chunks of continuous memory. -Each node has the size of three pointers and they form a linked list. - -TIP: Use {{% docref "lexy::parse_as_tree" %}} to build a parse tree for an input. - -CAUTION: The parse tree does not own the contents of token nodes, so make sure the input stays alive as long as the tree does. - -=== Construction: Constructors - -{{% interface %}} ----- -constexpr parse_tree(); -constexpr explicit parse_tree(MemoryResource* resource); ----- - -[.lead] -Construct an empty parse tree without any nodes. - -The default constructor is only valid for the _`default-resource`_ and uses the default resource for memory allocation. -The second overload assigns the specified `resource`, which is not changed by further assignment. - -[#builder] -=== Construction: `lexy::{zwsp}parse{zwsp}_tree::{zwsp}builder` - -{{% interface %}} ----- -class parse_tree::builder -{ - using _iterator_ = typename Reader::iterator; - -public: - struct marker - { - marker(); - }; - - //=== root node ===// - explicit builder(parse_tree&& tree, _production_ auto root); - explicit builder(_production_ auto root) - : builder(parse_tree{}, root) - {} - - parse_tree&& finish() &&; - - //=== production node ===// - marker start_production(_production_ auto production); - - void finish_production(marker&& m); - void cancel_production(marker&& m); - - //=== container node ===// - marker start_container(); - - void set_container_production(_production_ auto production); - - void finish_container(marker&& m); - void cancel_container(marker&& m); - - //=== token node ===// - void token(token_kind kind, _iterator_ begin, _iterator _end); -}; ----- - -[.lead] -Manually builds a non-empty parse tree. - -The constructor can optionally take an existing parse tree, which will be `clear()`ed. -This allows re-using already allocated memory or a custom memory resource. -The root node of the tree will be a production node for the specified `root` production, -which is the active node (see below). - -Then the tree can be built using the following methods: - -`finish`:: - Finishes the construction of the entire tree and returns it. - The active node must be the root node. - -`start_production`:: - Start construction for a new production node for `production` and pushes it to the active node's list of children. - It returns a `marker` object, which must eventually be passed to `finish_production` or `cancel_production`. - The new production node will be the active node. -+ -If `production` is a {{% docref "lexy::transparent_production" %}}, no new node is created. -However, the `marker` object must still be passed to `finish_production` or `cancel_production`. - -`finish_production`:: - Finishes the production node of the corresponding `marker` object, - which must be the active node. - The parent node will become active node again. - -`cancel_production`:: - Cancels construction of the production node of the corresponding `marker` object, - which must be the active node. - The node and all children already added to it will be removed from the parse tree; - it is returned to the same state it had before the corresponding `start_production` call. - -`start_container`:: - Starts a container of more nodes. - This can then later be turned into a production node, if desired. - It returns a `marker` object, which must eventually be passed to `finish_container` or `cancel_container`. - The container will be the active node. - -`set_container_production`:: - If the passed production is transparent, does nothing. - Otherwise, creates a new production node and adds all children from the currently active container to it. - It then creates a new container whose only child is the newly added production node. - The new container will be the active node, everything added to it will become a sibling of the production node. - -`finish_container`:: - Finishes a container of the corresponding `marker` object, which must be the active node. - Adds all child nodes to the parent without adding an intermediate node. - This results in the same tree as if `start_container()` had never been called, and all children just added directly. - The parent node will become active node again. - -`cancel_container`:: - Cancels construction of a container of the corresponding `marker` object, which must be the active node. - All children of the container will be removed from the parse tree; - it is returned to the same state it had before the corresponding `cancel_container` call. - -`token`:: - Construct a new token node and push it to the active node's list of children. - The node will have the specified {{% docref "lexy::token_kind" %}} and the lexeme `[begin, end)` of the input. -+ -If `kind.ignore_if_empty() == true` and `begin == end`, no token node is constructed. - -=== Container interface - -{{% interface %}} ----- -bool empty() const noexcept; <1> - -std::size_t size() const noexcept; <2> -std::size_t depth() const noexcept; <3> - -void clear() noexcept; <4> ----- -<1> Returns `true` if the tree is empty, `false` otherwise. - An empty tree does not have any nodes. -<2> Returns the total number of nodes of the tree, including the root node. -<3> Returns the maximum depth of all nodes in the tree, - which is the number of times you need to call `node.parent()` to reach the root. - The depth of an empty tree is not defined. -<4> Clears the tree by removing all nodes, but without deallocating memory. - -An empty tree has `size() == 0` and undefined `depth()`. -A tree that consists only of the root node has `size() == 1` and `depth() == 0`. -A shallow tree, where all nodes are children of the root node, has `depth() == 1`. -A completely nested tree, where each node has exactly one child, has `depth() == size() - 1`. - -[#node_kind] -=== Nodes: `lexy::{zwsp}parse{zwsp}_tree::{zwsp}node{zwsp}_kind` - -{{% interface %}} ----- -class parse_tree::node_kind -{ -public: - //=== access ===// - bool is_token() const noexcept; - bool is_production() const noexcept; - - bool is_root() const noexcept; - bool is_token_production() const noexcept; - - const char* name() const noexcept; - - //=== comparison ===// - friend bool operator==(node_kind lhs, node_kind rhs); - friend bool operator!=(node_kind lhs, node_kind rhs); - - friend bool operator==(node_kind nk, token_kind tk); - friend bool operator==(token_kind tk, node_kind nk); - friend bool operator!=(node_kind nk, token_kind tk); - friend bool operator!=(token_kind tk, node_kind nk); - - friend bool operator==(node_kind nk, _production_ auto p); - friend bool operator==(_production_ auto p, node_kind nk); - friend bool operator!=(node_kind nk, _production_ auto p); - friend bool operator!=(_production_ auto p, node_kind nk); -}; ----- - -[.lead] -Information about the kind of a node. - -`is_token`:: - `true` if the node is a token node, `false` otherwise. - `is_token() == !is_production()`. -`is_production`:: - `true` if the node is a production node, `false` otherwise. - `is_production() == !is_token()`. -`is_root`:: - `true` if the node is the root node of the tree, `false` otherwise. - The root node is always a production node. -`is_token_production`:: - `true` if the node is a production node that is a {{% docref "lexy::token_production" %}}, `false` otherwise. -`name`:: - For a production node, returns {{% docref "lexy::production_name" %}}. - For a token node, returns `.name()` of its {{% docref "lexy::token_kind" %}}. - -Node kinds can be compared with equality with each other, {{% docref "lexy::token_kind" %}} and productions. -Two node kinds are equal if they are either both token nodes with the same token nodes, or both production nodes for the same production. -A node kind and a token kind is equal, if the node kind is a token node with that kind, -and a node kind and a production is equal, if it is a production node for that production. - -[#node] -=== Nodes: `lexy::{zwsp}parse{zwsp}_tree::{zwsp}node` - -{{% interface %}} ----- -class parse_tree::node -{ -public: - //=== properties ===// - void* address() const noexcept; - - node_kind kind() const noexcept; - - lexy::lexeme lexeme() const noexcept; - lexy::token token() const noexcept; - - //=== relationships ===// - node parent() const noexcept; - - class children_range; - children_range children() const noexcept; - - class sibling_range; - sibling_range siblings() const noexcept; - - bool is_last_child() const noexcept; - - //=== comparison ===// - friend bool operator==(node lhs, node rhs) noexcept; - friend bool operator!=(node lhs, node rhs) noexcept; -}; ----- - -[.lead] -A reference to node in the parse tree. - -Internally, this is just a pointer to the node data structure. - -.Properties: -`address`:: - The address of the referenced node in memory. - It uniquely identifies the node. -`kind`:: - The {{% docref "lexy::parse_tree::node_kind" %}} of the node. -`lexeme`:: - For a token node, returns the {{% docref "lexy::lexeme" %}} of the node. - For a production node, returns an empty lexeme. -`token`:: - Requires that the node is a token node; returns the stored {{% docref "lexy::token" %}} of the node. - -Two node references can be compared for equality, which compares their addresses. - -==== Node relationships: Parent - -{{% interface %}} ----- -node parse_tree::node::parent() const noexcept; ----- - -[.lead] -Returns a reference to its parent node. - -For the root node, which does not have a parent node, returns `*this`. - -This operation is `O(number of siblings)`. - -==== Node relationships: Children - -{{% interface %}} ----- -class parse_tree::node::children_range -{ -public: - class iterator; // value_type = node - - iterator begin() const noexcept; - iterator end() const noexcept; - - bool empty() const noexcept; - std::size_t size() const noexcept; -}; - -children_range parse_tree::node::children() const noexcept; ----- - -[.lead] -A sized range that iterates over all direct children of the referenced node in order. - -For a token node, this is always an empty range. - -==== Node relationships: Siblings - -{{% interface %}} ----- -class parse_tree::node::sibling_range -{ -public: - class iterator; // value_type = node - - iterator begin() const noexcept; - iterator end() const noexcept; -}; - -sibling_range parse_tree::node::siblings() const noexcept; ----- - -[.lead] -A range that iterates over all siblings of the referenced node. - -The siblings of a node are all other child nodes of its parent. -Iteration begins with the child that is following the referenced node and continues until the last child of the parent node. -It then wraps around to the first child and ends when it reaches the referenced node again. -The referenced node is not included; no node is its own sibling. - -For the root node, this is always an empty range. - ---- - -=== Nodes: Root node - -{{% interface %}} ----- -node parse_tree::root() const noexcept; ----- - -[.lead] -A reference to the root node of the tree. - -The tree must not be empty. - -=== Traversal - -{{% interface %}} ----- -namespace lexy -{ - enum class traverse_event - { - enter, - exit, - leaf, - }; -} ----- - -{{% interface %}} ----- -class parse_tree::traverse_range -{ -public: - using event = traverse_event; - class iterator; // struct value_type { traverse_event event; node node; }; - - iterator begin() const noexcept; - iterator end() const noexcept; - - bool empty() const noexcept; -}; - -traverse_range parse_tree::traverse(node n) const noexcept; - -traverse_range parse_tree::traverse() const noexcept; ----- - -[.lead] -A range that traverses all descendants of a node. - -The first overload traverses all descendants of the node `n`, which includes `n` itself. -The second overload traverses all nodes in the parse tree. -For a non-empty tree, it is equivalent to `traverse(root())`. -For an empty tree, it returns the empty range. - -The value type of the traverse range's iterator is a pair of `lexy::traverse_event` and `node`. -The traverse event indicates why a node is visited, and `node` is the reference to the current node. - -For a token node `n`, `traverse(n)` is a one element range whose value is `n` itself with the `traverse_event::leaf`. - -For a production node `n`, `traverse(n)` is at least a two element range. -The first element is `n` itself with the `traverse_event::enter`. -It then recursively traverses all direct children of `n`. -The final element is again `n` with the `traverse_event::exit.` - -.Print a tree -==== -[source,cpp] ----- -auto depth = 0; -for (auto [event, node] : tree.traverse()) -{ - switch (event) - { - case lexy::traverse_event::enter: - ++depth; - indent(depth); - print_node(node); - break; - case lexy::traverse_event::exit: - --depth; - break; - - case lexy::traverse_event::leaf: - indent(depth); - print_node(node); - break; - } -} ----- -==== - -NOTE: Traversing the parse tree is an optimized operation that does not involve dynamic memory allocation or recursion. -Instead, each iteration step simply follows a pointer. - diff --git a/assembler/ext/src/lexy/docs/content/reference/token.adoc b/assembler/ext/src/lexy/docs/content/reference/token.adoc deleted file mode 100644 index 35664bf5f0..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/token.adoc +++ /dev/null @@ -1,318 +0,0 @@ ---- -header: "lexy/token.hpp" -entities: - "lexy::predefined_token_kind": predefined_token_kind - "lexy::token_kind": token_kind - "lexy::token_kind_map": token_kind_map - "lexy::token_kind_map_for": token_kind_map - "lexy::token": token - "lexy::token_for": token ---- -:toc: left - -[.lead] -Identifying and storing tokens of the input. - -[#predefined_token_kind] -== Enum `lexy::predefined_token_kind` - -{{% interface %}} ----- -namespace lexy -{ - enum predefined_token_kind - { - unknown_token_kind, - - error_token_kind, - whitespace_token_kind, - any_token_kind, - - literal_token_kind, - position_token_kind, - eof_token_kind, - - identifier_token_kind, - digits_token_kind, - }; -} ----- - -[.lead] -Predefined token kinds for special token rules, as given in the table below. - -[%collapsible] -.The predefined token kinds -==== -|=== -| Token Kind | Token Rule - -| `lexy::unknown_token_kind` | all token rules by default -| `lexy::error_token_kind` | tokens produced during the "discard input" phase of error recovery, e.g. by {{% docref "lexy::dsl::find" %}} or {{% docref "lexy::dsl::recover" %}} -| `lexy::whitespace_token_kind` | {{% docref "lexy::dsl::whitespace" %}} (not actually a token rule) -| `lexy::any_token_kind` | {{% docref "lexy::dsl::any" %}}, {{% docref "lexy::dsl::code_point" %}} (without predicate), {{% docref "lexy::dsl::until" %}} -| `lexy::literal_token_kind` | {{% docref "lexy::dsl::lit" %}}, {{% docref "lexy::dsl::code_point" %}} (literal version), and other tokens that are fully identified by their spelling -| `lexy::position_token_kind` | {{% docref "lexy::dsl::position" %}} (not actually a token rule) -| `lexy::eof_token_kind` | {{% docref "lexy::dsl::eof" %}} -| `lexy::identifier_token_kind` | {{% docref "lexy::dsl::identifier" %}} and {{% docref "lexy::dsl::symbol" %}} -| `lexy::digits_token_kind` | {{% docref "lexy::dsl::digit" %}}, {{% docref "lexy::dsl::digits" %}}, and other rules parsing digits -|=== -==== - -[#token_kind] -== Class `lexy::token_kind` - -{{% interface %}} ----- -namespace lexy -{ - template - class token_kind - { - using _underlying-type_ - = std::conditional_t, int, TokenKind>; - - public: - //=== constructors ===// - constexpr token_kind() noexcept; - constexpr token_kind(predefined_token_kind value) noexcept; - - constexpr token_kind(_underlying-type_ value) noexcept; - - constexpr token_kind(_token-rule_ auto token_rule) noexcept; - - //== access ===// - constexpr explicit operator bool() const noexcept; - constexpr bool is_predefined() const noexcept; - constexpr bool ignore_if_empty() const noexcept; - - constexpr _underlying-type_ get() const noexcept; - - constexpr const char* name() const noexcept; - - static constexpr std::uint_least16_t to_raw(token_kind kind) noexcept; - static constexpr token_kind from_raw(std::uint_least16_t kind) noexcept; - - friend constexpr bool operator==(token_kind lhs, token_kind rhs) noexcept; - friend constexpr bool operator!=(token_kind lhs, token_kind rhs) noexcept; - }; -} ----- - -[.lead] -Identifies a {{% docref "token-rule" %}}. - -It either stores a `lexy::predefined_token_kind` or a user-defined token kind given by `TokenKind`. -If `TokenKind` is `void` (the default), the assumes a user-defined token type is `int`. -Otherwise, `TokenKind` must be an enumeration type. - -Token rules are associated with their kind using {{% docref ".kind" %}} or by specializing {{% docref "lexy::token_kind_map_for" %}}. -Some token rules that require special behavior in the parse tree have a {{% docref "lexy::predefined_token_kind" %}}. -For all others, the token kind is unknown by default. - -Internally, all values are stored as a `std::uint_least16_t`. - -=== Constructors - -{{% interface %}} ----- -constexpr token_kind() noexcept -: token_kind(lexy::unknown_token_kind) -{} - -constexpr token_kind(predefined_token_kind value) noexcept; ----- - -Initialize with the given {{% docref "lexy::predefined_token_kind" %}}. - -{{% interface %}} ----- -constexpr token_kind(_underlying-type_ value) noexcept; - -template - requires std::is_enum_v -token_kind(T value) -> token_kind; -token_kind(std::integral auto value) -> token_kind; ----- - -Initialize with the given user-defined token kind. -If `TokenKind` is `void`, it accepts an `int`, otherwise `TokenKind` itself. -`value` must fit in a 15bit unsigned integer. - -If CTAD is used and the argument is an integer, deduces `void` for `TokenKind`. -Otherwise, deduces the specified information type. - -{{% interface %}} ----- -constexpr token_kind(_token-rule_ auto token_rule) noexcept; ----- - -Initialize with the token kind of the given {{% token-rule %}}. - -This is determined as follows: - -1. If {{% docref "lexy::token_kind_map_for" %}} instantiated with `TokenKind` contains a token kind for `token_rule`, uses that. -2. Otherwise, if `token_rule` has been assigned a {{% docref "lexy::predefined_token_kind" %}} by lexy, uses that. -3. Otherwise, if `token_rule` has been assigned a user-defined token kind by {{% docref ".kind" %}}, - whose type is compatible, uses that. - If `TokenKind == void`, a user-defined token kind is compatible if it is an integral value; - else, a user-defined token kind is compatible if it has the same enumeration type. -4. Otherwise, uses `lexy::unknown_token_kind`. - -Cases 2 and 3 are subject to the same range restrictions as the constructor that takes a user-defined value directly. - -=== Access - -{{% interface %}} ----- -constexpr explicit operator bool() const noexcept; <1> - -constexpr bool is_predefined() const noexcept; <2> - -constexpr bool ignore_if_empty() const noexcept; <3> ----- -<1> Returns `true` if the token kind is not `lexy::unknown_token_kind`, `false` otherwise. -<2> Returns `true` if the token kind is user-defined (including unknown), `false` otherwise. -<3> Returns `true` if an empty token of that kind should be ignored by {{% docref "lexy::parse_tree" %}} and related, `false` otherwise. - It currently returns `true` for `lexy::unknown_token_kind`, `lexy::error_token_kind`, `lexy::whitespace_token_kind`. - -{{% interface %}} ----- -constexpr _underlying-type_ get() const noexcept; ----- - -Returns the value of the token kind. - -If `TokenKind` is `void`, the return type is `int`. -Otherwise, it is `TokenKind`. - -If the token kind is user-defined, returns its value unchanged. -If the token kind is predefined, returns an implementation defined value. -This value is guaranteed to uniquely identify the predefined token kind and distinguish it from all user-defined token types, -but it must not be passed to the constructor taking a user-defined token kind. - -{{% interface %}} ----- -constexpr const char* name() const noexcept; ----- - -Returns the name of the token kind. - -If the token kind is `lexy::unknown_token_kind`, the name is `"token"`. -If the token kind is some other predefined token kind, the name is a nice version of the enumeration name (e.g. `"EOF"` for `lexy::eof_token_kind`). -If the token kind is user-defined and the ADL call `token_kind_name(get())` resolves to a `const char*`, returns that. -Otherwise, returns `"token"` for user-defined token kinds. - -NOTE: ADL only works if the `TokenKind` is an enumeration and not `void`. - -[#token_kind_map] -== `lexy::token_kind_map` - -{{% interface %}} ----- -namespace lexy -{ - class _token-kind-map_ - { - public: - template - consteval _token-kind-map_ map(_token-rule_ auto token_rule) const; - }; - - constexpr auto token_kind_map = _token-kind-map_(); - - template - constexpr auto token_kind_map_for = token_kind_map; -} ----- - -[.lead] -Defines a compile-time mapping of {{% token-rule %}}s to a user-defined `TokenKind` enum. - -It is initially empty. -A mapping is added by calling `.map()` which associates `TokenKind` with the `token_rule`; -its result is a map that contains this mapping in addition to all previous mappings. -`TokenKind` must always have the same type. - -The mapping is associated with the user-defined `TokenKind` enum by specializing `token_kind_map_for`; -the default specialization is the empty mapping for all token kinds. -This specialization is used by the {{% docref "lexy::token_kind" %}} constructor that takes a token rule. - -{{% godbolt-example "token_kind_map" "Associate custom token kinds with the default playground example" %}} - -CAUTION: Token rules are identified based on type. -If two token rules are equivalent but have different types, they're token kind is not going to be picked up. - -TIP: It is usually better to specify the token kind inline in the grammar using {{% docref ".kind" %}}. - -[#token] -== Class `lexy::token` - -{{% interface %}} ----- -namespace lexy -{ - template <_reader_ Reader, typename TokenKind = void> - class token - { - public: - using encoding = typename Reader::encoding; - using char_type = typename encoding::char_type; - using iterator = typename Reader::iterator; - - //=== constructors ===// - explicit constexpr token(token_kind kind, - lexy::lexeme lexeme) noexcept; - explicit constexpr token(token_kind kind, - iterator begin, iterator end) noexcept; - - //=== access ===// - constexpr token_kind kind() const noexcept; - constexpr lexy::lexeme lexeme() const noexcept; - - constexpr const char* name() const noexcept - { - return kind().name(); - } - - constexpr iterator position() const noexcept - { - return lexeme().begin(); - } - }; - - template <_input_ Input, typename TokenKind = void> - using token_for = token, TokenKind>; -} ----- - -[.lead] -Stores a token as a pair of {{% docref "lexy::token_kind" %}} and {{% docref "lexy::lexeme" %}}. - -A _token_ is not to be confused with a {{% token-rule %}}: -the latter describes what sort of input constitutes a token (e.g. a sequence of decimal digits or the keyword `int`), -while the former is the concrete realization of the rule (e.g. the number `123` at offset 10, or the keyword `int` at offset 23). - -=== Constructors - -{{% interface %}} ----- -explicit constexpr token(token_kind kind, - lexy::lexeme lexeme) noexcept; -explicit constexpr token(token_kind kind, - iterator begin, iterator end) noexcept; - -template -token(token_kind, lexy::lexeme) -> token; -template - requires std::is_enum_v -token(T kind, lexy::lexeme) -> token; -template -token(std::integral auto kind, lexy::lexeme) -> token; ----- - -[.lead] -Constructs the token from `kind` and `lexeme`. - -If CTAD is used, the arguments can be deduced for the first overload. - diff --git a/assembler/ext/src/lexy/docs/content/reference/visualize.adoc b/assembler/ext/src/lexy/docs/content/reference/visualize.adoc deleted file mode 100644 index 0b6f97fb6f..0000000000 --- a/assembler/ext/src/lexy/docs/content/reference/visualize.adoc +++ /dev/null @@ -1,201 +0,0 @@ ---- -header: "lexy/visualize.hpp" -entities: - "lexy::visualization_flags": visualization_flags - "lexy::visualization_options": visualization_options - "lexy::visualize_to": visualize_to - "lexy::cfile_output_iterator": visualize - "lexy::visualize": visualize - "lexy::visualization_display_width": visualization_display_width ---- -:toc: left - -[.lead] -Functions to visualize lexy's data structures for debugging purposes. - -[#visualization_flags] -== Enum bit flags `lexy::visualization_flags` - -{{% interface %}} ----- -namespace lexy -{ - enum visualization_flags - { - visualize_default, - - visualize_use_unicode, - visualize_use_color, - visualize_use_symbols, - - visualize_fancy - = visualize_use_unicode | visualize_use_color | visualize_use_symbols, - - visualize_space, - }; - - constexpr visualization_flags operator|(visualization_flags lhs, - visualization_flags rhs) noexcept; -} ----- - -[.lead] -Flags for controlling the visualization. - -`visualize_default`:: - The default behavior; no flag is set. -`visualize_use_unicode`:: - Visualization can use Unicode characters for meta data (e.g. the box drawing characters for the parse tree); - non-ASCII characters in the content are still escaped. - It will write UTF-8 encoded code points. -`visualize_use_color`:: - Visualization can use the ANSI escape codes to add color. -`visualize_use_symbols`:: - Visualization can use Unicode symbols for e.g. newline and tab characters, - which will be written as UTF-8 encoded code points. - It is separate from `visualize_use_unicode`. -`visualize_fancy`:: - Enable Unicode, color, and symbols. -`visualize_space`:: - Visualization will display space as a visible symbol instead of the literal space character. - Useful to indicate trailing spaces; best combined with `visualize_use_symbols`. - -NOTE: Use `visualize_fancy` for visualizing to modern terminals; -use `visualize_use_unicode | visualize_use_symbols` for visualizing to a file. - -[#visualization_options] -== Struct `lexy::visualization_options` - -{{% interface %}} ----- -namespace lexy -{ - struct visualization_options - { - static constexpr unsigned char max_tree_depth_limit = 32; - - visualization_flags flags = visualize_default; - - unsigned char max_tree_depth = max_tree_depth_limit; - unsigned char max_lexeme_width = 0; - unsigned char tab_width = 0; - - constexpr bool is_set(visualization_flags f) const noexcept; - - constexpr auto reset(visualization_flags f) const noexcept - -> visualization_options; - }; - - constexpr visualization_options operator|(visualization_options lhs, - visualization_flags rhs) noexcept; -} ----- - -[.lead] -Options for controlling visualization. - -It combines the {{% docref `lexy::visualization_flags` %}} with other options. - -`max_tree_depth`:: - When visualizing a {{% docref "lexy::parse_tree" %}}, stop visualization at this depth. - Child nodes whose depth exceeds `max_tree_depth` are omitted, which is indicated by a symbol. - It must be `<= max_tree_depth_limit`. -`max_lexeme_width`:: - When visualizing a {{% docref "lexy::lexeme" %}}, stop visualization after this many "characters". - Here a "character" depends on the encoding, e.g. for text based encodings, it is code points. - If it is `0`, an unlimited amount of characters is printed. -`tab_width`:: - How many spaces are printed for a tab character. - If it is `0`, tabs are printed as escaped control characters (e.g. `\t`). - -[#visualize_to] -== Function `lexy::visualize_to` - -{{% interface %}} ----- -namespace lexy -{ - template OutputIt> - OutputIt visualize_to(OutputIt out, code_point cp, - visualization_options opts = {}); <1> - - template OutputIt, _reader_ Reader> - OutputIt visualize_to(OutputIt out, lexeme lexeme, - visualization_options opts = {}); <2> - - template OutputIt, - _reader_ Reader, typename TokenKind, typename MemoryResource> - OutputIt visualize_to(OutputIt out, - const parse_tree& tree, - visualization_options opts = {}); <3> -} ----- - -<1> Visualize a {{% docref "lexy::code_point" %}}. -<2> Visualize a {{% docref "lexy::lexeme" %}} by visualizing the individual code points. -<3> Visualize a {{% docref "lexy::parse_tree" %}} by visualizing each node. - -[.lead] -Visualize a data structure by writing it to `out` using the {{% docref "lexy::visualization_options" %}}. - -The format is designed to be human-readable only; it is not documented exactly and subject to change. -By default, it writes ASCII characters only. -If `opts` has set the flags `visualize_use_unicode` or `visualize_use_symbols` sets, it can also write UTF-8 encoded code points. - -To visualize a code point, it writes it directly if it is a printable ASCII character, -and otherwise writes its code point value or another escape sequence. -Non-ASCII or control code points are never written directly for clarity in debugging. - -Visualization of a lexeme depends on the {{% encoding %}}. -For the text-based encodings it writes the individual code points. -For {{% docref "lexy::byte_encoding" %}}, it writes the bytes as hexadecimal. - -To visualize a parse tree, it visualizes each node in a tree format. -The maximal depth can be controlled by the options. - -NOTE: Use {{% docref "lexy::trace" %}} to visualize the parsing process itself. - -[#visualize] -== Function `lexy::visualize` - -{{% interface %}} ----- -namespace lexy -{ - struct cfile_output_iterator; - - template - void visualize(std::FILE* file, const T& obj, - visualization_options opts = {}) - { - visualize_to(cfile_output_iterator{file}, obj, opts); - } -} ----- - -[.lead] -Visualizes a data structure by writing it to `file`. - -It uses `cfile_output_iterator`, which is an output iterator that repeatedly calls `std::fputc`, and then forwards to {{% docref "lexy::visualize_to" %}}. - -{{% godbolt-example "visualize" "Visualize a `lexy::parse_tree`" %}} - -[#visualization_display_width] -== Function `lexy::visualization_display_width` - -{{% interface %}} ----- -namespace lexy -{ - template - std::size_t visualization_display_width(const T& obj, - visualization_options opts = {}); -} ----- - -[.lead] -Computes the display width for visualizing `obj` using `opts`, which is the number of Unicode code points. - -As the only non-ASCII Unicode characters are carefully chosen to occupy one display cell in a monospace font, -this is the number of characters necessary to underline the visualization result or indent past it. - diff --git a/assembler/ext/src/lexy/docs/layouts/_default/baseof.html b/assembler/ext/src/lexy/docs/layouts/_default/baseof.html deleted file mode 100644 index e8b563847f..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/_default/baseof.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - {{- block "title" . -}} - {{ if .IsHome }} - {{ .Site.Title }}: {{ .Site.Params.tagline }} - {{ else }} - {{ .Title }} — {{ .Site.Title }} - {{ end }} - {{- end -}} - - - {{ $style := resources.Get "css/style.scss" | resources.ToCSS | resources.Minify }} - - - -

- {{- block "main" . -}}{{- end -}} - - - diff --git a/assembler/ext/src/lexy/docs/layouts/_default/list.html b/assembler/ext/src/lexy/docs/layouts/_default/list.html deleted file mode 100644 index 94f3520a34..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/_default/list.html +++ /dev/null @@ -1,9 +0,0 @@ -{{ define "main" }} -
- -
- {{ .Content }} -
- -
-{{ end }} diff --git a/assembler/ext/src/lexy/docs/layouts/_default/single.html b/assembler/ext/src/lexy/docs/layouts/_default/single.html deleted file mode 100644 index e5013ab6dc..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/_default/single.html +++ /dev/null @@ -1,29 +0,0 @@ -{{ define "main" }} -
- -{{ if ne .TableOfContents "" }} - -{{ end }} - - - -
-{{ end }} diff --git a/assembler/ext/src/lexy/docs/layouts/playground/playground.html b/assembler/ext/src/lexy/docs/layouts/playground/playground.html deleted file mode 100644 index d64d61d8be..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/playground/playground.html +++ /dev/null @@ -1,354 +0,0 @@ -{{ define "main" }} - -
- -
-
- - - - - - - - - -
- -
- - - - - - - -
-
- -
-
-
-
-
-
-
-
- -
-
-
-
- -
- {{ .Content }} -
- -{{ $style := resources.Get "css/playground.scss" | resources.ToCSS | resources.Minify }} - - -{{ $playground := resources.Get "js/playground.js" | resources.ExecuteAsTemplate "playground.js" . | resources.Minify }} - - - - - - - - -{{ end }} diff --git a/assembler/ext/src/lexy/docs/layouts/reference/list.json.json b/assembler/ext/src/lexy/docs/layouts/reference/list.json.json deleted file mode 100644 index 6aadc7c88c..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/reference/list.json.json +++ /dev/null @@ -1,9 +0,0 @@ -{ -{{- range (where .Site.Pages "Section" "reference") -}} - {{- $url := .RelPermalink -}} - {{- range $name, $id := .Params.entities -}} - "{{ $name }}": "{{ $url }}#{{ $id }}", - {{- end -}} -{{- end -}} -"": "" -} diff --git a/assembler/ext/src/lexy/docs/layouts/reference/single.html b/assembler/ext/src/lexy/docs/layouts/reference/single.html deleted file mode 100644 index 6356306116..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/reference/single.html +++ /dev/null @@ -1,96 +0,0 @@ -{{ define "title" }} -{{ if (isset .Params "header") }} - {{ .Params.header }} — {{ .Site.Title }} -{{ else }} - {{ .Page.Title }} - {{ .Site.Title }} -{{ end }} -{{ end }} - -{{ define "main" }} -
- -{{ if ne .TableOfContents "" }} - -{{ end }} - -
-
- {{ if (isset .Params "header") }} -

Header {{ .Params.header }}

- {{ else }} -

{{ .Page.Title }}

- {{ end }} - -
- -
- {{ .Content }} -
- - {{- if and (ne .Kind "section") (.Scratch.Get "see-also") -}} -
-

See also

-
    - {{- range $link := (.Scratch.GetSortedMapValues "see-also") -}} -
  • {{ $link | safeHTML }}
  • - {{- end -}} -
-
- {{- end -}} -
- - - - - -
-{{ end }} diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/branch-rule.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/branch-rule.adoc deleted file mode 100644 index 0d214e58ab..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/branch-rule.adoc +++ /dev/null @@ -1,4 +0,0 @@ -{{- $url := relref . "/reference/dsl/branch#doc" -}} -{{- $.Page.Scratch.SetInMap "see-also" "branch rules" (printf "branch rules" $url) -}} -link:{{ $url }}[branch rule] -{{- printf "" -}} diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/char-class-rule.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/char-class-rule.adoc deleted file mode 100644 index 44a4e51090..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/char-class-rule.adoc +++ /dev/null @@ -1,4 +0,0 @@ -{{- $url := relref . "/reference/dsl/char_class#doc" -}} -{{- $.Page.Scratch.SetInMap "see-also" "char class rules" (printf "char class rules" $url) -}} -link:{{ $url }}[char class rule] -{{- printf "" -}} diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/docref.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/docref.adoc deleted file mode 100644 index b80353306a..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/docref.adoc +++ /dev/null @@ -1,16 +0,0 @@ -{{- $name := .Get 0 | lower -}} -{{- $text := .Get 1 | default (printf "`%s`" (.Get 0)) -}} -{{- $found := false -}} -{{- range where .Site.Pages "Section" "reference" -}} - {{- if isset (.Params.entities | default (dict "" "")) $name -}} - {{- $url := printf "%s#%s" .RelPermalink (index .Params.entities $name) -}} - {{- if ne $.Page.Permalink .Permalink -}} - {{- $.Page.Scratch.SetInMap "see-also" $name (printf "%s" $url $name) -}} - {{- end -}} - link:{{ $url }}[{{ $text }}] - {{- $found = true -}} - {{- end -}} -{{- end -}} -{{- if not $found -}} - {{- warnf "%q: Entity %s not found" .Page.File.Path $name -}} -{{- end -}} diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/download_list.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/download_list.adoc deleted file mode 100644 index e58f2b529f..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/download_list.adoc +++ /dev/null @@ -1,15 +0,0 @@ -{{ range sort $.Site.Data.tags "date" "desc" }} -== {{ .name }} +++{{ if .prerelease }} {{ (resources.Get "icons/beta.svg").Content | safeHTML }} {{ end }}+++ - -+++{{ (resources.Get "icons/calender.svg").Content | safeHTML }}+++ {{ default (now) .date | time.Format "2006-01-02" }} -+++{{ (resources.Get "icons/github.svg").Content | safeHTML }}+++ link:{{ .url }}[Github] -+++{{ (resources.Get "icons/download.svg").Content | safeHTML }}+++ link:{{ .download }}[Download] -+++{{ (resources.Get "icons/license.svg").Content | safeHTML }}+++ link:https://opensource.org/licenses/BSL-1.0/[BSL-1.0] - -```cmake -include(FetchContent) -FetchContent_Declare(lexy URL {{ .download }}) -FetchContent_MakeAvailable(lexy) -``` -{{ end }} - diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/encoding.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/encoding.adoc deleted file mode 100644 index 61c129e87d..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/encoding.adoc +++ /dev/null @@ -1,4 +0,0 @@ -{{- $url := relref . "/reference/encoding#doc" -}} -{{- $.Page.Scratch.SetInMap "see-also" "rules" (printf "input encodings" $url) -}} -link:{{ $url }}[encoding] -{{- printf "" -}} diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/error-callback.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/error-callback.adoc deleted file mode 100644 index 70c64e79bf..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/error-callback.adoc +++ /dev/null @@ -1,4 +0,0 @@ -{{- $url := relref . "/reference/action/validate#error-callback" -}} -{{- $.Page.Scratch.SetInMap "see-also" "rules" (printf "error callback" $url) -}} -link:{{ $url }}[error callback] -{{- printf "" -}} diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/github-example.html b/assembler/ext/src/lexy/docs/layouts/shortcodes/github-example.html deleted file mode 100644 index 66adeef343..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/github-example.html +++ /dev/null @@ -1,3 +0,0 @@ - - {{ (resources.Get "icons/github.svg").Content | safeHTML }}{{ .Get 0 }}.cpp - diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/godbolt-example.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/godbolt-example.adoc deleted file mode 100644 index 3c60f78cb1..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/godbolt-example.adoc +++ /dev/null @@ -1,38 +0,0 @@ -{{ $id := .Get 0 }} -{{ $source := ($id | printf "examples/%s.cpp" | resources.Get).Content | chomp }} - -{{ $input := "" }} -{{ $input_resource := ($id | printf "examples/%s.input" | resources.Get) }} -{{ if $input_resource }} - {{ $input = $input_resource.Content | chomp }} -{{ end }} - -{{ $full_source := $source | replaceRE "//({|})\\n?" "" }} -{{ $inline_source := $source | replaceRE "(?s:.*//{\n(.*)//}.*)" "$1"}} - -{{ $lexy := dict "id" "lexy" "version" "trunk" }} -{{ $compiler := dict "id" "clang_trunk" "libs" (slice $lexy) "options" "-std=c++20" }} - -{{ $executor := "" }} -{{ if findRE "^ARGV:" $input }} - {{ $executor = dict "compiler" $compiler "arguments" (replaceRE "^ARGV:" "" $input ) "argumentsVisible" true }} -{{ else }} - {{ $executor = dict "compiler" $compiler "stdin" $input "stdinVisible" (ne $input "") }} -{{ end }} - -{{ $session := dict "id" 1 "language" "c++" "source" $full_source "compilers" (slice) "executors" (slice $executor) }} -{{ $clientstate := dict "sessions" (slice $session) }} - -{{ $clientstate_b64 := replace ($clientstate | jsonify | base64Encode) "/" "%2F" }} - -.{{ .Get 1 }} -==== - -[.godbolt-example] -.+++{{ (resources.Get "icons/play.svg").Content | safeHTML }}+++ -[source,cpp] ----- -{{ $inline_source | safeHTML }} ----- -==== - diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/headerref.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/headerref.adoc deleted file mode 100644 index 3f55dad389..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/headerref.adoc +++ /dev/null @@ -1,2 +0,0 @@ -link:{{ relref . (.Get 0) }}[`lexy/{{ .Get 0 }}.hpp`] -{{- printf "" -}} diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/interface.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/interface.adoc deleted file mode 100644 index 3a6a326283..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/interface.adoc +++ /dev/null @@ -1,3 +0,0 @@ -.`{{ .Page.Params.header }}` -[source,cpp,subs="+quotes"] - diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/literal-rule.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/literal-rule.adoc deleted file mode 100644 index 9006a8b736..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/literal-rule.adoc +++ /dev/null @@ -1,4 +0,0 @@ -{{- $url := relref . "/reference/dsl/literal#doc" -}} -{{- $.Page.Scratch.SetInMap "see-also" "literal rules" (printf "literal rules" $url) -}} -link:{{ $url }}[literal rule] -{{- printf "" -}} diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/playground-example.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/playground-example.adoc deleted file mode 100644 index 4af4b20963..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/playground-example.adoc +++ /dev/null @@ -1,14 +0,0 @@ -{{ $id := .Get 0 }} -{{ $source := ($id | printf "playground/%s.cpp" | resources.Get).Content | replaceRE "^// INPUT:.*\n" "" | chomp }} - -.{{ .Get 1 }} -==== - -[.playground-example] -.+++{{ (resources.Get "icons/play.svg").Content | safeHTML }}+++ -[source,cpp] ----- -{{ $source | safeHTML }} ----- -==== - diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/rule.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/rule.adoc deleted file mode 100644 index 8bd96ec844..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/rule.adoc +++ /dev/null @@ -1,4 +0,0 @@ -{{- $url := relref . "/reference/dsl/#doc" -}} -{{- $.Page.Scratch.SetInMap "see-also" "rules" (printf "rules" $url) -}} -link:{{ $url }}[rule] -{{- printf "" -}} diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/svg.html b/assembler/ext/src/lexy/docs/layouts/shortcodes/svg.html deleted file mode 100644 index c792858ba8..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/svg.html +++ /dev/null @@ -1 +0,0 @@ -{{ (resources.Get (.Get 0)).Content | safeHTML }} diff --git a/assembler/ext/src/lexy/docs/layouts/shortcodes/token-rule.adoc b/assembler/ext/src/lexy/docs/layouts/shortcodes/token-rule.adoc deleted file mode 100644 index e6117ef705..0000000000 --- a/assembler/ext/src/lexy/docs/layouts/shortcodes/token-rule.adoc +++ /dev/null @@ -1,4 +0,0 @@ -{{- $url := relref . "/reference/dsl/token#doc" -}} -{{- $.Page.Scratch.SetInMap "see-also" "token rules" (printf "token rules" $url) -}} -link:{{ $url }}[token rule] -{{- printf "" -}} diff --git a/assembler/ext/src/lexy/docs/static/.nojekyll b/assembler/ext/src/lexy/docs/static/.nojekyll deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/assembler/ext/src/lexy/docs/static/CNAME b/assembler/ext/src/lexy/docs/static/CNAME deleted file mode 100644 index 4ae5f1816a..0000000000 --- a/assembler/ext/src/lexy/docs/static/CNAME +++ /dev/null @@ -1 +0,0 @@ -lexy.foonathan.net diff --git a/assembler/ext/src/lexy/examples/CMakeLists.txt b/assembler/ext/src/lexy/examples/CMakeLists.txt deleted file mode 100644 index 752a6942db..0000000000 --- a/assembler/ext/src/lexy/examples/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -# SPDX-License-Identifier: BSL-1.0 - -add_executable(lexy_example_config) -set_target_properties(lexy_example_config PROPERTIES OUTPUT_NAME "config") -target_sources(lexy_example_config PRIVATE config.cpp) -target_link_libraries(lexy_example_config PRIVATE foonathan::lexy::dev foonathan::lexy::file) - -add_executable(lexy_example_calculator) -set_target_properties(lexy_example_calculator PROPERTIES OUTPUT_NAME "calculator") -target_sources(lexy_example_calculator PRIVATE calculator.cpp) -target_link_libraries(lexy_example_calculator PRIVATE foonathan::lexy::dev foonathan::lexy::unicode) - -add_executable(lexy_example_email) -set_target_properties(lexy_example_email PROPERTIES OUTPUT_NAME "email") -target_sources(lexy_example_email PRIVATE email.cpp) -target_link_libraries(lexy_example_email PRIVATE foonathan::lexy::dev foonathan::lexy::file) - -add_executable(lexy_example_ip_address) -set_target_properties(lexy_example_ip_address PROPERTIES OUTPUT_NAME "ip_address") -target_sources(lexy_example_ip_address PRIVATE ip_address.cpp) -target_link_libraries(lexy_example_ip_address PRIVATE foonathan::lexy::dev) - -add_executable(lexy_example_json) -set_target_properties(lexy_example_json PROPERTIES OUTPUT_NAME "json") -target_sources(lexy_example_json PRIVATE json.cpp) -target_link_libraries(lexy_example_json PRIVATE foonathan::lexy::dev foonathan::lexy::file) - -add_executable(lexy_example_protobuf) -set_target_properties(lexy_example_protobuf PROPERTIES OUTPUT_NAME "protobuf") -target_sources(lexy_example_protobuf PRIVATE protobuf.cpp) -target_link_libraries(lexy_example_protobuf PRIVATE foonathan::lexy::dev foonathan::lexy::file) - -add_executable(lexy_example_shell) -set_target_properties(lexy_example_shell PROPERTIES OUTPUT_NAME "shell") -target_sources(lexy_example_shell PRIVATE shell.cpp) -target_link_libraries(lexy_example_shell PRIVATE foonathan::lexy::dev) - -add_executable(lexy_example_xml) -set_target_properties(lexy_example_xml PROPERTIES OUTPUT_NAME "xml") -target_sources(lexy_example_xml PRIVATE xml.cpp) -target_link_libraries(lexy_example_xml PRIVATE foonathan::lexy::dev foonathan::lexy::file) - -add_executable(lexy_example_turing EXCLUDE_FROM_ALL) -set_target_properties(lexy_example_turing PROPERTIES OUTPUT_NAME "turing") -target_sources(lexy_example_turing PRIVATE turing.cpp) -target_link_libraries(lexy_example_turing PRIVATE foonathan::lexy::dev foonathan::lexy::file) - diff --git a/assembler/ext/src/lexy/examples/calculator.cpp b/assembler/ext/src/lexy/examples/calculator.cpp deleted file mode 100644 index 7ee4c5d3cc..0000000000 --- a/assembler/ext/src/lexy/examples/calculator.cpp +++ /dev/null @@ -1,461 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -// Naive implementation of an AST with simple evaluation function. -namespace ast -{ -using expr_ptr = std::shared_ptr; - -struct environment -{ - struct function - { - int* parameter_var; - expr_ptr body; - }; - - std::map vars; - std::map fns; -}; - -struct expr -{ - virtual ~expr() = default; - virtual int evaluate(environment& env) const = 0; -}; - -struct expr_literal : expr -{ - int value; - - explicit expr_literal(int v) : value(v) {} - - int evaluate(environment&) const override - { - return value; - } -}; - -struct expr_name : expr -{ - std::string name; - - explicit expr_name(std::string n) : name(LEXY_MOV(n)) {} - - int evaluate(environment& env) const override - { - auto iter = env.vars.find(name); - // A real compiler would issue an error message at this point. - return iter == env.vars.end() ? 0 : iter->second; - } -}; - -struct expr_unary_arithmetic : expr -{ - enum op_t - { - negate, - complement, - } op; - expr_ptr rhs; - - explicit expr_unary_arithmetic(op_t op, expr_ptr e) : op(op), rhs(LEXY_MOV(e)) {} - - int evaluate(environment& env) const override - { - auto rhs_v = rhs->evaluate(env); - switch (op) - { - case negate: - return -rhs_v; - case complement: - return ~rhs_v; - } - return 0; // unreachable - } -}; - -struct expr_binary_arithmetic : expr -{ - enum op_t - { - plus, - minus, - times, - div, - pow, - bit_and, - bit_or, - bit_xor, - } op; - expr_ptr lhs, rhs; - - explicit expr_binary_arithmetic(expr_ptr lhs, op_t op, expr_ptr rhs) - : op(op), lhs(LEXY_MOV(lhs)), rhs(LEXY_MOV(rhs)) - {} - - int evaluate(environment& env) const override - { - auto lhs_v = lhs->evaluate(env); - auto rhs_v = rhs->evaluate(env); - switch (op) - { - case plus: - return lhs_v + rhs_v; - case minus: - return lhs_v - rhs_v; - case times: - return lhs_v * rhs_v; - case div: - return lhs_v / rhs_v; - case pow: - return static_cast(std::pow(lhs_v, rhs_v)); - case bit_and: - return lhs_v & rhs_v; - case bit_or: - return lhs_v | rhs_v; - case bit_xor: - return lhs_v ^ rhs_v; - } - - return 0; // unreachable - } -}; - -struct expr_comparison : expr -{ - enum op_t - { - equal, - less, - }; - std::vector ops; - std::vector operands; - - int evaluate(environment& env) const override - { - auto lhs = operands[0]->evaluate(env); - for (auto i = 0u; i != ops.size(); ++i) - { - auto rhs = operands[i + 1]->evaluate(env); - switch (ops[i]) - { - case equal: - if (lhs != rhs) - return 0; - break; - case less: - if (lhs >= rhs) - return 0; - break; - } - lhs = rhs; - } - return 1; - } -}; - -struct expr_if : expr -{ - expr_ptr condition, then, else_; - - explicit expr_if(expr_ptr condition, expr_ptr then, expr_ptr else_) - : condition(LEXY_MOV(condition)), then(LEXY_MOV(then)), else_(LEXY_MOV(else_)) - {} - - int evaluate(environment& env) const override - { - if (condition->evaluate(env) != 0) - return then->evaluate(env); - else - return else_->evaluate(env); - } -}; - -struct expr_call : expr -{ - std::string function; - expr_ptr argument; - - explicit expr_call(std::string function, expr_ptr argument) - : function(LEXY_MOV(function)), argument(LEXY_MOV(argument)) - {} - - int evaluate(environment& env) const override - { - auto iter = env.fns.find(function); - if (iter == env.fns.end()) - return 0; - auto& [param, body] = iter->second; - - auto old_value = std::exchange(*param, argument->evaluate(env)); - auto result = body->evaluate(env); - *param = old_value; - return result; - } -}; - -struct expr_assignment : expr -{ - expr_ptr lhs, rhs; - - explicit expr_assignment(expr_ptr lhs, expr_ptr rhs) : lhs(LEXY_MOV(lhs)), rhs(LEXY_MOV(rhs)) {} - - int evaluate(environment& env) const override - { - if (auto name = dynamic_cast(lhs.get())) - { - // Variable assignment. - return env.vars[name->name] = rhs->evaluate(env); - } - else if (auto call = dynamic_cast(lhs.get())) - { - // Function assignment. - auto param = dynamic_cast(call->argument.get()); - if (param == nullptr) - std::fputs("error: function parameter not a name\n", stderr); - else - env.fns[call->function] = environment::function{&env.vars[param->name], rhs}; - return 0; - } - else - { - std::fputs("error: assignment lhs not an lvalue\n", stderr); - return 0; - } - } -}; -} // namespace ast - -namespace grammar -{ -namespace dsl = lexy::dsl; - -constexpr auto escaped_newline = dsl::backslash >> dsl::newline; - -// An integer literal. -// Supports hexadecimal and decimal literals. -struct integer : lexy::token_production -{ - static constexpr auto rule = LEXY_LIT("0x") >> dsl::integer | dsl::integer; - - static constexpr auto value = lexy::forward; -}; - -// A Unicode-aware identifier. -struct name -{ - static constexpr auto rule - = dsl::identifier(dsl::unicode::xid_start_underscore, dsl::unicode::xid_continue); - - static constexpr auto value = lexy::as_string; -}; - -// An expression that is nested inside another expression. -struct nested_expr : lexy::transparent_production -{ - // We change the whitespace rule to allow newlines: - // as it's nested, the REPL can properly handle continuation lines. - static constexpr auto whitespace = dsl::ascii::space | escaped_newline; - // The rule itself just recurses back to expression, but with the adjusted whitespace now. - static constexpr auto rule = dsl::recurse; - - static constexpr auto value = lexy::forward; -}; - -// An arbitrary expression. -// It uses lexy's built-in support for operator precedence parsing to automatically generate a -// proper rule. This is done by inheriting from expression_production. -struct expr : lexy::expression_production -{ - struct expected_operand - { - static constexpr auto name = "expected operand"; - }; - - // We need to specify the atomic part of an expression. - static constexpr auto atom = [] { - auto paren_expr = dsl::parenthesized(dsl::p); - // Functions can only have a single argument for simplicity. - auto var_or_call = dsl::p >> dsl::if_(paren_expr); - auto literal = dsl::p; - - return paren_expr | var_or_call | literal | dsl::error; - }(); - - // Each of the nested classes defines one operation. - // They inherit from a tag type that specify the kind of operation (prefix, infix, postfix), - // and associativy (left, right, single (non-associative)), - // and specify the operator rule and operand. - - // x**2 - struct math_power : dsl::infix_op_right - { - static constexpr auto op = dsl::op(LEXY_LIT("**")); - - // math_power has highest binding power, so it's operand is the atom rule. - using operand = dsl::atom; - }; - // -x - struct math_prefix : dsl::prefix_op - { - static constexpr auto op = dsl::op(LEXY_LIT("-")); - - using operand = math_power; - }; - // x * x, x / x - struct math_product : dsl::infix_op_left - { - static constexpr auto op = [] { - // Since we have both ** and * as possible operators, we need to ensure that * is only - // matched when it is not followed by *. - // In the particular situation where ** has higher binding power, it doesn't actually - // matter here, but it's better to be more resilient. - auto star = dsl::not_followed_by(LEXY_LIT("*"), dsl::lit_c<'*'>); - return dsl::op(star) - / dsl::op(LEXY_LIT("/")); - }(); - using operand = math_prefix; - }; - // x + x, x - x - struct math_sum : dsl::infix_op_left - { - static constexpr auto op = dsl::op(LEXY_LIT("+")) - / dsl::op(LEXY_LIT("-")); - - using operand = math_product; - }; - - // ~x - struct bit_prefix : dsl::prefix_op - { - static constexpr auto op = dsl::op(LEXY_LIT("~")); - using operand = dsl::atom; - }; - // x & x - struct bit_and : dsl::infix_op_left - { - static constexpr auto op = dsl::op(LEXY_LIT("&")); - using operand = bit_prefix; - }; - // x | x, x ^ x - struct bit_or : dsl::infix_op_left - { - static constexpr auto op = dsl::op(LEXY_LIT("|")) - / dsl::op(LEXY_LIT("^")); - using operand = bit_and; - }; - - // Comparisons are list operators, which allows implementation of chaining. - // x == y < z - struct comparison : dsl::infix_op_list - { - // Other comparison operators omitted for simplicity. - static constexpr auto op = dsl::op(LEXY_LIT("==")) - / dsl::op(LEXY_LIT("<")); - - // The use of dsl::groups ensures that an expression can either contain math or bit - // operators. Mixing requires parenthesis. - using operand = dsl::groups; - }; - - // x ? y : z - struct conditional : dsl::infix_op_single - { - // We treat a conditional operator, which has three operands, - // as a binary operator where the operator consists of ?, the inner operator, and :. - // The ensures that `dsl::op` does not produce a value. - static constexpr auto op - = dsl::op(LEXY_LIT("?") >> dsl::p + dsl::lit_c<':'>); - using operand = comparison; - }; - - struct assignment : dsl::infix_op_single - { - static constexpr auto op - // Similar to * above, we need to prevent `=` from matching `==`. - = dsl::op(dsl::not_followed_by(LEXY_LIT("="), dsl::lit_c<'='>)); - using operand = conditional; - }; - - // An expression also needs to specify the operation with the lowest binding power. - // The operation of everything else is determined by following the `::operand` member. - using operation = assignment; - - static constexpr auto value = - // We need a sink as the comparison expression generates a list. - lexy::fold_inplace>( - [] { return std::make_unique(); }, - [](auto& node, ast::expr_ptr opr) { node->operands.push_back(LEXY_MOV(opr)); }, - [](auto& node, ast::expr_comparison::op_t op) { node->ops.push_back(op); }) - // The result of the list feeds into a callback that handles all other cases. - >> lexy::callback( - // atoms - lexy::forward, lexy::new_, - lexy::new_, lexy::new_, - // unary/binary operators - lexy::new_, - lexy::new_, - // conditional and assignment - lexy::new_, - lexy::new_); -}; - -// A statement, which is a list of expressions separated by semicolons. -struct stmt -{ - // We don't allow newlines as whitespace at the top-level. - // This is because we can't easily know whether we need to request more input when seeing a - // newline or not. Once we're having a e.g. parenthesized expression, we know that we need more - // input until we've reached ), so then change the whitespace rule. - static constexpr auto whitespace = dsl::ascii::blank | escaped_newline; - - static constexpr auto rule = [] { - // We can't use `dsl::eol` as our terminator directly, - // since that would try and skip whitespace, which requests more input on the REPL. - auto at_eol = dsl::peek(dsl::eol); - return dsl::terminator(at_eol).opt_list(dsl::p, dsl::sep(dsl::semicolon)); - }(); - - static constexpr auto value = lexy::as_list>; -}; -} // namespace grammar - -#ifndef LEXY_TEST -# include -# include -# include - -int main() -{ - ast::environment environment; - // We create an interactive REPL and use it for our input. - for (lexy_ext::shell> shell; shell.is_open();) - { - auto input = shell.prompt_for_input(); - - auto result = lexy::parse(input, lexy_ext::report_error); - if (result.has_value() && !result.value().empty()) - { - auto exprs = LEXY_MOV(result).value(); - for (auto i = 0u; i < exprs.size() - 1; ++i) - exprs[i]->evaluate(environment); - - auto value = exprs.back()->evaluate(environment); - std::printf("= %d\n", value); - } - } -} -#endif - diff --git a/assembler/ext/src/lexy/examples/config.cpp b/assembler/ext/src/lexy/examples/config.cpp deleted file mode 100644 index 220b272301..0000000000 --- a/assembler/ext/src/lexy/examples/config.cpp +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include -#include -#include -#include - -#include // lexy::parse -#include // value callbacks -#include // lexy::dsl::* -#include // lexy::read_file - -#include // lexy_ext::report_error - -struct PackageVersion -{ - int major; - int minor; - int patch; -}; - -struct PackageConfig -{ - std::string name; - PackageVersion version; - std::vector authors; -}; - -namespace grammar -{ -namespace dsl = lexy::dsl; - -struct name : lexy::token_production -{ - struct invalid_character - { - static constexpr auto name = "invalid name character"; - }; - - // Match an alpha character, followed by zero or more alphanumeric characters or underscores. - // Captures it all into a lexeme. - static constexpr auto rule = [] { - auto lead_char = dsl::ascii::alpha; - auto trailing_char = dsl::ascii::word; - - return dsl::identifier(lead_char, trailing_char) - + dsl::peek(dsl::ascii::space).error; - }(); - - // The final value of this production is a std::string we've created from the lexeme. - static constexpr auto value = lexy::as_string; -}; - -struct version : lexy::token_production -{ - struct forbidden_build_string - { - static constexpr auto name = "build string not supported"; - }; - - // Match three integers separated by dots, or the special tag "unreleased". - static constexpr auto rule = [] { - auto number = dsl::try_(dsl::integer, dsl::nullopt); - auto dot = dsl::try_(dsl::period); - auto dot_version = dsl::times<3>(number, dsl::sep(dot)) - + dsl::peek_not(dsl::lit_c<'-'>).error; - - auto unreleased = LEXY_LIT("unreleased"); - - return unreleased | dsl::else_ >> dot_version; - }(); - - // Construct a PackageVersion as the result of the production. - static constexpr auto value - = lexy::bind(lexy::construct, lexy::_1 or 0, lexy::_2 or 0, lexy::_3 or 0); -}; - -struct author -{ - struct invalid_character - { - static constexpr auto name = "invalid string character"; - }; - - // Match zero or more non-control code points ("characters") surrounded by quotation marks. - // We allow `\u` and `\U` as escape sequences. - static constexpr auto rule = [] { - auto cp = (-dsl::ascii::control).error; - auto escape = dsl::backslash_escape // - .rule(dsl::lit_c<'u'> >> dsl::code_point_id<4>) // - .rule(dsl::lit_c<'U'> >> dsl::code_point_id<8>); // - - return dsl::quoted(cp, escape); - }(); - - // Construct a UTF-8 string from the quoted content. - static constexpr auto value = lexy::as_string; -}; - -struct author_list -{ - // Match a comma separated (non-empty) list of authors surrounded by square brackets. - static constexpr auto rule = dsl::square_bracketed.list(dsl::p, dsl::sep(dsl::comma)); - - // Collect all authors into a std::vector. - static constexpr auto value = lexy::as_list>; -}; - -struct config -{ - struct unknown_field - { - static constexpr auto name = "unknown config field"; - }; - struct duplicate_field - { - static constexpr auto name = "duplicate config field"; - }; - - // Whitespace is ' ' and '\t'. - static constexpr auto whitespace = dsl::ascii::blank; - - static constexpr auto rule = [] { - auto make_field = [](auto name, auto rule) { - auto end = dsl::try_(dsl::newline, dsl::until(dsl::newline)); - return name >> dsl::try_(dsl::lit_c<'='>) + rule + end; - }; - - auto name_field = make_field(LEXY_LIT("name"), LEXY_MEM(name) = dsl::p); - auto version_field = make_field(LEXY_LIT("version"), LEXY_MEM(version) = dsl::p); - auto authors_field - = make_field(LEXY_LIT("authors"), LEXY_MEM(authors) = dsl::p); - - auto combination = dsl::combination(name_field, version_field, authors_field) - .missing_error.duplicate_error; - return combination + dsl::eof; - }(); - - static constexpr auto value = lexy::as_aggregate; -}; -} // namespace grammar - -int main(int argc, char** argv) -{ - if (argc < 2) - { - std::fprintf(stderr, "usage: %s ", argv[0]); - return 1; - } - - // We're requiring UTF-8 input. - auto file = lexy::read_file(argv[1]); - if (!file) - { - std::fprintf(stderr, "file '%s' not found", argv[1]); - return 1; - } - - auto result = lexy::parse(file.buffer(), lexy_ext::report_error); - - if (result.has_value()) - { - auto& config = result.value(); - - std::printf("Package %s (%d.%d.%d)\n", config.name.c_str(), config.version.major, - config.version.minor, config.version.patch); - - std::puts("Created by:"); - for (auto& author : config.authors) - std::printf("- \"%s\"", author.c_str()); - } - - if (!result) - return 2; -} - diff --git a/assembler/ext/src/lexy/examples/email.cpp b/assembler/ext/src/lexy/examples/email.cpp deleted file mode 100644 index ad53257ff7..0000000000 --- a/assembler/ext/src/lexy/examples/email.cpp +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include -#include -#include -#include - -#include // lexy::parse -#include // value callbacks -#include // lexy::dsl::* -#include // lexy::read_file - -#include // lexy_ext::report_error - -// Parses an email as defined by a simplified subset of RFC 5322 -// (https://tools.ietf.org/html/rfc5322). -// It does not support groups or IPs as email addresses, nor most -// headers or the line width limitations. - -namespace ast -{ -struct address -{ - std::optional display_name; - std::string local_part; - std::string domain; - - void print() const - { - if (display_name) - std::printf("%s <%s@%s> ", display_name->c_str(), local_part.c_str(), domain.c_str()); - else - std::printf("%s@%s ", local_part.c_str(), domain.c_str()); - } -}; - -struct message -{ - std::vector
from; - std::vector
to; - std::vector
cc; - std::string subject; - std::string body; - - void print() const - { - std::fputs("From: ", stdout); - for (auto& addr : from) - addr.print(); - std::putchar('\n'); - std::fputs("To: ", stdout); - for (auto& addr : to) - addr.print(); - std::putchar('\n'); - std::fputs("Cc: ", stdout); - for (auto& addr : cc) - addr.print(); - std::putchar('\n'); - std::printf("Subject:%s\n", subject.c_str()); - - std::putchar('\n'); - - std::printf("%s", body.c_str()); - } -}; - -} // namespace ast -namespace grammar -{ -namespace dsl = lexy::dsl; - -// We're limiting whitespace to ASCII blank. -// We don't distinguish here between folding and non-folding whitespace for simplicity. -// We also don't support comments - they're really complicated in that they support nesting and -// quotes and so on. -constexpr auto ws = dsl::whitespace(dsl::ascii::blank); - -//=== https://tools.ietf.org/html/rfc5322#section-3.2.3 ===// -constexpr auto atext - = LEXY_CHAR_CLASS("atext", dsl::ascii::alpha / dsl::ascii::digit / LEXY_LIT("!") / LEXY_LIT("#") - / LEXY_LIT("$") / LEXY_LIT("%") / LEXY_LIT("&") / LEXY_LIT("'") - / LEXY_LIT("*") / LEXY_LIT("+") / LEXY_LIT("-") / LEXY_LIT("/") - / LEXY_LIT("=") / LEXY_LIT("?") / LEXY_LIT("^") / LEXY_LIT("_") - / LEXY_LIT("`") / LEXY_LIT("{") / LEXY_LIT("|") / LEXY_LIT("}")); - -// Text of the specified characters. -// In the grammar it is always surrounded by whitespace. -// Here, we only add trailing whitespace; leading whitespace is taken care of earlier. -constexpr auto atom = dsl::identifier(atext) + ws; - -struct dot_atom -{ - // A list of atom separated by periods which are part of the content and thus captured (unlike - // the whitespace). - static constexpr auto rule = dsl::list(atom, dsl::sep(dsl::capture(dsl::period) >> ws)); - static constexpr auto value = lexy::as_string; -}; - -//=== https://tools.ietf.org/html/rfc5322#section-3.2.4 ===// -struct quoted_string -{ - static constexpr auto rule = [] { - // \c, where c is a printable ASCII character, is replaced by c itself. - auto escape = dsl::backslash_escape.capture(dsl::ascii::print); - // Skip trailing whitespace. - return dsl::quoted(dsl::ascii::print, escape) >> ws; - }(); - static constexpr auto value = lexy::as_string; -}; - -//=== https://tools.ietf.org/html/rfc5322#section-3.2.5 ===// -// Word skips trailing whitespace. -constexpr auto word = dsl::p | dsl::else_ >> atom; - -struct phrase -{ - // A phrase is a list of words which starts with another text character or quote. - static constexpr auto rule = dsl::list(dsl::peek(atext / LEXY_LIT("\"")) >> word); - static constexpr auto value = lexy::as_string; -}; - -//=== https://tools.ietf.org/html/rfc5322#section-3.4 ===// -// Note: we're having no group so we merge mailbox and address. -struct address -{ - static constexpr auto rule = [] { - auto local_part = dsl::p | dsl::else_ >> dsl::p; - auto at = dsl::at_sign + ws; - auto domain = dsl::p; // No domain literal support. - - // Sets the local part and domain member. - auto addr_spec = local_part + at + domain; - - // An address spec with an optional name. - // Need to skip whitespace after the <, trailing whitespace skipped by addr_spec. - auto angle_addr = dsl::angle_bracketed(ws + addr_spec); - // Whitespace between phrase and < is skipped by phrase. - auto name_addr = dsl::opt(dsl::p) + angle_addr; - - // We're only having a named address if we can match the optional phrase followed by an - // angle bracket. - auto name_addr_condition = dsl::opt(dsl::p) + LEXY_LIT("<"); - - // An address spec without a name. - auto unnamed_addr = dsl::nullopt + addr_spec; - - // Need to skip initial whitespace. - return ws + (dsl::peek(name_addr_condition) >> name_addr | dsl::else_ >> unnamed_addr); - }(); - static constexpr auto value = lexy::construct; -}; - -struct address_list -{ - static constexpr auto rule = dsl::list(dsl::p
, dsl::sep(dsl::comma)); - static constexpr auto value = lexy::as_list>; -}; - -//=== https://tools.ietf.org/html/rfc5322#section-3.5/6 ===// -struct unstructured -{ - static constexpr auto rule = dsl::opt(dsl::identifier(dsl::ascii::print)); - static constexpr auto value = lexy::as_string; -}; - -struct body -{ - // The body is literally anything until the end of the file. - static constexpr auto rule = dsl::capture(dsl::any); - static constexpr auto value = lexy::as_string; -}; - -struct fields -{ - static constexpr auto rule = [] { - // Some of the fields in the header of a message. - auto from = LEXY_LIT("From:") >> dsl::p + dsl::newline; - auto to = LEXY_LIT("To:") >> dsl::p + dsl::newline; - auto cc = LEXY_LIT("Cc:") >> dsl::p + dsl::newline; - auto subject = LEXY_LIT("Subject:") >> dsl::p + dsl::newline; - - // We allow a partial combination of the fields (i.e. each field at most once in an - // arbitrary order). Some fields are mandatory, but this verification is better done - // elsewhere. - // - // With LEXY_MEM() we can assign them to a member of the given name. - return dsl::partial_combination(LEXY_MEM(from) = from, LEXY_MEM(to) = to, LEXY_MEM(cc) = cc, - LEXY_MEM(subject) = subject); - }(); - static constexpr auto value = lexy::as_aggregate; -}; - -struct message -{ - // The fields followed by the body assigned to the body member. - static constexpr auto rule = dsl::p + dsl::newline + (LEXY_MEM(body) = dsl::p); - static constexpr auto value = lexy::as_aggregate; -}; -} // namespace grammar - -#ifndef LEXY_TEST -int main(int argc, char** argv) -{ - if (argc < 2) - { - std::fprintf(stderr, "usage: %s ", argv[0]); - return 1; - } - - // Emails only support ASCII characters. - auto file = lexy::read_file(argv[1]); - if (!file) - { - std::fprintf(stderr, "file '%s' not found", argv[1]); - return 1; - } - - auto message = lexy::parse(file.buffer(), lexy_ext::report_error); - if (!message) - return 2; - - message.value().print(); -} -#endif - diff --git a/assembler/ext/src/lexy/examples/ip_address.cpp b/assembler/ext/src/lexy/examples/ip_address.cpp deleted file mode 100644 index 0f6fa9937e..0000000000 --- a/assembler/ext/src/lexy/examples/ip_address.cpp +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include - -#include // lexy::parse -#include // value callbacks -#include // lexy::dsl::* -#include // lexy::argv_input - -#include // lexy_ext::report_error - -namespace ip -{ -// Stores an IP address. -struct ip_address -{ - int version; // 4 or 6 - std::uint16_t pieces[8]; -}; - -// Constructs an IPv4 address. -constexpr ip_address ipv4(std::uint8_t a, std::uint8_t b, std::uint8_t c, std::uint8_t d) -{ - ip_address result{4, {}}; - result.pieces[0] = static_cast((a << 8) | b); - result.pieces[1] = static_cast((c << 8) | d); - return result; -} - -// Constructs an IPv6 address. -class ipv6_builder -{ -public: - constexpr ipv6_builder() : _pieces{}, _count(0), _elision_index(-1) {} - - constexpr int count() const - { - return _count; - } - constexpr bool has_elision() const - { - return _elision_index >= 0; - } - - constexpr bool elision() - { - if (has_elision()) - return false; - - _elision_index = _count; - return true; - } - constexpr void piece(std::uint16_t p) - { - if (_count < 8) - _pieces[_count] = p; - ++_count; - } - constexpr void ipv4(ip_address ip) - { - LEXY_PRECONDITION(ip.version == 4); - if (_count <= 6) - { - _pieces[_count] = ip.pieces[0]; - _pieces[_count + 1] = ip.pieces[1]; - } - _count += 2; - } - - constexpr ip_address finish() && - { - ip_address result{6, {}}; - - auto dst = 0; - auto src = 0; - - // Copy everything before the elision. - while (src < _elision_index) - { - result.pieces[dst] = _pieces[src]; - ++dst; - ++src; - } - - // Skip over the zeroes. - auto zero_count = has_elision() ? 8 - _count : 0; - dst += zero_count; - - // Copy everything after the elision. - while (src < _count && src < 8) - { - result.pieces[dst] = _pieces[src]; - ++dst; - ++src; - } - - return result; - } - -private: - std::uint16_t _pieces[8]; - int _count; - int _elision_index; -}; -} // namespace ip - -// Formal specification: https://tools.ietf.org/html/draft-main-ipaddr-text-rep-00#section-3 -namespace grammar -{ -namespace dsl = lexy::dsl; - -// d8 in the specification. -struct ipv4_octet -{ - static constexpr auto rule = [] { - auto digits = dsl::digits<>.no_leading_zero(); - return dsl::integer(digits); - }(); - - static constexpr auto value = lexy::as_integer; -}; - -// Ipv4address in the specification. -struct ipv4_address -{ - static constexpr auto rule = dsl::times<4>(dsl::p, dsl::sep(dsl::period)); - static constexpr auto value = lexy::callback(&ip::ipv4); -}; - -// If lookahead finds a period after the digits, it must be an IPv4 address. -constexpr auto ipv4_address_condition = dsl::peek(dsl::digits<> + dsl::period); - -// h16 in the specification. -struct ipv6_piece -{ - static constexpr auto rule = dsl::integer; - static constexpr auto value = lexy::as_integer; -}; - -// IPv6address in the specification. -// We can't easily parse it using the DSL, so we provide a scan function. -struct ipv6_address : lexy::scan_production -{ - struct missing_pieces - { - static constexpr auto name = "not enough IPv6 pieces"; - }; - struct too_many_pieces - { - static constexpr auto name = "too many IPv6 pieces"; - }; - - struct duplicate_elision - { - static constexpr auto name = "duplicate zero elision"; - }; - - // Called by the algorithm to perform the actual parsing. - // The scanner manages the input and allows dispatching to other rules. - // (scan_result is a typedef injected by `lexy::scan_production`). - template - static constexpr scan_result scan(lexy::rule_scanner& scanner) - { - ip::ipv6_builder builder; - - // We parse arbitrary many pieces in a loop. - while (true) - { - // At any point, we can have zero elision with a double colon. - if (auto elision_begin = scanner.position(); scanner.branch(dsl::double_colon)) - { - if (!builder.elision()) - // Report an error if we had an elision already. - // We trivially recover from it and continue parsing. - scanner.error(duplicate_elision{}, elision_begin, scanner.position()); - - // Check whether it is followed by another piece, as it is allowed to be at the end. - if (!scanner.peek(dsl::digit)) - break; - } - // A normal separator is only allowed if we had a piece already. - else if (builder.count() > 0 && !scanner.branch(dsl::colon)) - { - // If we don't have a separator, we exit the loop. - break; - } - - // A piece is either an IPv4 address. - if (scanner.branch(ipv4_address_condition)) - { - auto ipv4 = scanner.parse(ipv4_address{}); - if (!scanner) - return lexy::scan_failed; - builder.ipv4(ipv4.value()); - - // If it was an IPv4 address, nothing must follow it. - break; - } - else - { - // Or hex digits. - auto piece = scanner.parse(ipv6_piece{}); - if (!scanner) - return lexy::scan_failed; - builder.piece(piece.value()); - } - } - - // Check that we're having the correct amount of pieces. - // Report an error otherwise, but trivially recover from it. - if (builder.count() < 8 && !builder.has_elision()) - scanner.error(missing_pieces{}, scanner.begin(), scanner.position()); - else if (builder.count() > 8 || (builder.has_elision() && builder.count() == 8)) - scanner.error(too_many_pieces{}, scanner.begin(), scanner.position()); - - // And return our result. - return LEXY_MOV(builder).finish(); - } -}; - -// Either IPv4 or IPv6. -struct ip_address -{ - static constexpr auto rule = [] { - auto ipv4 = ipv4_address_condition >> dsl::p; - auto ipv6 = dsl::else_ >> dsl::p; - - return (ipv4 | ipv6) + dsl::try_(dsl::eof); - }(); - - static constexpr auto value = lexy::forward; -}; -} // namespace grammar - -#ifndef LEXY_TEST -int main(int argc, char* argv[]) -{ - // Scan the IP address provided at the commandline. - lexy::argv_input input(argc, argv); - auto result = lexy::parse(input, lexy_ext::report_error); - if (!result.has_value()) - return 1; - - auto value = result.value(); - - // And print it as an integer. - std::printf("0x"); - auto count = value.version == 4 ? 2 : 8; - for (auto i = 0; i < count; ++i) - std::printf("%02X", value.pieces[i]); - std::printf("\n"); - - return result ? 0 : 1; -} -#endif - diff --git a/assembler/ext/src/lexy/examples/json.cpp b/assembler/ext/src/lexy/examples/json.cpp deleted file mode 100644 index 3a51d94032..0000000000 --- a/assembler/ext/src/lexy/examples/json.cpp +++ /dev/null @@ -1,351 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -#include // lexy::parse -#include // value callbacks -#include // lexy::dsl::* -#include // lexy::read_file - -#include // lexy_ext::report_error - -// Datastructures for storing JSON. -// Not really the point of the example, so as simple as possible. -namespace ast -{ -struct json_value; - -using json_null = std::nullptr_t; -using json_bool = bool; - -struct json_number -{ - std::int64_t integer; - std::optional fraction; - std::optional exponent; -}; - -using json_string = std::string; - -using json_array = std::vector; -using json_object = std::map; - -struct json_value -{ - std::variant v; - - template - json_value(T t) : v(std::move(t)) - {} - - void _indent(int level) const - { - for (auto i = 0; i < level; ++i) - std::fputc(' ', stdout); - } - - void _print(json_null, int) const - { - std::fputs("null", stdout); - } - void _print(json_bool b, int) const - { - if (b) - std::fputs("true", stdout); - else - std::fputs("false", stdout); - } - void _print(const json_number& i, int) const - { - std::fprintf(stdout, "%" PRId64, i.integer); - if (i.fraction) - std::fprintf(stdout, ".%s", i.fraction->c_str()); - if (i.exponent) - std::fprintf(stdout, "e%" PRId16, *i.exponent); - } - void _print(const json_string& str, int) const - { - std::fputc('"', stdout); - for (auto& c : str) - if (c == '"') - std::fputs(R"(\")", stdout); - else if (c == '\\') - std::fputs(R"(\\)", stdout); - else if (std::iscntrl(c) != 0) - std::fprintf(stdout, "\\x%02x", static_cast(c)); - else - std::fputc(c, stdout); - std::fputc('"', stdout); - } - void _print(const json_array& array, int level) const - { - std::fputs("[\n", stdout); - - auto first = true; - for (auto& elem : array) - { - if (first) - first = false; - else - std::fputs(",\n", stdout); - - _indent(level + 1); - elem.print(level + 1); - } - - std::fputs("\n", stdout); - _indent(level); - std::fputs("]", stdout); - } - void _print(const json_object& object, int level) const - { - std::fputs("{\n", stdout); - - auto first = true; - for (auto& [key, value] : object) - { - if (first) - first = false; - else - std::fputs(",\n", stdout); - - _indent(level + 1); - _print(key, level + 1); - std::fputs(" : ", stdout); - value.print(level + 1); - } - - std::fputs("\n", stdout); - _indent(level); - std::fputs("}", stdout); - } - - void print(int level = 0) const - { - std::visit([&](const auto& value) { _print(value, level); }, v); - } -}; -} // namespace ast - -// The grammar of JSON. -// Modelled after the specificaton of https://www.json.org. -// It is compliant modulo bugs. -namespace grammar -{ -namespace dsl = lexy::dsl; - -struct json_value; - -// The json value null. -struct null : lexy::token_production -{ - static constexpr auto rule = LEXY_LIT("null"); - static constexpr auto value = lexy::construct; -}; - -// A json value that is a boolean. -struct boolean : lexy::token_production -{ - struct true_ : lexy::transparent_production - { - static constexpr auto rule = LEXY_LIT("true"); - static constexpr auto value = lexy::constant(true); - }; - struct false_ : lexy::transparent_production - { - static constexpr auto rule = LEXY_LIT("false"); - static constexpr auto value = lexy::constant(false); - }; - - static constexpr auto rule = dsl::p | dsl::p; - static constexpr auto value = lexy::forward; -}; - -// A json value that is a number. -struct number : lexy::token_production -{ - // A signed integer parsed as int64_t. - struct integer : lexy::transparent_production - { - static constexpr auto rule - = dsl::minus_sign + dsl::integer(dsl::digits<>.no_leading_zero()); - static constexpr auto value = lexy::as_integer; - }; - - // The fractional part of a number parsed as the string. - struct fraction : lexy::transparent_production - { - static constexpr auto rule = dsl::lit_c<'.'> >> dsl::capture(dsl::digits<>); - static constexpr auto value = lexy::as_string; - }; - - // The exponent of a number parsed as int64_t. - struct exponent : lexy::transparent_production - { - static constexpr auto rule = [] { - auto exp_char = dsl::lit_c<'e'> | dsl::lit_c<'E'>; - return exp_char >> dsl::sign + dsl::integer; - }(); - static constexpr auto value = lexy::as_integer; - }; - - static constexpr auto rule - = dsl::peek(dsl::lit_c<'-'> / dsl::digit<>) - >> dsl::p + dsl::opt(dsl::p) + dsl::opt(dsl::p); - static constexpr auto value = lexy::construct; -}; - -// A json value that is a string. -struct string : lexy::token_production -{ - struct invalid_char - { - static LEXY_CONSTEVAL auto name() - { - return "invalid character in string literal"; - } - }; - - // A mapping of the simple escape sequences to their replacement values. - static constexpr auto escaped_symbols = lexy::symbol_table // - .map<'"'>('"') - .map<'\\'>('\\') - .map<'/'>('/') - .map<'b'>('\b') - .map<'f'>('\f') - .map<'n'>('\n') - .map<'r'>('\r') - .map<'t'>('\t'); - - static constexpr auto rule = [] { - // Everything is allowed inside a string except for control characters. - auto code_point = (-dsl::unicode::control).error; - - // Escape sequences start with a backlash and either map one of the symbols, - // or a Unicode code point of the form uXXXX. - auto escape = dsl::backslash_escape // - .symbol() - .rule(dsl::lit_c<'u'> >> dsl::code_point_id<4>); - - // String of code_point with specified escape sequences, surrounded by ". - // We abort string parsing if we see a newline to handle missing closing ". - return dsl::quoted.limit(dsl::ascii::newline)(code_point, escape); - }(); - - static constexpr auto value = lexy::as_string; -}; - -struct unexpected_trailing_comma -{ - static constexpr auto name = "unexpected trailing comma"; -}; - -// A json value that is an array. -struct array -{ - // A (potentially empty) list of json values, seperated by comma and surrounded by square - // brackets. - static constexpr auto rule - = dsl::square_bracketed - .opt_list(dsl::recurse, - // Trailing seperators are not allowed. - // Use `dsl::trailing_sep()` if you want to allow it. - dsl::sep(dsl::comma).trailing_error); - - static constexpr auto value = lexy::as_list; -}; - -// A json value that is an object. -struct object -{ - static constexpr auto rule = [] { - // We try parsing the colon. This means that a missing colon raises an error, which is then - // caught and parsing continues as if nothing happens. Without the try, parsing the current - // item would be canceled immediately. - auto item = dsl::p + dsl::try_(dsl::colon) + dsl::recurse; - - // Trailing seperators are not allowed. - // Use `dsl::trailing_sep()` if you want to allow it. - auto sep = dsl::sep(dsl::comma).trailing_error; - - // A (potentially empty) list of items, seperated by comma and surrounded by curly brackets. - return dsl::curly_bracketed.opt_list(item, sep); - }(); - - static constexpr auto value = lexy::as_collection; -}; - -// A json value. -struct json_value : lexy::transparent_production -{ - static constexpr auto name = "json value"; - - struct expected_json_value - { - static LEXY_CONSTEVAL auto name() - { - return "expected json value"; - } - }; - - static constexpr auto rule = [] { - auto primitive = dsl::p | dsl::p | dsl::p | dsl::p; - auto complex = dsl::p | dsl::p; - - return primitive | complex | dsl::error; - }(); - - static constexpr auto value = lexy::construct; -}; - -// Entry point of the production. -struct json -{ - // The maximum level of nesting of JSON data structures, - // i.e. how many `dsl::recurse` calls are allowed. - // json.org comes with a test suite that checks for this nesting level. - static constexpr auto max_recursion_depth = 19; - - // Whitespace is a sequence of space, tab, carriage return, or newline. - // Add your comment syntax here. - static constexpr auto whitespace = dsl::ascii::space / dsl::ascii::newline; - - static constexpr auto rule = dsl::p + dsl::eof; - static constexpr auto value = lexy::forward; -}; -} // namespace grammar - -#ifndef LEXY_TEST -int main(int argc, char** argv) -{ - if (argc < 2) - { - std::fprintf(stderr, "usage: %s ", argv[0]); - return 1; - } - - // We're requiring UTF-8 input. - auto file = lexy::read_file(argv[1]); - if (!file) - { - std::fprintf(stderr, "file '%s' not found", argv[1]); - return 1; - } - - auto json = lexy::parse(file.buffer(), lexy_ext::report_error); - if (json.has_value()) - json.value().print(); - - if (!json) - return 2; -} -#endif - diff --git a/assembler/ext/src/lexy/examples/protobuf.cpp b/assembler/ext/src/lexy/examples/protobuf.cpp deleted file mode 100644 index e5288b76a6..0000000000 --- a/assembler/ext/src/lexy/examples/protobuf.cpp +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -// This examples parses a protobuf message in the binary encoding. -// It then prints the basic structure of it, without knowing the message definition. - -#include -#include -#include -#include -#include -#include - -#include // lexy::parse -#include // value callbacks -#include // lexy::dsl::* -#include // lexy::read_file -#include // lexy::visualize - -#include // lexy_ext::report_error - -// Stores a generic protobuf message. -namespace ast -{ -// wire type 0 -struct field_varint -{ - std::uint64_t value; - - void print() const - { - std::printf("%" PRIu64, value); - } -}; - -// wire type 5 -struct field_32 -{ - std::uint32_t value; - - void print() const - { - auto as_unsigned = value; - auto as_signed = (value << 1) ^ (value >> 31); - auto as_float = lexy::bit_cast(value); - std::printf("%" PRIu32 " / %" PRIi32 " / %f", as_unsigned, as_signed, as_float); - } -}; - -// wire type 2 -struct field_64 -{ - std::uint64_t value; - - void print() const - { - auto as_unsigned = value; - auto as_signed = (value << 1) ^ (value >> 63); - auto as_float = lexy::bit_cast(value); - std::printf("%" PRIu64 " / %" PRIi64 " / %f", as_unsigned, as_signed, as_float); - } -}; - -// wire type 2 -struct field_bytes -{ - // Essentially a string_view into a buffer. - lexy::buffer_lexeme value; - - void print() const - { - // We print the value as raw bytes. - // It could be a string or a nested message, but without the schema, we can't know it. - lexy::visualize(stdout, value); - } -}; - -using field_value = std::variant; - -struct field -{ - std::uint64_t number; - field_value value; - - void print() const - { - std::printf("%" PRIu64 ": ", number); - std::visit([](const auto& value) { value.print(); }, value); - std::printf("\n"); - } -}; - -using message = std::vector; -} // namespace ast - -// The binary encoding of a protobuf message. -// Follows the documentation here: https://developers.google.com/protocol-buffers/docs/encoding -namespace grammar -{ -namespace dsl = lexy::dsl; - -// Builds a varint. -// This does not handle overflow (it simply computes the value module 2**64), -// nor overlong encodings for simplicity. -// (This would be a nested class of varint, but C++'s constexpr requirements can't handle it). -class varint_builder -{ -public: - constexpr varint_builder() : result(0), bit_shift(0) {} - - void add_prefix_byte(std::uint8_t prefix) - { - auto value = prefix & 0b0111'1111u; - result |= (value << bit_shift); - bit_shift += 7; - } - - std::uint64_t finish(std::uint8_t last) - { - result |= (static_cast(last) << bit_shift); - return result; - } - -private: - std::uint64_t result; - unsigned bit_shift; -}; - -// A Base 128 varint. -struct varint -{ - struct missing_byte - { - static constexpr auto name = "missing varint byte"; - }; - - static constexpr auto rule = [] { - // The last byte has the MSB set to zero. - auto last_byte = dsl::bits(dsl::bit::_0, dsl::bit::any<7>).error; - // Other bytes have the MSB set to one. - auto prefix_byte = dsl::bits(dsl::bit::_1, dsl::bit::any<7>).error; - - // A varint is a list of prefix bytes terminated by the last byte. - // We convert each one into integers. - return dsl::terminator(dsl::bint8(last_byte)).opt_list(dsl::bint8(prefix_byte)); - }(); - - static constexpr auto value = [] { - // The rule passes each prefix byte to the sink. - // It then invokes the callback with either `(nullopt, last_byte)` if no prefix byte, - // or `(sink-result, last_byte)` if there were prefix byte. - - // As sink, we create a builder and call `add_prefix_byte()` for every byte that is part of - // the prefix list. - auto sink = lexy::fold_inplace({}, &varint_builder::add_prefix_byte); - - auto callback = lexy::callback( - // If we had no list, we create an empty builder and finish. - [](lexy::nullopt, std::uint8_t prefix) { return varint_builder().finish(prefix); }, - // Otherwise, we finish the existing builder. - &varint_builder::finish); - - return sink >> callback; - }(); -}; - -// Just parse a varint and convert to the field type. -struct field_varint -{ - static constexpr auto rule = dsl::p; - static constexpr auto value = lexy::construct; -}; - -// A little endian 32-bit number. -struct field_32 -{ - static constexpr auto rule = dsl::little_bint32; - static constexpr auto value = lexy::construct; -}; - -// A little endian 64-bit number. -struct field_64 -{ - static constexpr auto rule = dsl::little_bint64; - static constexpr auto value = lexy::construct; -}; - -// N bytes, where N is given by a varint. -struct field_bytes -{ - static constexpr auto rule = dsl::repeat(dsl::p).capture(dsl::byte); - static constexpr auto value = lexy::construct; -}; - -// The key of a field. -struct field_key -{ - struct result - { - std::uint64_t number; - int type; - }; - - // It's just a varint. - static constexpr auto rule = dsl::p; - // But we split it into the number and wire type. - static constexpr auto value = lexy::callback([](std::uint64_t v) { - return result{v >> 3, static_cast(v & 0b111)}; - }); -}; - -// A field needs to dispatch a production based on the wire type. -// We can't express that with the DSL, so need to manually parse it using the scanner. -struct field : lexy::scan_production -{ - struct unknown_field_type - { - static constexpr auto name = "unknown field type"; - }; - - // This function defines how we're parsing it. - // It also gets acess to any parse state passed to the action, - // so it could e.g. get a schema and receive additional type information based on that. - template - static scan_result scan(lexy::rule_scanner& scanner) - { - // We first parse a key. - auto key = scanner.parse(field_key{}); - if (!scanner) - return lexy::scan_failed; - - // And then parse the corresponding value. - lexy::scan_result value; - switch (key.value().type) - { - case 0: - scanner.parse(value, dsl::p); - break; - case 1: - scanner.parse(value, dsl::p); - break; - case 2: - scanner.parse(value, dsl::p); - break; - case 5: - scanner.parse(value, dsl::p); - break; - - default: - // We have an unknown wire type. - // Calling `fatal_error()` will put the scanner in a failed state, caught by the check - // below. - scanner.fatal_error(unknown_field_type{}, scanner.begin(), scanner.position()); - break; - } - if (!scanner) - return lexy::scan_failed; - - return ast::field{key.value().number, value.value()}; - } -}; - -// A message is a list of fields until we reach EOF. -struct message -{ - static constexpr auto rule = dsl::terminator(dsl::eof).opt_list(dsl::p); - static constexpr auto value = lexy::as_list; -}; -} // namespace grammar - -#ifndef LEXY_TEST -int main(int argc, char** argv) -{ - if (argc < 2) - { - std::fprintf(stderr, "usage: %s ", argv[0]); - return 1; - } - - // We're reading the file in binary. - auto file = lexy::read_file(argv[1]); - if (!file) - { - std::fprintf(stderr, "file '%s' not found", argv[1]); - return 1; - } - - auto result = lexy::parse(file.buffer(), lexy_ext::report_error); - if (!result) - return 2; - - for (auto& field : result.value()) - { - field.print(); - std::printf("\n"); - } -} -#endif - diff --git a/assembler/ext/src/lexy/examples/shell.cpp b/assembler/ext/src/lexy/examples/shell.cpp deleted file mode 100644 index 6363a5071f..0000000000 --- a/assembler/ext/src/lexy/examples/shell.cpp +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include -#include -#include - -#include -#include -#include - -// A shell with a couple of basic commands. -namespace shell -{ -struct interpreter -{ - // Manages I/O. - lexy_ext::shell> shell; - // The values of variables. - std::map variables; - - // Retrieves the value of a variable. - const std::string& lookup_var(const std::string& name) const - { - auto iter = variables.find(name); - if (iter == variables.end()) - { - static const std::string not_found; - return not_found; - } - - return iter->second; - } -}; - -// Special directives that control what happens with entered commands. -enum class directive -{ - // Command following it is executed (the default). - execute, - // Parsing of the command following it is traced. - trace, - // All variables are printed. - vars, -}; - -class cmd_base -{ -public: - virtual ~cmd_base() = default; - - // Returns true if the shell should exit. - virtual bool execute(interpreter& intp) const = 0; -}; -using command = std::unique_ptr; - -// Exits the shell. -class cmd_exit : public cmd_base -{ -public: - bool execute(interpreter& intp) const override - { - intp.shell.write_message()("Goodbye."); - return true; - } -}; - -// Prints output. -class cmd_echo : public cmd_base -{ -public: - explicit cmd_echo(std::string msg) : _msg(LEXY_MOV(msg)) {} - - bool execute(interpreter& intp) const override - { - intp.shell.write_message()(_msg.data(), _msg.size()); - return false; - } - -private: - std::string _msg; -}; - -// Sets the value of a variable. -class cmd_set : public cmd_base -{ -public: - explicit cmd_set(std::string name, std::string value) - : _name(LEXY_MOV(name)), _value(LEXY_MOV(value)) - {} - - bool execute(interpreter& intp) const override - { - intp.variables[_name] = _value; - return false; - } - -private: - std::string _name; - std::string _value; -}; -} // namespace shell - -namespace grammar -{ -namespace dsl = lexy::dsl; - -// A bare argument or command name. -constexpr auto identifier = dsl::identifier(dsl::ascii::alnum); - -//=== The arguments ===// -struct invalid_str_char -{ - static constexpr auto name = "invalid string character"; -}; - -// The content of a string literal: any unicode code point except for control characters. -constexpr auto str_char = (-dsl::unicode::control).error; - -// An unquoted sequence of characters. -struct arg_bare -{ - static constexpr auto rule = identifier; - static constexpr auto value = lexy::as_string; -}; - -// A string without escape characters. -struct arg_string -{ - static constexpr auto rule = dsl::single_quoted(str_char); - static constexpr auto value = lexy::as_string; -}; - -// A string with escape characters. -struct arg_quoted -{ - struct interpolation - { - static constexpr auto rule = dsl::curly_bracketed(dsl::recurse); - static constexpr auto value - = lexy::bind(lexy::callback(&shell::interpreter::lookup_var), - lexy::parse_state, lexy::values); - }; - - static constexpr auto escaped_sequences = lexy::symbol_table // - .map<'"'>('"') - .map<'\\'>('\\') - .map<'/'>('/') - .map<'b'>('\b') - .map<'f'>('\f') - .map<'n'>('\n') - .map<'r'>('\r') - .map<'t'>('\t'); - - static constexpr auto rule = [] { - // C style escape sequences. - auto backslash_escape = dsl::backslash_escape.symbol(); - // Interpolation. - auto dollar_escape = dsl::dollar_escape.rule(dsl::p); - - return dsl::quoted.limit(dsl::ascii::newline)(str_char, backslash_escape, dollar_escape); - }(); - static constexpr auto value = lexy::as_string; -}; - -// An argument that expands to the value of a variable. -struct arg_var -{ - static constexpr auto rule = [] { - auto bare = dsl::p; - auto bracketed = dsl::curly_bracketed(dsl::recurse); - auto name = bracketed | dsl::else_ >> bare; - - return dsl::dollar_sign >> name; - }(); - static constexpr auto value - = lexy::bind(lexy::callback(&shell::interpreter::lookup_var), - lexy::parse_state, lexy::values); -}; - -// An argument to a command. -struct argument -{ - struct invalid - { - static constexpr auto name = "invalid argument character"; - }; - - static constexpr auto rule = dsl::p | dsl::p // - | dsl::p | dsl::p // - | dsl::error; - static constexpr auto value = lexy::forward; -}; - -// The separator between arguments. -constexpr auto arg_sep = [] { - struct missing_argument - { - static constexpr auto name() - { - return "missing argument"; - } - }; - - auto blank = dsl::ascii::blank; - auto escaped_nl = dsl::backslash >> dsl::newline; - auto sep = dsl::must(blank | escaped_nl).error; - return dsl::while_one(sep); -}(); - -//=== the commands ===// -struct cmd_exit -{ - static constexpr auto rule = LEXY_KEYWORD("exit", identifier) | dsl::eof; - static constexpr auto value = lexy::new_; -}; - -struct cmd_echo -{ - static constexpr auto rule = LEXY_KEYWORD("echo", identifier) >> arg_sep + dsl::p; - static constexpr auto value = lexy::new_; -}; - -struct cmd_set -{ - static constexpr auto rule = LEXY_KEYWORD("set", identifier) - >> arg_sep + dsl::p + arg_sep + dsl::p; - static constexpr auto value = lexy::new_; -}; - -// Parses one of three commands. -struct command -{ - struct unknown_command - { - static constexpr auto name = "unknown command"; - }; - struct trailing_args - { - static constexpr auto name = "trailing command arguments"; - }; - - static constexpr auto rule = [] { - auto unknown = dsl::error(identifier); - auto commands = dsl::p | dsl::p // - | dsl::p | unknown; - - // Allow an optional argument separator after the final command, - // but then there should not be any other arguments after that. - return commands + dsl::if_(arg_sep) + dsl::peek(dsl::eol).error; - }(); - static constexpr auto value = lexy::forward; -}; - -//=== the directive ===// -// Parse an optional parsing directive with trailing separator. -// Note that it doesn't parse the following command, this is done manually. -struct directive -{ - struct unknown_directive - { - static constexpr auto name = "unknown directive"; - }; - - // Map pre-defined directives. - static constexpr auto directives - = lexy::symbol_table // - .map(shell::directive::execute) // - .map(shell::directive::trace) // - .map(shell::directive::vars); - - static constexpr auto rule = [] { - auto pattern = dsl::identifier(dsl::ascii::alpha); - auto directive = dsl::symbol(pattern).error; - - // A directive is optional, but it also consumes the argument separator if parsed. - return dsl::opt(dsl::colon >> directive + dsl::if_(arg_sep)); - }(); - - // Forward the existing directive but default to execute. - static constexpr auto value - = lexy::bind(lexy::forward, lexy::_1 or shell::directive::execute); -}; -} // namespace grammar - -#ifndef LEXY_TEST -# include -# include -# include -# include - -int main() -{ - for (shell::interpreter intp; intp.shell.is_open();) - { - // We repeatedly prompt for a new line. - // Note: everytime we do it, the memory of the previous line is cleared. - auto input = intp.shell.prompt_for_input(); - - // Use a scanner to handle the directives. - auto scanner = lexy::scan(input, lexy_ext::report_error); - // Parse a directive. - auto directive = scanner.parse(); - if (!scanner) - continue; - - auto exit = false; - switch (directive.value()) - { - case shell::directive::execute: { - // Parse the command in the remaining input... - auto result = lexy::parse(scanner.remaining_input(), intp, - lexy_ext::report_error); - if (result) - // ... and execute it. - exit = result.value()->execute(intp); - break; - } - - case shell::directive::trace: - // Trace the command in the remaining input. - lexy::trace_to(intp.shell.write_message().output_iterator(), - scanner.remaining_input(), {lexy::visualize_fancy}); - break; - - case shell::directive::vars: { - // Write all variables. - auto writer = intp.shell.write_message(); - for (auto [name, value] : intp.variables) - { - writer(name.data(), name.length()); - writer(" = "); - writer(value.data(), value.length()); - writer("\n"); - } - } - } - - if (exit) - break; - } -} -#endif - diff --git a/assembler/ext/src/lexy/examples/turing.cpp b/assembler/ext/src/lexy/examples/turing.cpp deleted file mode 100644 index ab8f5af142..0000000000 --- a/assembler/ext/src/lexy/examples/turing.cpp +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -// This example demonstrates that lexy is turing complete: -// it parses and executes (!) a simple programming language by abusing the context variables. -// Don't use these techniques in your real lexy programs. -// Read the corresponding blog post here: https://foonathan.net/2021/11/lexy-turing/ - -#include - -#include -#include -#include -#include -#include - -// We need to cheat a little bit and add a custom rule that parses a rule and rewinds the input. -// This is the same behavior as `dsl::peek()`, but `dsl::peek()` does not give access to the context -// variables, so we need to roll our own. -namespace dsl_ext -{ -template -struct _rewind : lexy::dsl::rule_base -{ - template - struct p - { - struct continuation - { - template - LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, - typename Reader::iterator saved_pos, Args&&... args) - { - reader.set_position(saved_pos); - return NextParser::parse(context, reader, LEXY_FWD(args)...); - } - }; - - template - LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args) - { - auto saved_pos = reader.position(); - return lexy::parser_for::parse(context, reader, saved_pos, - LEXY_FWD(args)...); - } - }; -}; - -template -constexpr auto rewind(Rule) -{ - return _rewind{}; -} -} // namespace dsl_ext - -// The grammar for our language. -// It consists of unsigned integer variables that can be assigned plus if and while statements. -namespace grammar -{ -namespace dsl = lexy::dsl; - -template -struct statement; - -//=== tokens ===// -constexpr auto comment = LEXY_LIT("//") >> dsl::until(dsl::ascii::newline); - -constexpr auto identifier = dsl::identifier(dsl::ascii::alpha); -constexpr auto kw_if = LEXY_KEYWORD("if", identifier); -constexpr auto kw_else = LEXY_KEYWORD("else", identifier); -constexpr auto kw_while = LEXY_KEYWORD("while", identifier); - -// Number literal in base 1, i.e. tally marks. -struct number : lexy::token_production -{ - static constexpr auto rule = dsl::while_(dsl::lit_c<'|'>); - static constexpr auto value = lexy::forward; -}; - -//=== variables ===// -template -struct var_id -{}; - -// A variable is an unsigned integer. -// (dsl::context_counter can be negative, but we can't implement assignment otherwise.) -template -constexpr auto var = dsl::context_counter>; - -struct unknown_variable -{ - static constexpr auto name = "unknown variable"; -}; -constexpr auto unknown_variable_error = dsl::error(identifier); - -//=== statements ===// -// Variable assignment/increment/decrement. -template -struct var_stmt -{ - static constexpr auto name = "var-stmt"; - - // Var := number | Var += number | Var -= number - static constexpr auto rule = [] { - // There is no rule to reset a counter, so we need to decrement it as necessary. - // (This requires non-negative values). - auto reset = dsl::loop(var.is_zero() >> dsl::break_ | dsl::else_ >> var.dec()); - - // Once it's zero, we add the number. - auto assign = LEXY_LIT(":=") >> reset + var.push(dsl::p); - - auto add = LEXY_LIT("+=") >> var.push(dsl::p); - auto dec = LEXY_LIT("-=") >> var.pop(dsl::p); - - return dsl::keyword(identifier) >> (assign | add | dec) + dsl::semicolon; - }(); - - static constexpr auto value = lexy::noop; -}; - -// Executes a body of an if/while. -template -struct execute_body -{ - static constexpr auto name = "execute-body"; - - // Parsing the body executes it. - static constexpr auto rule = dsl::curly_bracketed.opt_list(dsl::recurse>); - static constexpr auto value = lexy::forward; -}; - -// Skips until we find the next curly brackets, keeping track of the opening brackets. -struct skip_body -{ - static constexpr auto name = "skip-body"; - - static constexpr auto rule = [] { - auto bracket_counter = dsl::context_counter; - auto check_balance = dsl::if_(bracket_counter.is_zero() >> dsl::break_); - - auto open = LEXY_LIT("{") >> bracket_counter.inc(); - auto close = LEXY_LIT("}") >> bracket_counter.dec(); - auto skip = open | close | comment | dsl::ascii::character; - - return bracket_counter.create() + dsl::loop(skip + check_balance); - }(); - - static constexpr auto value = lexy::forward; -}; - -// Checks whether a variable is non-zero. -// if x { statments } else { statements } -// else is optional -template -struct if_stmt -{ - static constexpr auto name = "if-stmt"; - - template - struct impl - { - static constexpr auto name = "if-stmt-impl"; - - static constexpr auto rule = [] { - auto non_zero = dsl::p> + dsl::if_(kw_else >> dsl::p); - auto zero = dsl::p + dsl::if_(kw_else >> dsl::p>); - - // If the variable is zero, we skip, otherwise, we execute. - auto select = var.is_zero() >> zero | dsl::else_ >> non_zero; - - return dsl::lit_c >> select; - }(); - - static constexpr auto value = lexy::forward; - }; - - static constexpr auto rule = kw_if >> (dsl::p> | ... | unknown_variable_error); - static constexpr auto value = lexy::forward; -}; - -// Loops while a variable is non-zero. -// while x { statements } -template -struct while_stmt -{ - static constexpr auto name = "while-stmt"; - - template - struct impl - { - static constexpr auto name = "while-stmt-impl"; - - static constexpr auto rule = [] { - // After executing the body, rewind back. - auto non_zero = dsl_ext::rewind(dsl::p>); - // After skipping the body, we break. - auto zero = dsl::p + dsl::break_; - - // We repeatedly select execution or skipping. - auto loop = dsl::loop(var.is_zero() >> zero | dsl::else_ >> non_zero); - - return dsl::lit_c >> loop; - }(); - - static constexpr auto value = lexy::forward; - }; - - static constexpr auto rule = kw_while >> (dsl::p> | ... | unknown_variable_error); - static constexpr auto value = lexy::forward; -}; - -template -struct statement -{ - static constexpr auto name = "statement"; - - static constexpr auto rule = [] { - auto if_stmts = dsl::p>; - auto while_stmts = dsl::p>; - auto var_stmts = (dsl::p> | ... | unknown_variable_error); - - return if_stmts | while_stmts | dsl::else_ >> var_stmts; - }(); - - static constexpr auto value = lexy::forward; -}; - -//=== program ===// -// A program is a list of statements. -template -struct program -{ - static constexpr auto name = "program"; - - static constexpr auto whitespace = dsl::ascii::space | comment; - - static constexpr auto rule = [] { - // Create all variables (initialized to zero). - auto create = (var.create() + ...); - - // Parse (and thus execute) a list of statements. - auto run = dsl::loop(dsl::eof >> dsl::break_ | dsl::else_ >> dsl::p>); - - // We produce the value of o (for output) as the parse result. - auto output = var<'o'>.value(); - - return create + run + output; - }(); - - static constexpr auto value = lexy::construct; -}; -} // namespace grammar - -#ifndef LEXY_TEST -int main(int argc, char** argv) -{ - if (argc < 2) - { - std::fprintf(stderr, "usage: %s ", argv[0]); - return 1; - } - - auto file = lexy::read_file(argv[1]); - if (!file) - { - std::fprintf(stderr, "file '%s' not found", argv[1]); - return 1; - } - - // Note: this instantiates a lot of code and thus it takes a while to compile. - // (It is not representative of an actual lexy grammar). - using program - = grammar::program<'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'>; - auto result = lexy::parse(file.buffer(), lexy_ext::report_error); - if (!result) - return 2; - - std::printf("result: %d\n", result.value()); -} -#endif - diff --git a/assembler/ext/src/lexy/examples/xml.cpp b/assembler/ext/src/lexy/examples/xml.cpp deleted file mode 100644 index 6286e29379..0000000000 --- a/assembler/ext/src/lexy/examples/xml.cpp +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#include -#include -#include -#include - -#include // lexy::parse -#include // value callbacks -#include // lexy::dsl::* -#include // lexy::read_file - -#include // lexy_ext::report_error - -// Datastructures for storing XML. -// Not really the point of the example, so as simple as possible. -namespace ast -{ -class xml_node -{ -public: - xml_node(const xml_node&) = delete; - xml_node& operator=(const xml_node&) = delete; - virtual ~xml_node() = default; - - virtual void print() const = 0; - -protected: - xml_node() = default; -}; - -using xml_node_ptr = std::unique_ptr; - -class xml_text final : public xml_node -{ -public: - explicit xml_text(std::string text) : _text(std::move(text)) {} - - void print() const override - { - std::fputs(_text.c_str(), stdout); - } - -private: - std::string _text; -}; - -class xml_reference final : public xml_node -{ -public: - explicit xml_reference(char c) : _c(c) {} - - void print() const override - { - switch (_c) - { - case '"': - std::fputs(""", stdout); - break; - case '&': - std::fputs("&", stdout); - break; - case '\'': - std::fputs("'", stdout); - break; - case '<': - std::fputs("<", stdout); - break; - case '>': - std::fputs(">", stdout); - break; - } - } - -private: - char _c; -}; - -class xml_cdata final : public xml_node -{ -public: - explicit xml_cdata(std::string text) : _text(std::move(text)) {} - - void print() const override - { - std::printf("", _text.c_str()); - } - -private: - std::string _text; -}; - -class xml_element final : public xml_node -{ -public: - explicit xml_element(std::string tag, std::vector children = {}) - : _tag(std::move(tag)), _children(std::move(children)) - {} - - void print() const override - { - std::printf("<%s>", _tag.c_str()); - for (auto& child : _children) - child->print(); - std::printf("", _tag.c_str()); - } - -private: - std::string _tag; - std::vector _children; -}; -} // namespace ast - -// The grammar of (a subset of) XML. -// It does not support attributes, the XML prolog, doctype, or processing instructions. -// It also only supports the pre-defined entity references. -namespace grammar -{ -namespace dsl = lexy::dsl; - -// An invalid character error. -// Used with try_ to turn generic failures into more specific ones. -struct invalid_character -{ - static constexpr auto name() - { - return "invalid character"; - } -}; - -// Whitespace that is manually inserted in a couple of places. -constexpr auto ws = dsl::whitespace(dsl::ascii::space / dsl::ascii::newline); - -// Comment. -struct comment -{ - static constexpr auto rule = LEXY_LIT("")); - static constexpr auto value = lexy::forward; -}; - -// Non-markup content. -struct text -{ - static constexpr auto rule = [] { - auto char_ = (dsl::code_point - dsl::lit_c<'<'> - dsl::lit_c<'&'>).error; - return dsl::identifier(char_); - }(); - static constexpr auto value - = lexy::as_string | lexy::new_; -}; - -// The name of a tag or entity. -constexpr auto name = [] { - // We only support ASCII here, as I'm too lazy to type all the code point ranges out. - auto head_char = dsl::ascii::alpha / dsl::lit_c<':'> / dsl::lit_c<'_'>; - auto trailing_char = head_char / dsl::lit_c<'-'> / dsl::lit_c<'.'> / dsl::ascii::digit; - - return dsl::identifier(head_char.error, trailing_char); -}(); - -// A pre-defined entity reference. -struct reference -{ - struct unknown_entity - { - static LEXY_CONSTEVAL auto name() - { - return "unknown entity"; - } - }; - - // The predefined XML entities and their replacement values. - static constexpr auto entities = lexy::symbol_table - .map('"') - .map('&') - .map('\'') - .map('<') - .map('>'); - - static constexpr auto rule = [] { - // The actual reference parses a name and performs a lookup to produce the replacement - // values. - auto reference = dsl::symbol(name).error; - return dsl::lit_c<'&'> >> reference + dsl::lit_c<';'>; - }(); - static constexpr auto value = lexy::new_; -}; - -// A CDATA section. -struct cdata -{ - static constexpr auto rule = [] { - // We define a string with custom delimiters. - auto delim = dsl::delimited(LEXY_LIT("")); - return delim(dsl::code_point); - }(); - - // We build a string; then we construct a node from it. - static constexpr auto value - = lexy::as_string >> lexy::new_; -}; - -// A tagged XML element. -struct element -{ - struct tag_mismatch - { - static LEXY_CONSTEVAL auto name() - { - return "closing tag doesn't match"; - } - }; - - static constexpr auto rule = [] { - // The brackets for surrounding the opening and closing tag. - auto open_tagged = dsl::brackets(LEXY_LIT("<"), LEXY_LIT(">")); - auto close_tagged = dsl::brackets(LEXY_LIT("")); - - // To check that the name is equal for the opening and closing tag, - // we use a variable that can store one name. - // Note: this only declares the variable, we still need to create it below. - auto name_var = dsl::context_identifier(name); - - // The open tag parses a name and captures it in the variable. - // It also checks for an empty tag (), in which case we're done and immediately - // return. - auto empty = dsl::if_(LEXY_LIT("/") >> LEXY_LIT(">") + dsl::return_); - auto open_tag = open_tagged(name_var.capture() + ws + empty); - - // The closing tag matches the name again and requires that it matches the one we've stored - // earlier. - auto close_tag = close_tagged(name_var.rematch().error + ws); - - // The content of the element. - auto content = dsl::p | dsl::p // - | dsl::peek(LEXY_LIT("<")) >> dsl::recurse // - | dsl::p | dsl::else_ >> dsl::p; - - // We match a (possibly empty) list of content surrounded itself by the open and close tag. - // But first we create the variable that holds the name. - return name_var.create() + dsl::brackets(open_tag, close_tag).opt_list(content); - }(); - - // We collect the children as vector; then we construct a node from it. - static constexpr auto value - = lexy::as_list> >> lexy::callback( - [](auto name, lexy::nullopt = {}) { - return std::make_unique(lexy::as_string(name)); - }, - [](auto name, auto&& children) { - return std::make_unique(lexy::as_string(name), - LEXY_MOV(children)); - }); -}; - -// An XML document. -struct document -{ - static constexpr auto rule = [] { - // We allow surrounding the document with comments and whitespace. - // (Whitespace does not allow productions, so we need to inline it). - auto ws_comment = ws | dsl::inline_; - return ws_comment + dsl::p + ws_comment + dsl::eof; - }(); - static constexpr auto value = lexy::forward; -}; -} // namespace grammar - -#ifndef LEXY_TEST -int main(int argc, char** argv) -{ - if (argc < 2) - { - std::fprintf(stderr, "usage: %s ", argv[0]); - return 1; - } - - // We assume UTF-8 encoded input. - auto file = lexy::read_file(argv[1]); - if (!file) - { - std::fprintf(stderr, "file '%s' not found", argv[1]); - return 1; - } - - auto document = lexy::parse(file.buffer(), lexy_ext::report_error); - if (!document) - return 2; - - document.value()->print(); -} -#endif - diff --git a/assembler/ext/src/lexy/include/lexy/_detail/assert.hpp b/assembler/ext/src/lexy/include/lexy/_detail/assert.hpp deleted file mode 100644 index a2b7f7f7ab..0000000000 --- a/assembler/ext/src/lexy/include/lexy/_detail/assert.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#ifndef LEXY_DETAIL_ASSERT_HPP_INCLUDED -#define LEXY_DETAIL_ASSERT_HPP_INCLUDED - -#include - -#ifndef LEXY_ENABLE_ASSERT - -// By default, enable assertions if NDEBUG is not defined. - -# if NDEBUG -# define LEXY_ENABLE_ASSERT 0 -# else -# define LEXY_ENABLE_ASSERT 1 -# endif - -#endif - -#if LEXY_ENABLE_ASSERT - -// We want assertions: use assert() if that's available, otherwise abort. -// We don't use assert() directly as that's not constexpr. - -# if NDEBUG - -# include -# define LEXY_PRECONDITION(Expr) ((Expr) ? void(0) : std::abort()) -# define LEXY_ASSERT(Expr, Msg) ((Expr) ? void(0) : std::abort()) - -# else - -# include - -# define LEXY_PRECONDITION(Expr) ((Expr) ? void(0) : assert(Expr)) -# define LEXY_ASSERT(Expr, Msg) ((Expr) ? void(0) : assert((Expr) && (Msg))) - -# endif - -#else - -// We don't want assertions. - -# define LEXY_PRECONDITION(Expr) static_cast(sizeof(Expr)) -# define LEXY_ASSERT(Expr, Msg) static_cast(sizeof(Expr)) - -#endif - -#endif // LEXY_DETAIL_ASSERT_HPP_INCLUDED - diff --git a/assembler/ext/src/lexy/include/lexy/_detail/buffer_builder.hpp b/assembler/ext/src/lexy/include/lexy/_detail/buffer_builder.hpp deleted file mode 100644 index bfa7c49020..0000000000 --- a/assembler/ext/src/lexy/include/lexy/_detail/buffer_builder.hpp +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#ifndef LEXY_DETAIL_BUFFER_BUILDER_HPP_INCLUDED -#define LEXY_DETAIL_BUFFER_BUILDER_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace lexy::_detail -{ -// Builds a buffer: it has a read are and a write area. -// The characters in the read area are already valid and can be read. -// The characters in the write area are not valid, but can be written too. -template -class buffer_builder -{ - static_assert(std::is_trivial_v); - - static constexpr std::size_t total_size_bytes = 1024; - static constexpr std::size_t stack_buffer_size - = (total_size_bytes - 3 * sizeof(T*)) / sizeof(T); - static constexpr auto growth_factor = 2; - -public: - buffer_builder() noexcept : _data(_stack_buffer), _read_size(0), _write_size(stack_buffer_size) - { - static_assert(sizeof(*this) == total_size_bytes, "invalid buffer size calculation"); - } - - ~buffer_builder() noexcept - { - // Free memory if we allocated any. - if (_data != _stack_buffer) - ::operator delete(_data); - } - - buffer_builder(const buffer_builder&) = delete; - buffer_builder& operator=(const buffer_builder&) = delete; - - // The total capacity: read + write. - std::size_t capacity() const noexcept - { - return _read_size + _write_size; - } - - // The read area. - const T* read_data() const noexcept - { - return _data; - } - std::size_t read_size() const noexcept - { - return _read_size; - } - - // The write area. - T* write_data() noexcept - { - return _data + _read_size; - } - std::size_t write_size() const noexcept - { - return _write_size; - } - - // Clears the read area. - void clear() noexcept - { - _write_size += _read_size; - _read_size = 0; - } - - // Takes the first n characters of the write area and appends them to the read area. - void commit(std::size_t n) noexcept - { - LEXY_PRECONDITION(n <= _write_size); - _read_size += n; - _write_size -= n; - } - - // Increases the write area, invalidates all pointers. - void grow() - { - const auto cur_cap = capacity(); - const auto new_cap = growth_factor * cur_cap; - - // Allocate new memory. - auto memory = static_cast(::operator new(new_cap * sizeof(T))); - // Copy the read area into the new memory. - std::memcpy(memory, _data, _read_size); - - // Release the old memory, if there was any. - if (_data != _stack_buffer) - ::operator delete(_data); - - // Update for the new area. - _data = memory; - // _read_size hasn't been changed - _write_size = new_cap - _read_size; - } - - //=== iterator ===// - // Stable iterator over the memory. - class stable_iterator : public forward_iterator_base - { - public: - constexpr stable_iterator() = default; - - explicit constexpr stable_iterator(const _detail::buffer_builder& buffer, - std::size_t idx) noexcept - : _buffer(&buffer), _idx(idx) - {} - - constexpr const T& deref() const noexcept - { - LEXY_PRECONDITION(_idx != _buffer->read_size()); - return _buffer->read_data()[_idx]; - } - - constexpr void increment() noexcept - { - LEXY_PRECONDITION(_idx != _buffer->read_size()); - ++_idx; - } - - constexpr bool equal(stable_iterator rhs) const noexcept - { - if (!_buffer || !rhs._buffer) - return !_buffer && !rhs._buffer; - else - { - LEXY_PRECONDITION(_buffer == rhs._buffer); - return _idx == rhs._idx; - } - } - - constexpr std::size_t index() const noexcept - { - return _idx; - } - - private: - const _detail::buffer_builder* _buffer = nullptr; - std::size_t _idx = 0; - }; - -private: - T* _data; - std::size_t _read_size; - std::size_t _write_size; - T _stack_buffer[stack_buffer_size]; -}; -} // namespace lexy::_detail - -#endif // LEXY_DETAIL_BUFFER_BUILDER_HPP_INCLUDED - diff --git a/assembler/ext/src/lexy/include/lexy/_detail/code_point.hpp b/assembler/ext/src/lexy/include/lexy/_detail/code_point.hpp deleted file mode 100644 index c72bf0639c..0000000000 --- a/assembler/ext/src/lexy/include/lexy/_detail/code_point.hpp +++ /dev/null @@ -1,363 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#ifndef LEXY_DETAIL_CODE_POINT_HPP_INCLUDED -#define LEXY_DETAIL_CODE_POINT_HPP_INCLUDED - -#include - -//=== encoding ===// -namespace lexy::_detail -{ -template -constexpr std::size_t encode_code_point(char32_t cp, typename Encoding::char_type* buffer, - std::size_t size) -{ - if constexpr (std::is_same_v) - { - LEXY_PRECONDITION(size >= 1); - - *buffer = char(cp); - return 1; - } - else if constexpr (std::is_same_v) - { - // Taken from http://www.herongyang.com/Unicode/UTF-8-UTF-8-Encoding-Algorithm.html. - if (cp <= 0x7F) - { - LEXY_PRECONDITION(size >= 1); - - buffer[0] = LEXY_CHAR8_T(cp); - return 1; - } - else if (cp <= 0x07'FF) - { - LEXY_PRECONDITION(size >= 2); - - auto first = (cp >> 6) & 0x1F; - auto second = (cp >> 0) & 0x3F; - - buffer[0] = LEXY_CHAR8_T(0xC0 | first); - buffer[1] = LEXY_CHAR8_T(0x80 | second); - return 2; - } - else if (cp <= 0xFF'FF) - { - LEXY_PRECONDITION(size >= 3); - - auto first = (cp >> 12) & 0x0F; - auto second = (cp >> 6) & 0x3F; - auto third = (cp >> 0) & 0x3F; - - buffer[0] = LEXY_CHAR8_T(0xE0 | first); - buffer[1] = LEXY_CHAR8_T(0x80 | second); - buffer[2] = LEXY_CHAR8_T(0x80 | third); - return 3; - } - else - { - LEXY_PRECONDITION(size >= 4); - - auto first = (cp >> 18) & 0x07; - auto second = (cp >> 12) & 0x3F; - auto third = (cp >> 6) & 0x3F; - auto fourth = (cp >> 0) & 0x3F; - - buffer[0] = LEXY_CHAR8_T(0xF0 | first); - buffer[1] = LEXY_CHAR8_T(0x80 | second); - buffer[2] = LEXY_CHAR8_T(0x80 | third); - buffer[3] = LEXY_CHAR8_T(0x80 | fourth); - return 4; - } - } - else if constexpr (std::is_same_v) - { - if (cp <= 0xFF'FF) - { - LEXY_PRECONDITION(size >= 1); - - buffer[0] = char16_t(cp); - return 1; - } - else - { - // Algorithm implemented from - // https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF. - LEXY_PRECONDITION(size >= 2); - - auto u_prime = cp - 0x1'0000; - auto high_ten_bits = u_prime >> 10; - auto low_ten_bits = u_prime & 0b0000'0011'1111'1111; - - buffer[0] = char16_t(0xD800 + high_ten_bits); - buffer[1] = char16_t(0xDC00 + low_ten_bits); - return 2; - } - } - else if constexpr (std::is_same_v) - { - LEXY_PRECONDITION(size >= 1); - - *buffer = char32_t(cp); - return 1; - } - else - { - static_assert(lexy::_detail::error, - "cannot encode a code point in this encoding"); - (void)cp; - (void)buffer; - (void)size; - return 0; - } -} -} // namespace lexy::_detail - -//=== parsing ===// -namespace lexy::_detail -{ -enum class cp_error -{ - success, - eof, - leads_with_trailing, - missing_trailing, - surrogate, - overlong_sequence, - out_of_range, -}; - -template -struct cp_result -{ - char32_t cp; - cp_error error; - typename Reader::iterator end; -}; - -template -constexpr cp_result parse_code_point(Reader reader) -{ - if constexpr (std::is_same_v) - { - if (reader.peek() == Reader::encoding::eof()) - return {{}, cp_error::eof, reader.position()}; - - auto cur = reader.peek(); - reader.bump(); - - auto cp = static_cast(cur); - if (cp <= 0x7F) - return {cp, cp_error::success, reader.position()}; - else - return {cp, cp_error::out_of_range, reader.position()}; - } - else if constexpr (std::is_same_v) - { - constexpr auto payload_lead1 = 0b0111'1111; - constexpr auto payload_lead2 = 0b0001'1111; - constexpr auto payload_lead3 = 0b0000'1111; - constexpr auto payload_lead4 = 0b0000'0111; - constexpr auto payload_cont = 0b0011'1111; - - constexpr auto pattern_lead1 = 0b0 << 7; - constexpr auto pattern_lead2 = 0b110 << 5; - constexpr auto pattern_lead3 = 0b1110 << 4; - constexpr auto pattern_lead4 = 0b11110 << 3; - constexpr auto pattern_cont = 0b10 << 6; - - auto first = reader.peek(); - if ((first & ~payload_lead1) == pattern_lead1) - { - // ASCII character. - reader.bump(); - return {first, cp_error::success, reader.position()}; - } - else if ((first & ~payload_cont) == pattern_cont) - { - return {{}, cp_error::leads_with_trailing, reader.position()}; - } - else if ((first & ~payload_lead2) == pattern_lead2) - { - reader.bump(); - - auto second = reader.peek(); - if ((second & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.position()}; - reader.bump(); - - auto result = char32_t(first & payload_lead2); - result <<= 6; - result |= char32_t(second & payload_cont); - - // C0 and C1 are overlong ASCII. - if (first == 0xC0 || first == 0xC1) - return {result, cp_error::overlong_sequence, reader.position()}; - else - return {result, cp_error::success, reader.position()}; - } - else if ((first & ~payload_lead3) == pattern_lead3) - { - reader.bump(); - - auto second = reader.peek(); - if ((second & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.position()}; - reader.bump(); - - auto third = reader.peek(); - if ((third & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.position()}; - reader.bump(); - - auto result = char32_t(first & payload_lead3); - result <<= 6; - result |= char32_t(second & payload_cont); - result <<= 6; - result |= char32_t(third & payload_cont); - - auto cp = result; - if (0xD800 <= cp && cp <= 0xDFFF) - return {cp, cp_error::surrogate, reader.position()}; - else if (first == 0xE0 && second < 0xA0) - return {cp, cp_error::overlong_sequence, reader.position()}; - else - return {cp, cp_error::success, reader.position()}; - } - else if ((first & ~payload_lead4) == pattern_lead4) - { - reader.bump(); - - auto second = reader.peek(); - if ((second & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.position()}; - reader.bump(); - - auto third = reader.peek(); - if ((third & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.position()}; - reader.bump(); - - auto fourth = reader.peek(); - if ((fourth & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.position()}; - reader.bump(); - - auto result = char32_t(first & payload_lead4); - result <<= 6; - result |= char32_t(second & payload_cont); - result <<= 6; - result |= char32_t(third & payload_cont); - result <<= 6; - result |= char32_t(fourth & payload_cont); - - auto cp = result; - if (cp > 0x10'FFFF) - return {cp, cp_error::out_of_range, reader.position()}; - else if (first == 0xF0 && second < 0x90) - return {cp, cp_error::overlong_sequence, reader.position()}; - else - return {cp, cp_error::success, reader.position()}; - } - else // FE or FF - { - return {{}, cp_error::eof, reader.position()}; - } - } - else if constexpr (std::is_same_v) - { - constexpr auto payload1 = 0b0000'0011'1111'1111; - constexpr auto payload2 = payload1; - - constexpr auto pattern1 = 0b110110 << 10; - constexpr auto pattern2 = 0b110111 << 10; - - if (reader.peek() == Reader::encoding::eof()) - return {{}, cp_error::eof, reader.position()}; - - auto first = char16_t(reader.peek()); - if ((first & ~payload1) == pattern1) - { - reader.bump(); - if (reader.peek() == Reader::encoding::eof()) - return {{}, cp_error::missing_trailing, reader.position()}; - - auto second = char16_t(reader.peek()); - if ((second & ~payload2) != pattern2) - return {{}, cp_error::missing_trailing, reader.position()}; - reader.bump(); - - // We've got a valid code point. - auto result = char32_t(first & payload1); - result <<= 10; - result |= char32_t(second & payload2); - result |= 0x10000; - return {result, cp_error::success, reader.position()}; - } - else if ((first & ~payload2) == pattern2) - { - return {{}, cp_error::leads_with_trailing, reader.position()}; - } - else - { - // Single code unit code point; always valid. - reader.bump(); - return {first, cp_error::success, reader.position()}; - } - } - else if constexpr (std::is_same_v) - { - if (reader.peek() == Reader::encoding::eof()) - return {{}, cp_error::eof, reader.position()}; - - auto cur = reader.peek(); - reader.bump(); - - auto cp = cur; - if (cp > 0x10'FFFF) - return {cp, cp_error::out_of_range, reader.position()}; - else if (0xD800 <= cp && cp <= 0xDFFF) - return {cp, cp_error::surrogate, reader.position()}; - else - return {cp, cp_error::success, reader.position()}; - } - else - { - static_assert(lexy::_detail::error, - "no known code point for this encoding"); - return {}; - } -} - -template -constexpr void recover_code_point(Reader& reader, cp_result result) -{ - switch (result.error) - { - case cp_error::success: - // Consume the entire code point. - reader.set_position(result.end); - break; - case cp_error::eof: - // We don't need to do anything to "recover" from EOF. - break; - - case cp_error::leads_with_trailing: - // Invalid code unit, consume to recover. - LEXY_PRECONDITION(result.end == reader.position()); - reader.bump(); - break; - - case cp_error::missing_trailing: - case cp_error::surrogate: - case cp_error::out_of_range: - case cp_error::overlong_sequence: - // Consume all the invalid code units to recover. - reader.set_position(result.end); - break; - } -} -} // namespace lexy::_detail - -#endif // LEXY_DETAIL_CODE_POINT_HPP_INCLUDED - diff --git a/assembler/ext/src/lexy/include/lexy/_detail/config.hpp b/assembler/ext/src/lexy/include/lexy/_detail/config.hpp deleted file mode 100644 index 7b6375e222..0000000000 --- a/assembler/ext/src/lexy/include/lexy/_detail/config.hpp +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (C) 2020-2022 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#ifndef LEXY_DETAIL_CONFIG_HPP_INCLUDED -#define LEXY_DETAIL_CONFIG_HPP_INCLUDED - -#include -#include - -#if defined(LEXY_USER_CONFIG_HEADER) -# include LEXY_USER_CONFIG_HEADER -#elif defined(__has_include) -# if __has_include() -# include -# elif __has_include("lexy_user_config.hpp") -# include "lexy_user_config.hpp" -# endif -#endif - -//=== utility traits===// -#define LEXY_MOV(...) static_cast&&>(__VA_ARGS__) -#define LEXY_FWD(...) static_cast(__VA_ARGS__) - -#define LEXY_DECLVAL(...) \ - reinterpret_cast<::lexy::_detail::add_rvalue_ref<__VA_ARGS__>>(*reinterpret_cast(1024)) - -#define LEXY_DECAY_DECLTYPE(...) std::decay_t - -/// Creates a new type from the instantiation of a template. -/// This is used to shorten type names. -#define LEXY_INSTANTIATION_NEWTYPE(Name, Templ, ...) \ - struct Name : Templ<__VA_ARGS__> \ - { \ - using Templ<__VA_ARGS__>::Templ; \ - } - -namespace lexy::_detail -{ -template -using add_rvalue_ref = T&&; - -template -constexpr bool error = false; - -template -constexpr void swap(T& lhs, T& rhs) -{ - T tmp = LEXY_MOV(lhs); - lhs = LEXY_MOV(rhs); - rhs = LEXY_MOV(tmp); -} - -template -constexpr bool is_decayed_same = std::is_same_v, std::decay_t>; - -template -using type_or = std::conditional_t, Fallback, T>; -} // namespace lexy::_detail - -//=== NTTP ===// -#ifndef LEXY_HAS_NTTP -// See https://github.com/foonathan/lexy/issues/15. -# if __cpp_nontype_template_parameter_class >= 201806 || __cpp_nontype_template_args >= 201911 -# define LEXY_HAS_NTTP 1 -# else -# define LEXY_HAS_NTTP 0 -# endif -#endif - -//=== consteval ===// -#ifndef LEXY_HAS_CONSTEVAL -# if defined(_MSC_VER) && !defined(__clang__) -// Currently can't handle returning strings from consteval, check back later. -# define LEXY_HAS_CONSTEVAL 0 -# elif __cpp_consteval -# define LEXY_HAS_CONSTEVAL 1 -# else -# define LEXY_HAS_CONSTEVAL 0 -# endif -#endif - -#if LEXY_HAS_CONSTEVAL -# define LEXY_CONSTEVAL consteval -#else -# define LEXY_CONSTEVAL constexpr -#endif - -//=== char8_t ===// -#ifndef LEXY_HAS_CHAR8_T -# if __cpp_char8_t -# define LEXY_HAS_CHAR8_T 1 -# else -# define LEXY_HAS_CHAR8_T 0 -# endif -#endif - -#if LEXY_HAS_CHAR8_T - -# define LEXY_CHAR_OF_u8 char8_t -# define LEXY_CHAR8_T char8_t -# define LEXY_CHAR8_STR(Str) u8##Str - -#else - -namespace lexy -{ -using _char8_t = unsigned char; -} // namespace lexy - -# define LEXY_CHAR_OF_u8 char -# define LEXY_CHAR8_T ::lexy::_char8_t -# define LEXY_CHAR8_STR(Str) \ - LEXY_NTTP_STRING(::lexy::_detail::type_string, u8##Str)::c_str - -#endif - -//=== endianness ===// -#ifndef LEXY_IS_LITTLE_ENDIAN -# if defined(__BYTE_ORDER__) -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define LEXY_IS_LITTLE_ENDIAN 1 -# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# define LEXY_IS_LITTLE_ENDIAN 0 -# else -# error "unsupported byte order" -# endif -# elif defined(_MSC_VER) -# define LEXY_IS_LITTLE_ENDIAN 1 -# else -# error "unknown endianness" -# endif -#endif - -//=== force inline ===// -#ifndef LEXY_FORCE_INLINE -# if defined(__has_cpp_attribute) -# if __has_cpp_attribute(gnu::always_inline) -# define LEXY_FORCE_INLINE [[gnu::always_inline]] -# endif -# endif -# -# ifndef LEXY_FORCE_INLINE -# define LEXY_FORCE_INLINE inline -# endif -#endif - -//=== empty_member ===// -#ifndef LEXY_EMPTY_MEMBER - -# if defined(__has_cpp_attribute) -# if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 11 -// GCC <= 11 has buggy support, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101040 -# define LEXY_HAS_EMPTY_MEMBER 0 -# elif __has_cpp_attribute(no_unique_address) -# define LEXY_HAS_EMPTY_MEMBER 1 -# endif -# endif -# ifndef LEXY_HAS_EMPTY_MEMBER -# define LEXY_HAS_EMPTY_MEMBER 0 -# endif - -# if LEXY_HAS_EMPTY_MEMBER -# define LEXY_EMPTY_MEMBER [[no_unique_address]] -# else -# define LEXY_EMPTY_MEMBER -# endif - -#endif - -#endif // LEXY_DETAIL_CONFIG_HPP_INCLUDED - diff --git a/assembler/ext/src/lexy/include/lexy/_detail/detect.hpp b/assembler/ext/src/lexy/include/lexy/_detail/detect.hpp deleted file mode 100644 index 9aae72b6ec..0000000000 --- a/assembler/ext/src/lexy/include/lexy/_detail/detect.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2020-2021 Müller -// SPDX-License-Identifier: BSL-1.0 - -#ifndef LEXY_DETAIL_DETECT_HPP_INCLUDED -#define LEXY_DETAIL_DETECT_HPP_INCLUDED - -#include - -namespace lexy::_detail -{ -template -using void_t = void; - -template