mirror of
https://github.com/boostorg/spirit.git
synced 2026-01-19 04:42:11 +00:00
Merge pull request #831 from saki7/revert-modernization
Revert modernization
This commit is contained in:
77
.appveyor.yml
Normal file
77
.appveyor.yml
Normal file
@@ -0,0 +1,77 @@
|
||||
#==============================================================================
|
||||
# Copyright (c) 2016-2020 Nikita Kniazev
|
||||
#
|
||||
# Use, modification and distribution is subject to the Boost Software
|
||||
# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#==============================================================================
|
||||
|
||||
clone_depth: 50
|
||||
|
||||
environment:
|
||||
global:
|
||||
PROJECT: libs\spirit
|
||||
|
||||
matrix:
|
||||
- { APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2019', ADDRMDL: 64, TOOLSET: 'msvc-14.2' }
|
||||
- { APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017', ADDRMDL: 64, TOOLSET: 'msvc-14.1' }
|
||||
- { APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015', ADDRMDL: 64, TOOLSET: 'msvc-14.0' }
|
||||
|
||||
init:
|
||||
- set BOOST_ROOT=%APPVEYOR_BUILD_FOLDER%\..\boost
|
||||
- set BOOST_BUILD_PATH=%BOOST_ROOT%\..\boost-build
|
||||
- set B2_ARGS=link=shared threading=multi variant=release
|
||||
address-model=%ADDRMDL% toolset=%TOOLSET%
|
||||
define=BOOST_ALL_NO_LIB
|
||||
define=BOOST_SPIRIT_X3_HIDE_CXX17_WARNING
|
||||
|
||||
before_build:
|
||||
- set PATH=%BOOST_ROOT%;C:\Python36-x64\Scripts;%PATH%
|
||||
- ps: |
|
||||
# Creating %USERPROFILE%/user-config.jam file
|
||||
@'
|
||||
|
||||
import feature os regex toolset pch ;
|
||||
|
||||
|
||||
# A subfeature that tells Spirit tests to use PCH
|
||||
feature.subfeature pch on : version : spirit : optional propagated incidental ;
|
||||
|
||||
'@ | sc "$env:USERPROFILE/user-config.jam"
|
||||
|
||||
- set BRANCH=%APPVEYOR_REPO_BRANCH%
|
||||
# TODO: Determine the root branch when PR targeted/build from not our main branches.
|
||||
- if not "%BRANCH%" == "master"
|
||||
if not "%BRANCH%" == "develop"
|
||||
set BRANCH=develop
|
||||
- echo Root branch is %BRANCH%
|
||||
|
||||
# Sadly git's --shallow-submodules has hardcoded depth of 1 commit
|
||||
# Patch the git binary with a little more depth to deal with boost-commitbot's lag
|
||||
- ps: |
|
||||
$git = Get-Command git | Select-Object -ExpandProperty Definition
|
||||
$git = Split-Path -Parent $git | Split-Path -Parent
|
||||
Get-ChildItem -Path "$git\mingw64\*" -Include *.exe -Recurse |
|
||||
ForEach-Object -Process {(Get-Content -Raw $_).Replace("--depth=1","--depth=9") | Set-Content $_}
|
||||
|
||||
# Checkout Boost
|
||||
- git clone -j10 --branch=%BRANCH% --depth=1 --quiet
|
||||
--recurse-submodules=":(exclude)%PROJECT%" --shallow-submodules
|
||||
https://github.com/boostorg/boost.git %BOOST_ROOT%
|
||||
- pushd %BOOST_ROOT%
|
||||
# Remove empty folder
|
||||
- rmdir /S /Q %PROJECT%
|
||||
# Move the repository to boost/libs and make a link to previous place
|
||||
- move %APPVEYOR_BUILD_FOLDER% %PROJECT%
|
||||
- mklink /J %APPVEYOR_BUILD_FOLDER% %PROJECT%
|
||||
|
||||
build_script:
|
||||
- bootstrap.bat --with-toolset=msvc
|
||||
|
||||
# Let's have less noise (Appveyor cannot collapse command output)
|
||||
- b2 headers 2>&1 >> deps_build.log
|
||||
|| ( echo === deps_build.log === && cat deps_build.log )
|
||||
|
||||
test_script:
|
||||
- b2 %B2_ARGS% %PROJECT%\classic\test %PROJECT%\repository\test %PROJECT%\test
|
||||
warnings=extra warnings-as-errors=on pch=on-spirit
|
||||
50
.drone.star
Normal file
50
.drone.star
Normal file
@@ -0,0 +1,50 @@
|
||||
# Use, modification, and distribution are
|
||||
# subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE.txt)
|
||||
#
|
||||
# Copyright Rene Rivera 2020.
|
||||
|
||||
# For Drone CI we use the Starlark scripting language to reduce duplication.
|
||||
# As the yaml syntax for Drone CI is rather limited.
|
||||
#
|
||||
#
|
||||
globalenv={'PROJECT': 'libs/spirit'}
|
||||
linuxglobalimage="cppalliance/droneubuntu1804:1"
|
||||
windowsglobalimage="cppalliance/dronevs2019"
|
||||
|
||||
def main(ctx):
|
||||
return [
|
||||
linux_cxx("STD=14 JOB=test/x3 Job 0", "clang-10", packages="clang-10 libc++-10-dev libc++abi-10-dev jq", llvm_os="bionic", llvm_ver="10", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '14', 'JOB': 'test/x3', 'TRAVIS_COMPILER': 'clang-10', 'DRONE_JOB_UUID': 'b6589fc6ab'}, globalenv=globalenv),
|
||||
linux_cxx("STD=14 JOB=test/x3 Job 1", "gcc-10", packages="g++-10 jq", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '14', 'JOB': 'test/x3', 'TRAVIS_COMPILER': 'gcc-10', 'DRONE_JOB_UUID': '356a192b79'}, globalenv=globalenv),
|
||||
linux_cxx("STD=11 JOB=test/qi Job 2", "clang-10", packages="clang-10 libc++-10-dev libc++abi-10-dev jq", llvm_os="bionic", llvm_ver="10", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '11', 'JOB': 'test/qi', 'TRAVIS_COMPILER': 'clang-10', 'DRONE_JOB_UUID': 'da4b9237ba'}, globalenv=globalenv),
|
||||
linux_cxx("STD=11 JOB=test/karma Job 3", "clang-10", packages="clang-10 libc++-10-dev libc++abi-10-dev jq", llvm_os="bionic", llvm_ver="10", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '11', 'JOB': 'test/karma', 'TRAVIS_COMPILER': 'clang-10', 'DRONE_JOB_UUID': '77de68daec'}, globalenv=globalenv),
|
||||
linux_cxx("STD=11 JOB=test/lex Job 4", "clang-10", packages="clang-10 libc++-10-dev libc++abi-10-dev jq", llvm_os="bionic", llvm_ver="10", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '11', 'JOB': 'test/lex', 'TRAVIS_COMPILER': 'clang-10', 'DRONE_JOB_UUID': '1b64538924'}, globalenv=globalenv),
|
||||
linux_cxx("STD=11 JOB=test/support Job 5", "clang-10", packages="clang-10 libc++-10-dev libc++abi-10-dev jq", llvm_os="bionic", llvm_ver="10", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '11', 'JOB': 'test/support', 'TRAVIS_COMPILER': 'clang-10', 'DRONE_JOB_UUID': 'ac3478d69a'}, globalenv=globalenv),
|
||||
linux_cxx("STD=11 JOB=repository/test Job 6", "clang-10", packages="clang-10 libc++-10-dev libc++abi-10-dev jq", llvm_os="bionic", llvm_ver="10", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '11', 'JOB': 'repository/test', 'TRAVIS_COMPILER': 'clang-10', 'DRONE_JOB_UUID': 'c1dfd96eea'}, globalenv=globalenv),
|
||||
# Not building #
|
||||
# linux_cxx("STD=03 JOB=test/qi Job 7", "clang-10", packages="clang-10 libc++-10-dev libc++abi-10-dev jq", llvm_os="bionic", llvm_ver="10", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '03', 'JOB': 'test/qi', 'TRAVIS_COMPILER': 'clang-10', 'DRONE_JOB_UUID': '902ba3cda1'}, globalenv=globalenv),
|
||||
# Not building #
|
||||
# linux_cxx("STD=03 JOB=test/karma Job 8", "clang-10", packages="clang-10 libc++-10-dev libc++abi-10-dev jq", llvm_os="bionic", llvm_ver="10", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '03', 'JOB': 'test/karma', 'TRAVIS_COMPILER': 'clang-10', 'DRONE_JOB_UUID': 'fe5dbbcea5'}, globalenv=globalenv),
|
||||
linux_cxx("STD=03 JOB=test/lex Job 9", "clang-10", packages="clang-10 libc++-10-dev libc++abi-10-dev jq", llvm_os="bionic", llvm_ver="10", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '03', 'JOB': 'test/lex', 'TRAVIS_COMPILER': 'clang-10', 'DRONE_JOB_UUID': '0ade7c2cf9'}, globalenv=globalenv),
|
||||
linux_cxx("STD=03 JOB=test/support Job 10", "clang-10", packages="clang-10 libc++-10-dev libc++abi-10-dev jq", llvm_os="bionic", llvm_ver="10", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '03', 'JOB': 'test/support', 'TRAVIS_COMPILER': 'clang-10', 'DRONE_JOB_UUID': 'b1d5781111'}, globalenv=globalenv),
|
||||
linux_cxx("STD=03 JOB=repository/test Job 11", "clang-10", packages="clang-10 libc++-10-dev libc++abi-10-dev jq", llvm_os="bionic", llvm_ver="10", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '03', 'JOB': 'repository/test', 'TRAVIS_COMPILER': 'clang-10', 'DRONE_JOB_UUID': '17ba079149'}, globalenv=globalenv),
|
||||
linux_cxx("STD=11 JOB=test/qi Job 12", "gcc-10", packages="g++-10 jq", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '11', 'JOB': 'test/qi', 'TRAVIS_COMPILER': 'gcc-10', 'DRONE_JOB_UUID': '7b52009b64'}, globalenv=globalenv),
|
||||
linux_cxx("STD=11 JOB=test/karma Job 13", "gcc-10", packages="g++-10 jq", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '11', 'JOB': 'test/karma', 'TRAVIS_COMPILER': 'gcc-10', 'DRONE_JOB_UUID': 'bd307a3ec3'}, globalenv=globalenv),
|
||||
linux_cxx("STD=11 JOB=test/lex Job 14", "gcc-10", packages="g++-10 jq", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '11', 'JOB': 'test/lex', 'TRAVIS_COMPILER': 'gcc-10', 'DRONE_JOB_UUID': 'fa35e19212'}, globalenv=globalenv),
|
||||
linux_cxx("STD=11 JOB=test/support Job 15", "gcc-10", packages="g++-10 jq", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '11', 'JOB': 'test/support', 'TRAVIS_COMPILER': 'gcc-10', 'DRONE_JOB_UUID': 'f1abd67035'}, globalenv=globalenv),
|
||||
linux_cxx("STD=11 JOB=repository/test Job 16", "gcc-10", packages="g++-10 jq", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '11', 'JOB': 'repository/test', 'TRAVIS_COMPILER': 'gcc-10', 'DRONE_JOB_UUID': '1574bddb75'}, globalenv=globalenv),
|
||||
# Not building #
|
||||
# linux_cxx("STD=03 JOB=test/qi Job 17", "gcc-10", packages="g++-10 jq", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '03', 'JOB': 'test/qi', 'TRAVIS_COMPILER': 'gcc-10', 'DRONE_JOB_UUID': '0716d9708d'}, globalenv=globalenv),
|
||||
# Not building #
|
||||
# linux_cxx("STD=03 JOB=test/karma Job 18", "gcc-10", packages="g++-10 jq", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '03', 'JOB': 'test/karma', 'TRAVIS_COMPILER': 'gcc-10', 'DRONE_JOB_UUID': '9e6a55b6b4'}, globalenv=globalenv),
|
||||
linux_cxx("STD=03 JOB=test/lex Job 19", "gcc-10", packages="g++-10 jq", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '03', 'JOB': 'test/lex', 'TRAVIS_COMPILER': 'gcc-10', 'DRONE_JOB_UUID': 'b3f0c7f6bb'}, globalenv=globalenv),
|
||||
linux_cxx("STD=03 JOB=test/support Job 20", "gcc-10", packages="g++-10 jq", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '03', 'JOB': 'test/support', 'TRAVIS_COMPILER': 'gcc-10', 'DRONE_JOB_UUID': '91032ad7bb'}, globalenv=globalenv),
|
||||
linux_cxx("STD=03 JOB=repository/test Job 21", "gcc-10", packages="g++-10 jq", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '03', 'JOB': 'repository/test', 'TRAVIS_COMPILER': 'gcc-10', 'DRONE_JOB_UUID': '472b07b9fc'}, globalenv=globalenv),
|
||||
# Not building #
|
||||
# linux_cxx("STD=03 JOB=classic/test Job 22", "clang-10", packages="clang-10 libc++-10-dev libc++abi-10-dev jq", llvm_os="bionic", llvm_ver="10", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '03', 'JOB': 'classic/test', 'TRAVIS_COMPILER': 'clang-10', 'DRONE_JOB_UUID': '12c6fc06c9'}, globalenv=globalenv),
|
||||
# Not building #
|
||||
# linux_cxx("STD=03 JOB=classic/test Job 23", "gcc-10", packages="g++-10 jq", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'STD': '03', 'JOB': 'classic/test', 'TRAVIS_COMPILER': 'gcc-10', 'DRONE_JOB_UUID': 'd435a6cdd7'}, globalenv=globalenv),
|
||||
]
|
||||
|
||||
# from https://github.com/boostorg/boost-ci
|
||||
load("@boost_ci//ci/drone/:functions.star", "linux_cxx","windows_cxx","osx_cxx","freebsd_cxx")
|
||||
88
.drone/drone.sh
Executable file
88
.drone/drone.sh
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2020 Rene Rivera, Sam Darwin
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
set -e
|
||||
export TRAVIS_BUILD_DIR=$(pwd)
|
||||
export DRONE_BUILD_DIR=$(pwd)
|
||||
export TRAVIS_BRANCH=$DRONE_BRANCH
|
||||
export VCS_COMMIT_ID=$DRONE_COMMIT
|
||||
export GIT_COMMIT=$DRONE_COMMIT
|
||||
export REPO_NAME=$DRONE_REPO
|
||||
export USER=$(whoami)
|
||||
export CC=${CC:-gcc}
|
||||
export PATH=~/.local/bin:/usr/local/bin:$PATH
|
||||
export BOOST_ROOT="$HOME/boost"
|
||||
export BOOST_BUILD_PATH="$HOME/build-boost"
|
||||
export TRAVIS_PULL_REQUEST=${DRONE_PULL_REQUEST:-false}
|
||||
export TRAVIS_REPO_SLUG=$REPO_NAME
|
||||
|
||||
if [ "$DRONE_JOB_BUILDTYPE" == "boost" ]; then
|
||||
|
||||
echo '==================================> INSTALL'
|
||||
|
||||
export CACHE_NAME=$TRAVIS_OS_NAME-$TOOLSET-$STD-$JOB
|
||||
export PATH=$BOOST_ROOT:$PATH
|
||||
if [[ "$TRAVIS_COMPILER" =~ ^clang- ]]; then export STDLIB=stdlib=libc++ ; fi
|
||||
# Creating ~/user-config.jam file
|
||||
sed 's/^ //' > ~/user-config.jam << 'EOF'
|
||||
|
||||
import feature ;
|
||||
import os ;
|
||||
import regex ;
|
||||
import toolset ;
|
||||
|
||||
|
||||
local TOOLSET = [ os.environ TRAVIS_COMPILER ] ;
|
||||
local toolset-parts = [ regex.split $(TOOLSET) "-" ] ;
|
||||
local toolset-name = $(toolset-parts[1]) ;
|
||||
local toolset-feature = $(toolset-parts[2-]:J="-") ;
|
||||
|
||||
local cxx ;
|
||||
switch $(toolset-name) {
|
||||
case gcc : cxx ?= [ regex.replace $(TOOLSET) "gcc" "g++" ] ;
|
||||
case clang : cxx ?= [ regex.replace $(TOOLSET) "clang" "clang++" ] ;
|
||||
case * : EXIT "user-config: Unsupported toolset $(toolset-name)" ;
|
||||
}
|
||||
|
||||
using $(toolset-name) : $(toolset-feature) : ccache $(cxx) ;
|
||||
|
||||
# Release variant with enabled asserts
|
||||
variant sanitize : <optimization>speed <debug-symbols>off <inlining>full
|
||||
<runtime-debugging>off ;
|
||||
|
||||
# Determining the root branch
|
||||
if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then
|
||||
export BRANCH=$TRAVIS_BRANCH
|
||||
else
|
||||
# It is a pull request. Retrieve the base branch from GitHub
|
||||
GH_PR_API=https://api.github.com/repos/$TRAVIS_REPO_SLUG/pulls/$TRAVIS_PULL_REQUEST
|
||||
export BRANCH=`curl -s $GH_PR_API | jq -r .head.ref`;
|
||||
fi
|
||||
if [[ ! "$BRANCH" =~ ^(master|develop)$ ]]; then
|
||||
# Travis has been triggered not from our main branches.
|
||||
# Find out the base branch from the git history
|
||||
# TODO: Not implemented yet, but in most cases it will be develop branch
|
||||
export BRANCH=develop
|
||||
fi
|
||||
echo Root branch is $BRANCH
|
||||
|
||||
env
|
||||
sed 's/--depth=1/--depth=9/g' `which git` > ~/git && chmod +x ~/git
|
||||
~/git clone -j10 --branch=$BRANCH --depth=1 --quiet --recurse-submodules=":(exclude)$PROJECT" --shallow-submodules https://github.com/boostorg/boost.git $BOOST_ROOT
|
||||
pushd $BOOST_ROOT
|
||||
rm -rf $PROJECT
|
||||
./bootstrap.sh --with-toolset=clang
|
||||
./b2 headers
|
||||
cp -rp $TRAVIS_BUILD_DIR $PROJECT
|
||||
ln -s $PROJECT $TRAVIS_BUILD_DIR
|
||||
cd $PROJECT
|
||||
cd $JOB
|
||||
|
||||
echo '==================================> SCRIPT'
|
||||
|
||||
b2 link=shared threading=multi variant=release,sanitize toolset=$TRAVIS_COMPILER cxxstd=$STD $STDLIB warnings=extra warnings-as-errors=on
|
||||
|
||||
fi
|
||||
529
.github/workflows/ci.yml
vendored
529
.github/workflows/ci.yml
vendored
@@ -9,295 +9,300 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
BOOST_SPIRIT_BUILD_JOBS: 4
|
||||
BOOST_SPIRIT_CACHED_UPSTREAM_LIBS: --with-regex --with-thread --with-atomic --with-chrono --with-container --with-date_time --with-exception --with-math
|
||||
PROJECT: libs/spirit
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
spirit_component: ${{ steps.filter.outputs.changes }}
|
||||
karma: ${{ steps.filter.outputs.karma }}
|
||||
lex: ${{ steps.filter.outputs.lex }}
|
||||
qi: ${{ steps.filter.outputs.qi }}
|
||||
support: ${{ steps.filter.outputs.support }}
|
||||
repository: ${{ steps.filter.outputs.repository }}
|
||||
x3: ${{ steps.filter.outputs.x3 }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: dorny/paths-filter@v3
|
||||
id: filter
|
||||
with:
|
||||
# Note: references to "support" directory in X3 can be completely
|
||||
# eliminated as soon as those components are moved to X3's
|
||||
# self-contained location
|
||||
filters: |
|
||||
karma:
|
||||
- '.github/workflows/*.yml'
|
||||
- 'include/boost/spirit/home/support/**/*'
|
||||
- 'include/boost/spirit/home/support.hpp'
|
||||
- 'include/boost/spirit/home/karma/**/*'
|
||||
- 'include/boost/spirit/home/karma.hpp'
|
||||
- 'test/karma/**/*'
|
||||
lex:
|
||||
- '.github/workflows/*.yml'
|
||||
- 'include/boost/spirit/home/support/**/*'
|
||||
- 'include/boost/spirit/home/support.hpp'
|
||||
- 'include/boost/spirit/home/lex/**/*'
|
||||
- 'include/boost/spirit/home/lex.hpp'
|
||||
- 'test/lex/**/*'
|
||||
qi:
|
||||
- '.github/workflows/*.yml'
|
||||
- 'include/boost/spirit/home/support/**/*'
|
||||
- 'include/boost/spirit/home/support.hpp'
|
||||
- 'include/boost/spirit/home/qi/**/*'
|
||||
- 'include/boost/spirit/home/qi.hpp'
|
||||
- 'test/qi/**/*'
|
||||
support:
|
||||
- '.github/workflows/*.yml'
|
||||
- 'include/boost/spirit/home/support/**/*'
|
||||
- 'include/boost/spirit/home/support.hpp'
|
||||
- 'test/support/**/*'
|
||||
repository:
|
||||
- '.github/workflows/*.yml'
|
||||
- 'include/boost/spirit/repository/**/*'
|
||||
- 'repository/**/*'
|
||||
x3:
|
||||
- '.github/workflows/*.yml'
|
||||
- 'include/boost/spirit/home/x3/**/*'
|
||||
- 'include/boost/spirit/home/x3.hpp'
|
||||
- 'test/x3/**/*'
|
||||
- 'include/boost/spirit/home/support/char_set/**/*'
|
||||
- 'include/boost/spirit/home/support/char_encoding/**/*'
|
||||
|
||||
build:
|
||||
name: "[${{ matrix.cpp_version.name }}] ${{ matrix.spirit_component }} | ${{ matrix.compiler.toolset }}-${{ matrix.compiler.version }} (${{ matrix.build_type.name }}) @ ${{ matrix.os.name }}-${{ matrix.os.version }}"
|
||||
|
||||
needs: changes
|
||||
if: ${{ needs.changes.outputs.spirit_component != '[]' && needs.changes.outputs.spirit_component != '' }}
|
||||
|
||||
runs-on: ${{ matrix.os.name }}-${{ matrix.os.version }}
|
||||
|
||||
posix:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
matrix:
|
||||
os:
|
||||
- name: ubuntu
|
||||
version: 24.04
|
||||
- name: windows
|
||||
version: 2022
|
||||
build_type:
|
||||
- name: Debug
|
||||
lowercase: debug
|
||||
- name: Release
|
||||
lowercase: release
|
||||
cpp_version:
|
||||
- name: C++11
|
||||
number: 11
|
||||
- name: C++23
|
||||
number: 23
|
||||
msvc_std: /std:c++23preview
|
||||
- name: C++26
|
||||
number: 26
|
||||
msvc_std: /std:c++latest
|
||||
compiler:
|
||||
- name: GCC
|
||||
toolset: gcc
|
||||
version: 14
|
||||
cxxflags: -fdiagnostics-color=always
|
||||
- name: Clang
|
||||
toolset: clang
|
||||
version: 22
|
||||
cxxflags: -fcolor-diagnostics
|
||||
- name: MSVC
|
||||
toolset: msvc
|
||||
version: 2022
|
||||
cxxflags: /EHsc /utf-8
|
||||
include:
|
||||
- name: "C++17 test/x3"
|
||||
buildtype: "boost"
|
||||
packages: "clang-18 libc++-18-dev libc++abi-18-dev libunwind-18-dev jq ccache"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-22.04"
|
||||
cxx: "clang-18"
|
||||
sources: ""
|
||||
llvm_os: "jammy"
|
||||
llvm_ver: "18"
|
||||
std: "17"
|
||||
job: "test/x3"
|
||||
travis_compiler: "clang-18"
|
||||
- name: "C++17 test/x3"
|
||||
buildtype: "boost"
|
||||
packages: "g++-13 jq ccache"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-22.04"
|
||||
cxx: "gcc-13"
|
||||
sources: ""
|
||||
llvm_os: ""
|
||||
llvm_ver: ""
|
||||
std: "17"
|
||||
job: "test/x3"
|
||||
travis_compiler: "gcc-13"
|
||||
- name: "C++11 test/qi"
|
||||
buildtype: "boost"
|
||||
packages: "clang-14 libc++-14-dev libc++abi-14-dev libunwind-14-dev jq ccache"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-22.04"
|
||||
cxx: "clang-14"
|
||||
sources: ""
|
||||
llvm_os: "jammy"
|
||||
llvm_ver: "14"
|
||||
std: "11"
|
||||
job: "test/qi"
|
||||
travis_compiler: "clang-14"
|
||||
- name: "C++11 test/karma"
|
||||
buildtype: "boost"
|
||||
packages: "clang-14 libc++-14-dev libc++abi-14-dev libunwind-14-dev jq ccache"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-22.04"
|
||||
cxx: "clang-14"
|
||||
sources: ""
|
||||
llvm_os: "jammy"
|
||||
llvm_ver: "14"
|
||||
std: "11"
|
||||
job: "test/karma"
|
||||
travis_compiler: "clang-14"
|
||||
- name: "C++11 test/lex"
|
||||
buildtype: "boost"
|
||||
packages: "clang-14 libc++-14-dev libc++abi-14-dev libunwind-14-dev jq ccache"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-22.04"
|
||||
cxx: "clang-14"
|
||||
sources: ""
|
||||
llvm_os: "jammy"
|
||||
llvm_ver: "14"
|
||||
std: "11"
|
||||
job: "test/lex"
|
||||
travis_compiler: "clang-14"
|
||||
- name: "C++11 test/support"
|
||||
buildtype: "boost"
|
||||
packages: "clang-14 libc++-14-dev libc++abi-14-dev libunwind-14-dev jq ccache"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-22.04"
|
||||
cxx: "clang-14"
|
||||
sources: ""
|
||||
llvm_os: "jammy"
|
||||
llvm_ver: "14"
|
||||
std: "11"
|
||||
job: "test/support"
|
||||
travis_compiler: "clang-14"
|
||||
- name: "C++11 repository/test"
|
||||
buildtype: "boost"
|
||||
packages: "clang-14 libc++-14-dev libc++abi-14-dev libunwind-14-dev jq ccache"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-22.04"
|
||||
cxx: "clang-14"
|
||||
sources: ""
|
||||
llvm_os: "jammy"
|
||||
llvm_ver: "14"
|
||||
std: "11"
|
||||
job: "repository/test"
|
||||
travis_compiler: "clang-14"
|
||||
- name: "C++11 test/qi"
|
||||
buildtype: "boost"
|
||||
packages: "g++-11 jq ccache"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-22.04"
|
||||
cxx: "gcc-11"
|
||||
sources: ""
|
||||
llvm_os: ""
|
||||
llvm_ver: ""
|
||||
std: "11"
|
||||
job: "test/qi"
|
||||
travis_compiler: "gcc-11"
|
||||
- name: "C++11 test/karma"
|
||||
buildtype: "boost"
|
||||
packages: "g++-11 jq ccache"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-22.04"
|
||||
cxx: "gcc-11"
|
||||
sources: ""
|
||||
llvm_os: ""
|
||||
llvm_ver: ""
|
||||
std: "11"
|
||||
job: "test/karma"
|
||||
travis_compiler: "gcc-11"
|
||||
- name: "C++11 test/lex"
|
||||
buildtype: "boost"
|
||||
packages: "g++-11 jq ccache"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-22.04"
|
||||
cxx: "gcc-11"
|
||||
sources: ""
|
||||
llvm_os: ""
|
||||
llvm_ver: ""
|
||||
std: "11"
|
||||
job: "test/lex"
|
||||
travis_compiler: "gcc-11"
|
||||
- name: "C++11 test/support"
|
||||
buildtype: "boost"
|
||||
packages: "g++-11 jq ccache"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-22.04"
|
||||
cxx: "gcc-11"
|
||||
sources: ""
|
||||
llvm_os: ""
|
||||
llvm_ver: ""
|
||||
std: "11"
|
||||
job: "test/support"
|
||||
travis_compiler: "gcc-11"
|
||||
- name: "C++11 repository/test"
|
||||
buildtype: "boost"
|
||||
packages: "g++-11 jq ccache"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-22.04"
|
||||
cxx: "gcc-11"
|
||||
sources: ""
|
||||
llvm_os: ""
|
||||
llvm_ver: ""
|
||||
std: "11"
|
||||
job: "repository/test"
|
||||
travis_compiler: "gcc-11"
|
||||
|
||||
spirit_component: ${{ fromJSON(needs.changes.outputs.spirit_component) }}
|
||||
|
||||
exclude:
|
||||
# Blacklist all invalid combinations of environments
|
||||
- os:
|
||||
name: windows
|
||||
cpp_version:
|
||||
number: 11 # /std:c++11 is no longer supported
|
||||
- os:
|
||||
name: windows
|
||||
compiler:
|
||||
name: GCC
|
||||
- os:
|
||||
name: windows
|
||||
compiler:
|
||||
name: Clang
|
||||
- os:
|
||||
name: ubuntu
|
||||
compiler:
|
||||
name: MSVC
|
||||
|
||||
# Blacklist incompatible toolchains
|
||||
- spirit_component: karma
|
||||
cpp_version:
|
||||
number: 23
|
||||
- spirit_component: karma
|
||||
cpp_version:
|
||||
number: 26
|
||||
- spirit_component: lex
|
||||
cpp_version:
|
||||
number: 23
|
||||
- spirit_component: lex
|
||||
cpp_version:
|
||||
number: 26
|
||||
- spirit_component: qi
|
||||
cpp_version:
|
||||
number: 23
|
||||
- spirit_component: qi
|
||||
cpp_version:
|
||||
number: 26
|
||||
- spirit_component: support
|
||||
cpp_version:
|
||||
number: 23
|
||||
- spirit_component: support
|
||||
cpp_version:
|
||||
number: 26
|
||||
- spirit_component: repository
|
||||
cpp_version:
|
||||
number: 23
|
||||
- spirit_component: repository
|
||||
cpp_version:
|
||||
number: 26
|
||||
- spirit_component: x3
|
||||
cpp_version:
|
||||
number: 11
|
||||
runs-on: ${{ matrix.os }}
|
||||
container: ${{ matrix.container }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
# required for upstream Boost version detection
|
||||
# sadly not working due to upstream bug: https://github.com/actions/checkout/issues/1471
|
||||
fetch-tags: true
|
||||
- name: Check if running in container
|
||||
if: matrix.container != ''
|
||||
run: echo "GHA_CONTAINER=${{ matrix.container }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Fetch git tags
|
||||
run: |
|
||||
git fetch --depth=1 origin +refs/tags/*:refs/tags/*
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Initialize Ubuntu
|
||||
if: matrix.os.name == 'ubuntu'
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: |
|
||||
sudo echo "set man-db/auto-update false" | sudo debconf-communicate
|
||||
sudo dpkg-reconfigure man-db
|
||||
sudo apt-get install -y jq
|
||||
|
||||
- name: Setup GCC
|
||||
if: matrix.compiler.toolset == 'gcc'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y g++-${{ matrix.compiler.version }}
|
||||
|
||||
- name: Setup Clang
|
||||
if: matrix.compiler.toolset == 'clang'
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x ./llvm.sh
|
||||
sudo ./llvm.sh ${{ matrix.compiler.version }}
|
||||
sudo apt-get install -y libc++-${{ matrix.compiler.version }}-dev libc++abi-${{ matrix.compiler.version }}-dev
|
||||
echo "BOOST_SPIRIT_STDLIB=stdlib=libc++" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Fetch Environment Info
|
||||
id: env-info
|
||||
- name: Linux
|
||||
shell: bash
|
||||
env:
|
||||
CXX: ${{ matrix.cxx }}
|
||||
SOURCES: ${{ matrix.sources }}
|
||||
LLVM_OS: ${{ matrix.llvm_os }}
|
||||
LLVM_VER: ${{ matrix.llvm_ver }}
|
||||
PACKAGES: ${{ matrix.packages }}
|
||||
PACKAGES_TO_REMOVE: ${{ matrix.packages_to_remove }}
|
||||
JOB_BUILDTYPE: ${{ matrix.buildtype }}
|
||||
STD: ${{ matrix.std }}
|
||||
JOB: ${{ matrix.job }}
|
||||
TRAVIS_COMPILER: ${{ matrix.travis_compiler }}
|
||||
TRAVIS_BRANCH: ${{ github.base_ref }}
|
||||
TRAVIS_OS_NAME: "linux"
|
||||
run: |
|
||||
echo '==================================> SETUP'
|
||||
echo '==================================> PACKAGES'
|
||||
set -e
|
||||
export BOOST_RELEASE_VERSION_NAME=$(git for-each-ref refs/tags --sort=-refname --format='%(refname:lstrip=-1)' --count=1)
|
||||
echo "BOOST_RELEASE_VERSION_NAME: $BOOST_RELEASE_VERSION_NAME"
|
||||
echo "BOOST_RELEASE_VERSION_NAME=$BOOST_RELEASE_VERSION_NAME" >> "$GITHUB_OUTPUT"
|
||||
if [ -n "$PACKAGES_TO_REMOVE" ]; then sudo apt-get purge -y $PACKAGES_TO_REMOVE; fi
|
||||
echo ">>>>> APT: REPO.."
|
||||
for i in {1..3}; do sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test" && break || sleep 2; done
|
||||
|
||||
if [ "${{ matrix.os.name }}" = "windows" ]; then
|
||||
export BOOST_ROOT=$(cygpath -w $HOME/boost)
|
||||
else
|
||||
export BOOST_ROOT=$HOME/boost
|
||||
if test -n "${LLVM_OS}" ; then
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
if test -n "${LLVM_VER}" ; then
|
||||
sudo -E apt-add-repository "deb http://apt.llvm.org/${LLVM_OS}/ llvm-toolchain-${LLVM_OS}-${LLVM_VER} main"
|
||||
else
|
||||
# Snapshot (i.e. trunk) build of clang
|
||||
sudo -E apt-add-repository "deb http://apt.llvm.org/${LLVM_OS}/ llvm-toolchain-${LLVM_OS} main"
|
||||
fi
|
||||
fi
|
||||
echo "BOOST_ROOT: $BOOST_ROOT"
|
||||
echo "BOOST_ROOT=$BOOST_ROOT" >> "$GITHUB_OUTPUT"
|
||||
echo ">>>>> APT: UPDATE.."
|
||||
sudo -E apt-get -o Acquire::Retries=3 update
|
||||
if test -n "${SOURCES}" ; then
|
||||
echo ">>>>> APT: INSTALL SOURCES.."
|
||||
for SOURCE in $SOURCES; do
|
||||
sudo -E apt-add-repository ppa:$SOURCE
|
||||
done
|
||||
fi
|
||||
echo ">>>>> APT: INSTALL ${PACKAGES}.."
|
||||
sudo -E DEBIAN_FRONTEND=noninteractive apt-get -o Acquire::Retries=3 -y --no-install-suggests --no-install-recommends install ${PACKAGES}
|
||||
|
||||
- name: Cache upstream Boost libraries (restore)
|
||||
id: cache-boost
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
key: ${{ steps.env-info.outputs.BOOST_RELEASE_VERSION_NAME }}-${{ matrix.os.name }}-${{ matrix.os.version }}-${{ matrix.compiler.toolset }}-${{ matrix.compiler.version }}-${{ matrix.cpp_version.name }}-${{ matrix.build_type.name }}
|
||||
path: |
|
||||
${{ steps.env-info.outputs.BOOST_ROOT }}
|
||||
!${{ steps.env-info.outputs.BOOST_ROOT }}/.git
|
||||
echo '==================================> INSTALL AND COMPILE'
|
||||
set -e
|
||||
export TRAVIS_BUILD_DIR=$(pwd)
|
||||
export TRAVIS_BRANCH=${TRAVIS_BRANCH:-$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')}
|
||||
export VCS_COMMIT_ID=$GITHUB_SHA
|
||||
export GIT_COMMIT=$GITHUB_SHA
|
||||
export REPO_NAME=$(basename $GITHUB_REPOSITORY)
|
||||
export USER=$(whoami)
|
||||
export CC=${CC:-gcc}
|
||||
export PATH=~/.local/bin:/usr/local/bin:$PATH
|
||||
export BOOST_ROOT="$HOME/boost"
|
||||
export BOOST_BUILD_PATH="$HOME/build-boost"
|
||||
export GITHUB_EVENT_NUMBER=${{ github.event.number }}
|
||||
export TRAVIS_PULL_REQUEST=${GITHUB_EVENT_NUMBER:-false}
|
||||
export TRAVIS_REPO_SLUG=$REPO_NAME
|
||||
|
||||
- name: Clone upstream Boost libraries
|
||||
if: steps.cache-boost.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git -c advice.detachedHead=false clone --no-tags --single-branch --branch=${{ steps.env-info.outputs.BOOST_RELEASE_VERSION_NAME }} --depth=1 --quiet --recurse-submodules=":(exclude)libs/spirit" --shallow-submodules https://github.com/boostorg/boost.git ${{ steps.env-info.outputs.BOOST_ROOT }}
|
||||
|
||||
- name: Build upstream Boost libraries (Ubuntu)
|
||||
if: matrix.os.name == 'ubuntu' && steps.cache-boost.outputs.cache-hit != 'true'
|
||||
env:
|
||||
BOOST_ROOT: ${{ steps.env-info.outputs.BOOST_ROOT }}
|
||||
working-directory: ${{ steps.env-info.outputs.BOOST_ROOT }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -xe
|
||||
rm -rf libs/spirit
|
||||
./bootstrap.sh --with-toolset=${{ matrix.compiler.toolset }}
|
||||
./b2 -d0 headers
|
||||
./b2 -d1 -j$BOOST_SPIRIT_BUILD_JOBS $BOOST_SPIRIT_CACHED_UPSTREAM_LIBS link=shared threading=multi variant=${{ matrix.build_type.lowercase }} toolset=${{ matrix.compiler.toolset }}-${{ matrix.compiler.version }} cxxstd=${{ matrix.cpp_version.number }} cxxflags="${{ matrix.compiler.cxxflags }}" $BOOST_SPIRIT_STDLIB warnings=extra warnings-as-errors=off
|
||||
if [ "$JOB_BUILDTYPE" == "boost" ]; then
|
||||
|
||||
- uses: TheMrMilchmann/setup-msvc-dev@v3
|
||||
if: matrix.os.name == 'windows'
|
||||
with:
|
||||
arch: x64
|
||||
echo '==================================> INSTALL'
|
||||
|
||||
- name: Build upstream Boost libraries (Windows)
|
||||
if: matrix.os.name == 'windows' && steps.cache-boost.outputs.cache-hit != 'true'
|
||||
env:
|
||||
BOOST_ROOT: ${{ steps.env-info.outputs.BOOST_ROOT }}
|
||||
working-directory: ${{ steps.env-info.outputs.BOOST_ROOT }}
|
||||
shell: cmd
|
||||
run: |
|
||||
rd /s /q libs\spirit
|
||||
.\bootstrap.bat --with-toolset=${{ matrix.compiler.toolset }}
|
||||
.\b2 -d0 headers
|
||||
.\b2 -d1 -j%BOOST_SPIRIT_BUILD_JOBS% %BOOST_SPIRIT_CACHED_UPSTREAM_LIBS% link=shared threading=multi variant=${{ matrix.build_type.lowercase }} toolset=${{ matrix.compiler.toolset }} cxxflags="${{ matrix.cpp_version.msvc_std }} ${{matrix.compiler.cxxflags}}" warnings=extra warnings-as-errors=off
|
||||
export CACHE_NAME=$TRAVIS_OS_NAME-$TOOLSET-$STD-$JOB
|
||||
export PATH=$BOOST_ROOT:$PATH
|
||||
if [[ "$TRAVIS_COMPILER" =~ ^clang- ]]; then export STDLIB=stdlib=libc++ ; fi
|
||||
# Creating ~/user-config.jam file
|
||||
sed 's/^ //' > ~/user-config.jam << 'EOF'
|
||||
|
||||
- name: Cache upstream Boost libraries
|
||||
if: steps.cache-boost.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
key: ${{ steps.cache-boost.outputs.cache-primary-key }}
|
||||
path: |
|
||||
${{ steps.env-info.outputs.BOOST_ROOT }}
|
||||
!${{ steps.env-info.outputs.BOOST_ROOT }}/.git
|
||||
import feature ;
|
||||
import os ;
|
||||
import regex ;
|
||||
import toolset ;
|
||||
|
||||
- name: Build and test (Ubuntu)
|
||||
if: matrix.os.name == 'ubuntu'
|
||||
env:
|
||||
BOOST_ROOT: ${{ steps.env-info.outputs.BOOST_ROOT }}
|
||||
working-directory: ${{ steps.env-info.outputs.BOOST_ROOT }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -xe
|
||||
cp -rp $GITHUB_WORKSPACE libs/spirit
|
||||
cd libs/spirit/test
|
||||
ln -s ../repository/test repository # workaround legacy directory structure
|
||||
cd ${{ matrix.spirit_component }}
|
||||
|
||||
$BOOST_ROOT/b2 -d1 -j$BOOST_SPIRIT_BUILD_JOBS link=shared threading=multi variant=${{ matrix.build_type.lowercase }} toolset=${{ matrix.compiler.toolset }}-${{ matrix.compiler.version }} cxxstd=${{ matrix.cpp_version.number }} cxxflags="${{ matrix.compiler.cxxflags }}" $BOOST_SPIRIT_STDLIB warnings=extra warnings-as-errors=off
|
||||
local TOOLSET = [ os.environ TRAVIS_COMPILER ] ;
|
||||
local toolset-parts = [ regex.split $(TOOLSET) "-" ] ;
|
||||
local toolset-name = $(toolset-parts[1]) ;
|
||||
local toolset-feature = $(toolset-parts[2-]:J="-") ;
|
||||
|
||||
- name: Build and test (Windows)
|
||||
if: matrix.os.name == 'windows'
|
||||
env:
|
||||
BOOST_ROOT: ${{ steps.env-info.outputs.BOOST_ROOT }}
|
||||
working-directory: ${{ steps.env-info.outputs.BOOST_ROOT }}
|
||||
shell: cmd
|
||||
run: |
|
||||
xcopy /S /E /Q %GITHUB_WORKSPACE% libs\spirit\
|
||||
cd libs\spirit\test
|
||||
cd ${{ matrix.spirit_component }}
|
||||
local cxx ;
|
||||
switch $(toolset-name) {
|
||||
case gcc : cxx ?= [ regex.replace $(TOOLSET) "gcc" "g++" ] ;
|
||||
case clang : cxx ?= [ regex.replace $(TOOLSET) "clang" "clang++" ] ;
|
||||
case * : EXIT "user-config: Unsupported toolset $(toolset-name)" ;
|
||||
}
|
||||
|
||||
%BOOST_ROOT%\b2 -d1 -j%BOOST_SPIRIT_BUILD_JOBS% link=shared threading=multi variant=${{ matrix.build_type.lowercase }} toolset=${{ matrix.compiler.toolset }} cxxflags="${{ matrix.cpp_version.msvc_std }} ${{matrix.compiler.cxxflags}}" warnings=extra warnings-as-errors=off
|
||||
using $(toolset-name) : $(toolset-feature) : ccache $(cxx) ;
|
||||
|
||||
# Release variant with enabled asserts
|
||||
variant sanitize : <optimization>speed <debug-symbols>off <inlining>full
|
||||
<runtime-debugging>off ;
|
||||
|
||||
EOF
|
||||
# Determining the root branch
|
||||
if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then
|
||||
export BRANCH=$TRAVIS_BRANCH
|
||||
else
|
||||
# It is a pull request. Retrieve the base branch from GitHub
|
||||
GH_PR_API=https://api.github.com/repos/$TRAVIS_REPO_SLUG/pulls/$TRAVIS_PULL_REQUEST
|
||||
export BRANCH=`curl -s $GH_PR_API | jq -r .head.ref`;
|
||||
fi
|
||||
if [[ ! "$BRANCH" =~ ^(master|develop)$ ]]; then
|
||||
# Travis has been triggered not from our main branches.
|
||||
# Find out the base branch from the git history
|
||||
# TODO: Not implemented yet, but in most cases it will be develop branch
|
||||
export BRANCH=develop
|
||||
fi
|
||||
echo Root branch is $BRANCH
|
||||
|
||||
env
|
||||
sed 's/--depth=1/--depth=9/g' `which git` > ~/git && chmod +x ~/git
|
||||
~/git clone -j10 --branch=$BRANCH --depth=1 --quiet --recurse-submodules=":(exclude)$PROJECT" --shallow-submodules https://github.com/boostorg/boost.git $BOOST_ROOT
|
||||
pushd $BOOST_ROOT
|
||||
rm -rf $PROJECT
|
||||
./bootstrap.sh --with-toolset=clang
|
||||
./b2 headers
|
||||
cp -rp $TRAVIS_BUILD_DIR $PROJECT
|
||||
ln -s $PROJECT $TRAVIS_BUILD_DIR
|
||||
cd $PROJECT
|
||||
cd $JOB
|
||||
|
||||
echo '==================================> SCRIPT'
|
||||
|
||||
b2 link=shared threading=multi variant=release,sanitize toolset=$TRAVIS_COMPILER cxxstd=$STD $STDLIB warnings=extra warnings-as-errors=off define=BOOST_SPIRIT_X3_HIDE_CXX17_WARNING
|
||||
|
||||
fi
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,5 @@
|
||||
|
||||
.DS_Store
|
||||
/build*/
|
||||
|
||||
test/lex/matlib_static_switch.h
|
||||
|
||||
|
||||
155
.travis.yml
Normal file
155
.travis.yml
Normal file
@@ -0,0 +1,155 @@
|
||||
#==============================================================================
|
||||
# Copyright (c) 2016-2021 Nikita Kniazev
|
||||
#
|
||||
# Use, modification and distribution is subject to the Boost Software
|
||||
# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#==============================================================================
|
||||
|
||||
language: cpp
|
||||
|
||||
sudo: false
|
||||
|
||||
addon_shortcuts:
|
||||
clang-12: &clang-12
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-12 main'
|
||||
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
|
||||
packages:
|
||||
- clang-12
|
||||
- libc++-12-dev
|
||||
- libc++abi-12-dev
|
||||
|
||||
gcc-11: &gcc-11
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||
packages:
|
||||
- g++-11
|
||||
|
||||
os: linux
|
||||
dist: bionic
|
||||
|
||||
env:
|
||||
global:
|
||||
- PROJECT=libs/spirit
|
||||
- BOOST_ROOT=$HOME/boost
|
||||
- BOOST_BUILD_PATH=$HOME/build-boost
|
||||
|
||||
matrix:
|
||||
include:
|
||||
### Spirit 3
|
||||
- { env: 'STD=14 JOB=test/x3', compiler: clang-12, addons: *clang-12 }
|
||||
- { env: 'STD=14 JOB=test/x3', compiler: gcc-11, addons: *gcc-11 }
|
||||
### Spirit 2
|
||||
## Clang
|
||||
# 11
|
||||
- { env: 'STD=11 JOB=test/qi', compiler: clang-12, addons: *clang-12 }
|
||||
- { env: 'STD=11 JOB=test/karma', compiler: clang-12, addons: *clang-12 }
|
||||
- { env: 'STD=11 JOB=test/lex', compiler: clang-12, addons: *clang-12 }
|
||||
- { env: 'STD=11 JOB=test/support', compiler: clang-12, addons: *clang-12 }
|
||||
- { env: 'STD=11 JOB=repository/test', compiler: clang-12, addons: *clang-12 }
|
||||
# 03
|
||||
- { env: 'STD=03 JOB=test/qi', compiler: clang-12, addons: *clang-12 }
|
||||
- { env: 'STD=03 JOB=test/karma', compiler: clang-12, addons: *clang-12 }
|
||||
- { env: 'STD=03 JOB=test/lex', compiler: clang-12, addons: *clang-12 }
|
||||
- { env: 'STD=03 JOB=test/support', compiler: clang-12, addons: *clang-12 }
|
||||
- { env: 'STD=03 JOB=repository/test', compiler: clang-12, addons: *clang-12 }
|
||||
## GCC
|
||||
# 11
|
||||
- { env: 'STD=11 JOB=test/qi', compiler: gcc-11, addons: *gcc-11 }
|
||||
- { env: 'STD=11 JOB=test/karma', compiler: gcc-11, addons: *gcc-11 }
|
||||
- { env: 'STD=11 JOB=test/lex', compiler: gcc-11, addons: *gcc-11 }
|
||||
- { env: 'STD=11 JOB=test/support', compiler: gcc-11, addons: *gcc-11 }
|
||||
- { env: 'STD=11 JOB=repository/test', compiler: gcc-11, addons: *gcc-11 }
|
||||
# 03
|
||||
- { env: 'STD=03 JOB=test/qi', compiler: gcc-11, addons: *gcc-11 }
|
||||
- { env: 'STD=03 JOB=test/karma', compiler: gcc-11, addons: *gcc-11 }
|
||||
- { env: 'STD=03 JOB=test/lex', compiler: gcc-11, addons: *gcc-11 }
|
||||
- { env: 'STD=03 JOB=test/support', compiler: gcc-11, addons: *gcc-11 }
|
||||
- { env: 'STD=03 JOB=repository/test', compiler: gcc-11, addons: *gcc-11 }
|
||||
### Spirit 1
|
||||
- { env: 'STD=03 JOB=classic/test', compiler: clang-12, addons: *clang-12 }
|
||||
- { env: 'STD=03 JOB=classic/test', compiler: gcc-11, addons: *gcc-11 }
|
||||
|
||||
cache: ccache
|
||||
|
||||
before_install:
|
||||
- export CACHE_NAME=$TRAVIS_OS_NAME-$TOOLSET-$STD-$JOB
|
||||
- export PATH=$BOOST_ROOT:$PATH
|
||||
- if [[ "$TRAVIS_COMPILER" =~ ^clang- ]]; then export STDLIB=stdlib=libc++ ; fi
|
||||
- |
|
||||
# Creating ~/user-config.jam file
|
||||
sed 's/^ //' > ~/user-config.jam << 'EOF'
|
||||
|
||||
import feature ;
|
||||
import os ;
|
||||
import regex ;
|
||||
import toolset ;
|
||||
|
||||
|
||||
local TOOLSET = [ os.environ TRAVIS_COMPILER ] ;
|
||||
local toolset-parts = [ regex.split $(TOOLSET) "-" ] ;
|
||||
local toolset-name = $(toolset-parts[1]) ;
|
||||
local toolset-feature = $(toolset-parts[2-]:J="-") ;
|
||||
|
||||
local cxx ;
|
||||
switch $(toolset-name) {
|
||||
case gcc : cxx ?= [ regex.replace $(TOOLSET) "gcc" "g++" ] ;
|
||||
case clang : cxx ?= [ regex.replace $(TOOLSET) "clang" "clang++" ] ;
|
||||
case * : EXIT "user-config: Unsupported toolset $(toolset-name)" ;
|
||||
}
|
||||
|
||||
using $(toolset-name) : $(toolset-feature) : ccache $(cxx) ;
|
||||
|
||||
# Release variant with enabled asserts
|
||||
variant sanitize : <optimization>speed <debug-symbols>off <inlining>full
|
||||
<runtime-debugging>off ;
|
||||
|
||||
- |
|
||||
# Determining the root branch
|
||||
if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then
|
||||
export BRANCH=$TRAVIS_BRANCH
|
||||
else
|
||||
# It is a pull request. Retrieve the base branch from GitHub
|
||||
GH_PR_API=https://api.github.com/repos/$TRAVIS_REPO_SLUG/pulls/$TRAVIS_PULL_REQUEST
|
||||
export BRANCH=`curl -s $GH_PR_API | jq -r .head.ref`;
|
||||
fi
|
||||
if [[ ! "$BRANCH" =~ ^(master|develop)$ ]]; then
|
||||
# Travis has been triggered not from our main branches.
|
||||
# Find out the base branch from the git history
|
||||
# TODO: Not implemented yet, but in most cases it will be develop branch
|
||||
export BRANCH=develop
|
||||
fi
|
||||
echo Root branch is $BRANCH
|
||||
|
||||
# Dump environment variables
|
||||
- env
|
||||
|
||||
# Sadly git's --shallow-submodules has hardcoded depth of 1 commit
|
||||
# Patch the git binary with a little more depth to deal with boost-commitbot's lag
|
||||
- sed 's/--depth=1/--depth=9/g' `which git` > ~/git && chmod +x ~/git
|
||||
|
||||
# Checkout Boost
|
||||
- ~/git clone -j10 --branch=$BRANCH --depth=1 --quiet
|
||||
--recurse-submodules=":(exclude)$PROJECT" --shallow-submodules
|
||||
https://github.com/boostorg/boost.git $BOOST_ROOT
|
||||
- pushd $BOOST_ROOT
|
||||
# Remove the empty folder
|
||||
- rm -rf $PROJECT
|
||||
- ./bootstrap.sh --with-toolset=clang
|
||||
- ./b2 headers
|
||||
|
||||
# Move the repository to boost/libs and make a link to previous place
|
||||
- mv $TRAVIS_BUILD_DIR $PROJECT
|
||||
- ln -s $PROJECT $TRAVIS_BUILD_DIR
|
||||
|
||||
- cd $PROJECT
|
||||
- cd $JOB
|
||||
|
||||
script:
|
||||
- b2 link=shared threading=multi variant=release,sanitize
|
||||
toolset=$TRAVIS_COMPILER cxxstd=$STD $STDLIB
|
||||
warnings=extra warnings-as-errors=on
|
||||
define=BOOST_SPIRIT_X3_HIDE_CXX17_WARNING
|
||||
72
README.md
72
README.md
@@ -1,63 +1,73 @@
|
||||
# Spirit [](https://github.com/boostorg/spirit/actions/workflows/ci.yml)
|
||||
# This repository is no longer actively maintained. [Spirit.X4](https://github.com/boostorg/spirit_x4) is the successor and is currently under development.
|
||||
|
||||
Spirit is a set of C++ libraries for parsing and output generation implemented as
|
||||
Domain Specific Embedded Languages (DSEL) using Expression templates and Template
|
||||
Meta-Programming. The Spirit libraries enable a target grammar to be written
|
||||
exclusively in C++. Inline grammar specifications can mix freely with other
|
||||
C++ code and, thanks to the generative power of C++ templates, are immediately
|
||||
All components predating X4 currently lack an active maintainer. They are feature-frozen and will accept security patches only.
|
||||
|
||||
If you wish to maintain a legacy version, please contact the [Boost developers' mailing list](https://lists.boost.org/).
|
||||
|
||||
For background information, see:
|
||||
|
||||
- <https://lists.boost.org/archives/list/boost@lists.boost.org/thread/K3EQLEQJHEUBROB6ODUKTZHFP2FDUS2E/?sort=date>
|
||||
- <https://github.com/boostorg/spirit/issues/795>
|
||||
- <https://github.com/boostorg/spirit/pull/807>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Spirit
|
||||
======
|
||||
|
||||
Spirit is a set of C++ libraries for parsing and output generation implemented as
|
||||
Domain Specific Embedded Languages (DSEL) using Expression templates and Template
|
||||
Meta-Programming. The Spirit libraries enable a target grammar to be written
|
||||
exclusively in C++. Inline grammar specifications can mix freely with other
|
||||
C++ code and, thanks to the generative power of C++ templates, are immediately
|
||||
executable.
|
||||
|
||||
## Spirit.X3 (3rd generation)
|
||||
### Spirit.X3 (3rd generation)
|
||||
|
||||
[Documentation](http://www.boost.org/doc/libs/develop/libs/spirit/doc/x3/html/index.html)
|
||||
|
||||
The newest Spirit shines faster compile times. Currently only a parser framework (no serialization support).
|
||||
The newest Spirit shines faster compile times. Currently only a parser framework.
|
||||
|
||||
### Supported environments
|
||||
*WARNING*: C++14 compilers support will be dropped soon.
|
||||
|
||||
- C++23 and C++26
|
||||
- GCC 14
|
||||
- Clang 22
|
||||
- MSVC (2022)
|
||||
Spirit X3 in Boost 1.81 (scheduled to November 2022) will use C++17 features.
|
||||
|
||||
Supported compilers will be:
|
||||
* Clang 4 (currently 3.6)
|
||||
* GCC 7 (currently 5)
|
||||
* VS 2017 v15.8 (currently 2015 U3)
|
||||
|
||||
## Spirit V2 (2nd generation)
|
||||
### Spirit V2 (2nd generation)
|
||||
|
||||
[Documentation](http://www.boost.org/doc/libs/develop/libs/spirit/doc/html/index.html)
|
||||
|
||||
The latest Long Term Support version of Spirit. A Swiss Army knife for data
|
||||
manipulation on any kind of input.
|
||||
|
||||
Note: Spirit V2 is no longer actively maintained. For new projects, use X3.
|
||||
|
||||
Consists of:
|
||||
|
||||
- [Qi]: Parser framework.
|
||||
- [Karma]: Generator framework.
|
||||
- [Lex]: Lexical analyzer framework.
|
||||
- [Qi]: Parser framework.
|
||||
- [Karma]: Generator framework.
|
||||
- [Lex]: Lexical analyzer framework.
|
||||
|
||||
Runs on most C++03 compilers (GCC 4.1, Clang 3.0, VS 2005).
|
||||
|
||||
[Spirit V2]: http://www.boost.org/doc/libs/develop/libs/spirit/doc/html/index.html
|
||||
[Qi]: http://www.boost.org/doc/libs/develop/libs/spirit/doc/html/spirit/qi.html
|
||||
[Karma]: http://www.boost.org/doc/libs/develop/libs/spirit/doc/html/spirit/karma.html
|
||||
[Lex]: http://www.boost.org/doc/libs/develop/libs/spirit/doc/html/spirit/lex.html
|
||||
|
||||
### Supported environments
|
||||
|
||||
- C++11 only
|
||||
- GCC 14
|
||||
- Clang 22
|
||||
- **Windows is no longer supported** because [C++11 support was removed in Visual Studio 2017 and later](https://learn.microsoft.com/en-us/cpp/build/reference/std-specify-language-standard-version?view=msvc-170#remarks).
|
||||
|
||||
|
||||
## Spirit.Classic (1st generation)
|
||||
### Spirit.Classic (1st generation)
|
||||
|
||||
[Documentation](http://www.boost.org/doc/libs/develop/libs/spirit/classic/index.html)
|
||||
|
||||
An elderling member of Spirit. It receives only limited maintenance, but
|
||||
An elderling member of Spirit. It receives only limited maintanance, but
|
||||
it is still used even inside Boost by [Boost.Serialization] and [Boost.Wave]
|
||||
libraries. It also contains Phoenix V1.
|
||||
|
||||
Spirit.Classic should support even ancient compilers.
|
||||
Spririt.Classic should support even ancient compilers.
|
||||
|
||||
[Boost.Serialization]: http://boost.org/libs/serialization
|
||||
[Boost.Wave]: http://boost.org/libs/wave
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
[/==============================================================================
|
||||
Copyright (C) 2001-2018 Joel de Guzman
|
||||
Copyright (C) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -129,10 +128,9 @@ our `on_success` handler:
|
||||
|
||||
struct annotate_position
|
||||
{
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename T, typename Context>
|
||||
void on_success(
|
||||
It const& first, Se const& last, T& ast, Context const& context
|
||||
) const
|
||||
template <typename T, typename Iterator, typename Context>
|
||||
inline void on_success(Iterator const& first, Iterator const& last
|
||||
, T& ast, Context const& context)
|
||||
{
|
||||
auto& position_cache = x3::get<position_cache_tag>(context).get();
|
||||
position_cache.annotate(ast, first, last);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[/==============================================================================
|
||||
Copyright (C) 2001-2018 Joel de Guzman
|
||||
Copyright (C) 2024-2025 Nana Sakisaka
|
||||
Copyright (C) 2024 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -129,12 +129,10 @@ Here's our `on_error` handler:
|
||||
|
||||
struct error_handler
|
||||
{
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Exception, typename Context>
|
||||
[[nodiscard]] x3::error_handler_result
|
||||
on_error(
|
||||
It const& first, Se const& last,
|
||||
Exception const& x, Context const& context
|
||||
)
|
||||
template <typename Iterator, typename Exception, typename Context>
|
||||
x3::error_handler_result on_error(
|
||||
Iterator& first, Iterator const& last
|
||||
, Exception const& x, Context const& context)
|
||||
{
|
||||
auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
|
||||
std::string message = "Error! Expecting: " + x3::which(x) + " here:";
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
// Copyright (c) 2025 Nana Sakisaka
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
//
|
||||
// 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)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_LEX_TOKEN_FEB_10_2008_0751PM)
|
||||
@@ -38,33 +37,31 @@
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#if defined(BOOST_SPIRIT_DEBUG)
|
||||
#include <iosfwd>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace lex { namespace lexertl
|
||||
{
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The token is the type of the objects returned by default by the
|
||||
// The token is the type of the objects returned by default by the
|
||||
// iterator.
|
||||
//
|
||||
// template parameters:
|
||||
// Iterator The type of the iterator used to access the
|
||||
// underlying character stream.
|
||||
// AttributeTypes A mpl sequence containing the types of all
|
||||
// required different token values to be supported
|
||||
// AttributeTypes A mpl sequence containing the types of all
|
||||
// required different token values to be supported
|
||||
// by this token type.
|
||||
// HasState A mpl::bool_ indicating, whether this token type
|
||||
// should support lexer states.
|
||||
// Idtype The type to use for the token id (defaults to
|
||||
// Idtype The type to use for the token id (defaults to
|
||||
// std::size_t).
|
||||
//
|
||||
// It is possible to use other token types with the spirit::lex
|
||||
// framework as well. If you plan to use a different type as your token
|
||||
// type, you'll need to expose the following things from your token type
|
||||
// It is possible to use other token types with the spirit::lex
|
||||
// framework as well. If you plan to use a different type as your token
|
||||
// type, you'll need to expose the following things from your token type
|
||||
// to make it compatible with spirit::lex:
|
||||
//
|
||||
// typedefs
|
||||
@@ -75,28 +72,28 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
|
||||
//
|
||||
// methods
|
||||
// default constructor
|
||||
// This should initialize the token as an end of
|
||||
// This should initialize the token as an end of
|
||||
// input token.
|
||||
// constructors The prototype of the other required
|
||||
// constructors The prototype of the other required
|
||||
// constructors should be:
|
||||
//
|
||||
// token(int)
|
||||
// This constructor should initialize the token as
|
||||
// an invalid token (not carrying any specific
|
||||
// This constructor should initialize the token as
|
||||
// an invalid token (not carrying any specific
|
||||
// values)
|
||||
//
|
||||
// where: the int is used as a tag only and its value is
|
||||
// where: the int is used as a tag only and its value is
|
||||
// ignored
|
||||
//
|
||||
// and:
|
||||
//
|
||||
// token(Idtype id, std::size_t state,
|
||||
// token(Idtype id, std::size_t state,
|
||||
// iterator_type first, iterator_type last);
|
||||
//
|
||||
// where: id: token id
|
||||
// state: lexer state this token was matched in
|
||||
// first, last: pair of iterators marking the matched
|
||||
// range in the underlying input stream
|
||||
// first, last: pair of iterators marking the matched
|
||||
// range in the underlying input stream
|
||||
//
|
||||
// accessors
|
||||
// id() return the token id of the matched input sequence
|
||||
@@ -107,16 +104,16 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
|
||||
// value() return the token value
|
||||
//
|
||||
// Additionally, you will have to implement a couple of helper functions
|
||||
// in the same namespace as the token type: a comparison operator==() to
|
||||
// compare your token instances, a token_is_valid() function and different
|
||||
// specializations of the Spirit customization point
|
||||
// in the same namespace as the token type: a comparison operator==() to
|
||||
// compare your token instances, a token_is_valid() function and different
|
||||
// specializations of the Spirit customization point
|
||||
// assign_to_attribute_from_value as shown below.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator = char const*
|
||||
, typename AttributeTypes = mpl::vector0<>
|
||||
, typename HasState = mpl::true_
|
||||
, typename Idtype = std::size_t>
|
||||
, typename Idtype = std::size_t>
|
||||
struct token;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -130,7 +127,7 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
|
||||
typedef mpl::false_ has_state;
|
||||
typedef Idtype id_type;
|
||||
typedef unused_type token_value_type;
|
||||
typedef typename std::make_unsigned<id_type>::type uid_type;
|
||||
typedef typename make_unsigned<id_type>::type uid_type;
|
||||
|
||||
// default constructed tokens correspond to EOI tokens
|
||||
token() : id_(boost::lexer::npos) {}
|
||||
@@ -156,32 +153,32 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
|
||||
: id_(id) {}
|
||||
#endif
|
||||
|
||||
// this default conversion operator is needed to allow the direct
|
||||
// usage of tokens in conjunction with the primitive parsers defined
|
||||
// this default conversion operator is needed to allow the direct
|
||||
// usage of tokens in conjunction with the primitive parsers defined
|
||||
// in Qi
|
||||
operator id_type() const { return id_type(uid_type(id_)); }
|
||||
|
||||
// Retrieve or set the token id of this token instance.
|
||||
// Retrieve or set the token id of this token instance.
|
||||
id_type id() const { return id_type(uid_type(id_)); }
|
||||
void id(id_type newid) { id_ = uid_type(newid); }
|
||||
|
||||
std::size_t state() const { return 0; } // always '0' (INITIAL state)
|
||||
|
||||
bool is_valid() const
|
||||
{
|
||||
return 0 != id_ && boost::lexer::npos != id_;
|
||||
bool is_valid() const
|
||||
{
|
||||
return 0 != id_ && boost::lexer::npos != id_;
|
||||
}
|
||||
|
||||
#if defined(BOOST_SPIRIT_DEBUG)
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1600)
|
||||
// workaround for MSVC10 which has problems copying a default
|
||||
// workaround for MSVC10 which has problems copying a default
|
||||
// constructed iterator_range
|
||||
token& operator= (token const& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
if (this != &rhs)
|
||||
{
|
||||
id_ = rhs.id_;
|
||||
if (is_valid())
|
||||
if (is_valid())
|
||||
matched_ = rhs.matched_;
|
||||
}
|
||||
return *this;
|
||||
@@ -196,8 +193,8 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
|
||||
|
||||
#if defined(BOOST_SPIRIT_DEBUG)
|
||||
template <typename Char, typename Traits, typename Iterator
|
||||
, typename AttributeTypes, typename HasState, typename Idtype>
|
||||
inline std::basic_ostream<Char, Traits>&
|
||||
, typename AttributeTypes, typename HasState, typename Idtype>
|
||||
inline std::basic_ostream<Char, Traits>&
|
||||
operator<< (std::basic_ostream<Char, Traits>& os
|
||||
, token<Iterator, AttributeTypes, HasState, Idtype> const& t)
|
||||
{
|
||||
@@ -251,11 +248,11 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
|
||||
std::size_t state() const { return state_; }
|
||||
|
||||
#if defined(BOOST_SPIRIT_DEBUG) && BOOST_WORKAROUND(BOOST_MSVC, == 1600)
|
||||
// workaround for MSVC10 which has problems copying a default
|
||||
// workaround for MSVC10 which has problems copying a default
|
||||
// constructed iterator_range
|
||||
token& operator= (token const& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
if (this != &rhs)
|
||||
{
|
||||
this->base_type::operator=(static_cast<base_type const&>(rhs));
|
||||
state_ = rhs.state_;
|
||||
@@ -269,21 +266,21 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The generic version of the token type derives from the
|
||||
// specialization above and adds a single data member holding the item
|
||||
// The generic version of the token type derives from the
|
||||
// specialization above and adds a single data member holding the item
|
||||
// data carried by the token instance.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Meta-function to calculate the type of the variant data item to be
|
||||
// Meta-function to calculate the type of the variant data item to be
|
||||
// stored with each token instance.
|
||||
//
|
||||
// Note: The iterator pair needs to be the first type in the list of
|
||||
// types supported by the generated variant type (this is being
|
||||
// used to identify whether the stored data item in a particular
|
||||
// token instance needs to be converted from the pair of
|
||||
// iterators (see the first of the assign_to_attribute_from_value
|
||||
// Note: The iterator pair needs to be the first type in the list of
|
||||
// types supported by the generated variant type (this is being
|
||||
// used to identify whether the stored data item in a particular
|
||||
// token instance needs to be converted from the pair of
|
||||
// iterators (see the first of the assign_to_attribute_from_value
|
||||
// specializations below).
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename IteratorPair, typename AttributeTypes>
|
||||
@@ -298,22 +295,22 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The type of the data item stored with a token instance is defined
|
||||
// The type of the data item stored with a token instance is defined
|
||||
// by the template parameter 'AttributeTypes' and may be:
|
||||
//
|
||||
// lex::omit: no data item is stored with the token
|
||||
// instance (this is handled by the
|
||||
//
|
||||
// lex::omit: no data item is stored with the token
|
||||
// instance (this is handled by the
|
||||
// specializations of the token class
|
||||
// below)
|
||||
// mpl::vector0<>: each token instance stores a pair of
|
||||
// iterators pointing to the matched input
|
||||
// mpl::vector0<>: each token instance stores a pair of
|
||||
// iterators pointing to the matched input
|
||||
// sequence
|
||||
// mpl::vector<...>: each token instance stores a variant being
|
||||
// able to store the pair of iterators pointing
|
||||
// to the matched input sequence, or any of the
|
||||
// mpl::vector<...>: each token instance stores a variant being
|
||||
// able to store the pair of iterators pointing
|
||||
// to the matched input sequence, or any of the
|
||||
// types a specified in the mpl::vector<>
|
||||
//
|
||||
// All this is done to ensure the token type is as small (in terms
|
||||
// All this is done to ensure the token type is as small (in terms
|
||||
// of its byte-size) as possible.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename IteratorPair, typename AttributeTypes>
|
||||
@@ -332,16 +329,16 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
|
||||
struct token : token<Iterator, lex::omit, HasState, Idtype>
|
||||
{
|
||||
private: // precondition assertions
|
||||
BOOST_STATIC_ASSERT((mpl::is_sequence<AttributeTypes>::value ||
|
||||
BOOST_STATIC_ASSERT((mpl::is_sequence<AttributeTypes>::value ||
|
||||
is_same<AttributeTypes, lex::omit>::value));
|
||||
typedef token<Iterator, lex::omit, HasState, Idtype> base_type;
|
||||
|
||||
protected:
|
||||
// If no additional token value types are given, the token will
|
||||
protected:
|
||||
// If no additional token value types are given, the token will
|
||||
// hold the plain pair of iterators pointing to the matched range
|
||||
// in the underlying input sequence. Otherwise the token value is
|
||||
// in the underlying input sequence. Otherwise the token value is
|
||||
// stored as a variant and will again hold the pair of iterators but
|
||||
// is able to hold any of the given data types as well. The conversion
|
||||
// is able to hold any of the given data types as well. The conversion
|
||||
// from the iterator pair to the required data type is done when it is
|
||||
// accessed for the first time.
|
||||
typedef iterator_range<Iterator> iterpair_type;
|
||||
@@ -375,14 +372,14 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
|
||||
token_value_type const& value() const { return value_; }
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1600)
|
||||
// workaround for MSVC10 which has problems copying a default
|
||||
// workaround for MSVC10 which has problems copying a default
|
||||
// constructed iterator_range
|
||||
token& operator= (token const& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
if (this != &rhs)
|
||||
{
|
||||
this->base_type::operator=(static_cast<base_type const&>(rhs));
|
||||
if (this->is_valid())
|
||||
if (this->is_valid())
|
||||
value_ = rhs.value_;
|
||||
}
|
||||
return *this;
|
||||
@@ -397,21 +394,21 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
|
||||
// tokens are considered equal, if their id's match (these are unique)
|
||||
template <typename Iterator, typename AttributeTypes, typename HasState
|
||||
, typename Idtype>
|
||||
inline bool
|
||||
operator== (token<Iterator, AttributeTypes, HasState, Idtype> const& lhs,
|
||||
inline bool
|
||||
operator== (token<Iterator, AttributeTypes, HasState, Idtype> const& lhs,
|
||||
token<Iterator, AttributeTypes, HasState, Idtype> const& rhs)
|
||||
{
|
||||
return lhs.id() == rhs.id();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This overload is needed by the multi_pass/functor_input_policy to
|
||||
// validate a token instance. It has to be defined in the same namespace
|
||||
// This overload is needed by the multi_pass/functor_input_policy to
|
||||
// validate a token instance. It has to be defined in the same namespace
|
||||
// as the token class itself to allow ADL to find it.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename AttributeTypes, typename HasState
|
||||
, typename Idtype>
|
||||
inline bool
|
||||
inline bool
|
||||
token_is_valid(token<Iterator, AttributeTypes, HasState, Idtype> const& t)
|
||||
{
|
||||
return t.is_valid();
|
||||
@@ -422,8 +419,8 @@ namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// We have to provide specializations for the customization point
|
||||
// assign_to_attribute_from_value allowing to extract the needed value
|
||||
// from the token.
|
||||
// assign_to_attribute_from_value allowing to extract the needed value
|
||||
// from the token.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is called from the parse function of token_def if the token_def
|
||||
@@ -433,15 +430,15 @@ namespace boost { namespace spirit { namespace traits
|
||||
struct assign_to_attribute_from_value<Attribute
|
||||
, lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
|
||||
{
|
||||
static void
|
||||
static void
|
||||
call(lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> const& t
|
||||
, Attribute& attr)
|
||||
{
|
||||
// The goal of this function is to avoid the conversion of the pair of
|
||||
// iterators (to the matched character sequence) into the token value
|
||||
// of the required type being done more than once. For this purpose it
|
||||
// checks whether the stored value type is still the default one (pair
|
||||
// of iterators) and if yes, replaces the pair of iterators with the
|
||||
// iterators (to the matched character sequence) into the token value
|
||||
// of the required type being done more than once. For this purpose it
|
||||
// checks whether the stored value type is still the default one (pair
|
||||
// of iterators) and if yes, replaces the pair of iterators with the
|
||||
// converted value to be returned from subsequent calls.
|
||||
|
||||
if (0 == t.value().which()) {
|
||||
@@ -449,38 +446,38 @@ namespace boost { namespace spirit { namespace traits
|
||||
typedef iterator_range<Iterator> iterpair_type;
|
||||
iterpair_type const& ip = boost::get<iterpair_type>(t.value());
|
||||
|
||||
// Interestingly enough we use the assign_to() framework defined in
|
||||
// Spirit.Qi allowing to convert the pair of iterators to almost any
|
||||
// required type (assign_to(), if available, uses the standard Spirit
|
||||
// Interestingly enough we use the assign_to() framework defined in
|
||||
// Spirit.Qi allowing to convert the pair of iterators to almost any
|
||||
// required type (assign_to(), if available, uses the standard Spirit
|
||||
// parsers to do the conversion).
|
||||
spirit::traits::assign_to(ip.begin(), ip.end(), attr);
|
||||
|
||||
// If you get an error during the compilation of the following
|
||||
// assignment expression, you probably forgot to list one or more
|
||||
// types used as token value types (in your token_def<...>
|
||||
// definitions) in your definition of the token class. I.e. any token
|
||||
// value type used for a token_def<...> definition has to be listed
|
||||
// during the declaration of the token type to use. For instance let's
|
||||
// If you get an error during the compilation of the following
|
||||
// assignment expression, you probably forgot to list one or more
|
||||
// types used as token value types (in your token_def<...>
|
||||
// definitions) in your definition of the token class. I.e. any token
|
||||
// value type used for a token_def<...> definition has to be listed
|
||||
// during the declaration of the token type to use. For instance let's
|
||||
// assume we have two token_def's:
|
||||
//
|
||||
// token_def<int> number; number = "...";
|
||||
// token_def<std::string> identifier; identifier = "...";
|
||||
//
|
||||
// Then you'll have to use the following token type definition
|
||||
// Then you'll have to use the following token type definition
|
||||
// (assuming you are using the token class):
|
||||
//
|
||||
// typedef mpl::vector<int, std::string> token_values;
|
||||
// typedef token<base_iter_type, token_values> token_type;
|
||||
//
|
||||
// where: base_iter_type is the iterator type used to expose the
|
||||
// where: base_iter_type is the iterator type used to expose the
|
||||
// underlying input stream.
|
||||
//
|
||||
// This token_type has to be used as the second template parameter
|
||||
// This token_type has to be used as the second template parameter
|
||||
// to the lexer class:
|
||||
//
|
||||
// typedef lexer<base_iter_type, token_type> lexer_type;
|
||||
//
|
||||
// again, assuming you're using the lexer<> template for your
|
||||
// again, assuming you're using the lexer<> template for your
|
||||
// tokenization.
|
||||
|
||||
typedef lex::lexertl::token<
|
||||
@@ -515,7 +512,7 @@ namespace boost { namespace spirit { namespace traits
|
||||
struct assign_to_container_from_value<
|
||||
iterator_range<Iterator>, iterator_range<Iterator> >
|
||||
{
|
||||
static void
|
||||
static void
|
||||
call(iterator_range<Iterator> const& val, iterator_range<Iterator>& attr)
|
||||
{
|
||||
attr = val;
|
||||
@@ -523,18 +520,18 @@ namespace boost { namespace spirit { namespace traits
|
||||
};
|
||||
|
||||
// These are called from the parse function of token_def if the token type
|
||||
// has no special attribute type assigned
|
||||
// has no special attribute type assigned
|
||||
template <typename Attribute, typename Iterator, typename HasState
|
||||
, typename Idtype>
|
||||
struct assign_to_attribute_from_value<Attribute
|
||||
, lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> >
|
||||
{
|
||||
static void
|
||||
static void
|
||||
call(lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> const& t
|
||||
, Attribute& attr)
|
||||
{
|
||||
// The default type returned by the token_def parser component (if
|
||||
// it has no token value type assigned) is the pair of iterators
|
||||
// The default type returned by the token_def parser component (if
|
||||
// it has no token value type assigned) is the pair of iterators
|
||||
// to the matched character sequence.
|
||||
spirit::traits::assign_to(t.value().begin(), t.value().end(), attr);
|
||||
}
|
||||
@@ -554,12 +551,12 @@ namespace boost { namespace spirit { namespace traits
|
||||
struct assign_to_attribute_from_value<Attribute
|
||||
, lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> >
|
||||
{
|
||||
static void
|
||||
static void
|
||||
call(lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> const& t
|
||||
, Attribute& attr)
|
||||
{
|
||||
// The default type returned by the token_def parser component (if
|
||||
// it has no token value type assigned) is the pair of iterators
|
||||
// The default type returned by the token_def parser component (if
|
||||
// it has no token value type assigned) is the pair of iterators
|
||||
// to the matched character sequence.
|
||||
spirit::traits::assign_to(t.value().begin(), t.value().end(), attr);
|
||||
}
|
||||
@@ -575,14 +572,14 @@ namespace boost { namespace spirit { namespace traits
|
||||
|
||||
// This is called from the parse function of token_def if the token type
|
||||
// has been explicitly omitted (i.e. no attribute value is used), which
|
||||
// essentially means that every attribute gets initialized using default
|
||||
// essentially means that every attribute gets initialized using default
|
||||
// constructed values.
|
||||
template <typename Attribute, typename Iterator, typename HasState
|
||||
, typename Idtype>
|
||||
struct assign_to_attribute_from_value<Attribute
|
||||
, lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> >
|
||||
{
|
||||
static void
|
||||
static void
|
||||
call(lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> const&
|
||||
, Attribute&)
|
||||
{
|
||||
@@ -605,15 +602,15 @@ namespace boost { namespace spirit { namespace traits
|
||||
fusion::vector2<Idtype_, iterator_range<Iterator> >
|
||||
, lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
|
||||
{
|
||||
static void
|
||||
static void
|
||||
call(lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> const& t
|
||||
, fusion::vector2<Idtype_, iterator_range<Iterator> >& attr)
|
||||
{
|
||||
// The type returned by the lexer_def_ parser components is a
|
||||
// fusion::vector containing the token id of the matched token
|
||||
// The type returned by the lexer_def_ parser components is a
|
||||
// fusion::vector containing the token id of the matched token
|
||||
// and the pair of iterators to the matched character sequence.
|
||||
typedef iterator_range<Iterator> iterpair_type;
|
||||
typedef fusion::vector2<Idtype_, iterator_range<Iterator> >
|
||||
typedef fusion::vector2<Idtype_, iterator_range<Iterator> >
|
||||
attribute_type;
|
||||
|
||||
iterpair_type const& ip = boost::get<iterpair_type>(t.value());
|
||||
@@ -632,7 +629,7 @@ namespace boost { namespace spirit { namespace traits
|
||||
{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Overload debug output for a single token, this integrates lexer tokens
|
||||
// Overload debug output for a single token, this integrates lexer tokens
|
||||
// with Qi's simple_trace debug facilities
|
||||
template <typename Iterator, typename Attribute, typename HasState
|
||||
, typename Idtype>
|
||||
@@ -642,7 +639,7 @@ namespace boost { namespace spirit { namespace traits
|
||||
typedef lex::lexertl::token<Iterator, Attribute, HasState, Idtype> token_type;
|
||||
|
||||
template <typename Out>
|
||||
static void print(Out& out, token_type const& val)
|
||||
static void print(Out& out, token_type const& val)
|
||||
{
|
||||
out << '[';
|
||||
spirit::traits::print_token(out, val.value());
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013-2014 Agustin Berge
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -10,184 +9,142 @@
|
||||
#define BOOST_SPIRIT_X3_AUXILIARY_ANY_PARSER_APR_09_2014_1145PM
|
||||
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/support/subcontext.hpp>
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/container_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/spirit/home/x3/support/traits/is_parser.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
// Type-erased parser that holds any underlying parser which models `X3Parser<It, It>`.
|
||||
template <
|
||||
std::forward_iterator It, // used only for polymorphism
|
||||
typename Attribute = unused_type,
|
||||
typename Context = unused_type // used only for polymorphism
|
||||
>
|
||||
struct any_parser : parser<any_parser<It, Attribute, Context>>
|
||||
typename Iterator
|
||||
, typename Attribute = unused_type
|
||||
, typename Context = subcontext<>>
|
||||
struct any_parser : parser<any_parser<Iterator, Attribute, Context>>
|
||||
{
|
||||
// `any_parser` existed historically because writing a type-erased parser in C++
|
||||
// was cumbersome before modern language features. Its use is now discouraged for
|
||||
// technical reasons:
|
||||
//
|
||||
// 1) Performance: type erasure places dynamic indirection on the parsing hot path.
|
||||
// Every token step must operate through type-erased iterators/contexts,
|
||||
// inhibiting inlining and adding dispatch overhead.
|
||||
//
|
||||
// 2) Formal grounds: PEGs are deterministic (ordered choice) and do not require
|
||||
// runtime reification of the grammar. The same behaviors can be expressed as
|
||||
// a static composition of parsers with semantic predicates.
|
||||
//
|
||||
// 3) Empirical evidence: a GitHub full-text search indicates that `any_parser`
|
||||
// is rarely used in practice.
|
||||
//
|
||||
// Reaching for `any_parser` means attempting to *define* the right-hand side of the
|
||||
// grammar dynamically from the left-hand side of the input. That indirection is
|
||||
// unnecessary in PEG; you can always structure the grammar statically. If more
|
||||
// complex branching is required, use the symbols parser or design a fully featured
|
||||
// parser class for your specific grammar.
|
||||
//
|
||||
// Note for X3 developers: if we allow the existence of `any_parser`, it would become
|
||||
// a very undesirable technical burden which prohibits the future enhancements.
|
||||
// Imagine that we're implementing an out-of-the-box packrat memoization support in
|
||||
// the future. The existence of `any_parser` makes the situation undesirably complex,
|
||||
// as we need to consider the *dynamic* properties of stateful parsers.
|
||||
typedef Attribute attribute_type;
|
||||
|
||||
using attribute_type = Attribute;
|
||||
|
||||
static constexpr bool has_attribute = !std::is_same_v<Attribute, unused_type>;
|
||||
static constexpr bool handles_container = traits::is_container<Attribute>::value;
|
||||
static bool const has_attribute =
|
||||
!is_same<unused_type, attribute_type>::value;
|
||||
static bool const handles_container =
|
||||
traits::is_container<Attribute>::value;
|
||||
|
||||
public:
|
||||
constexpr any_parser() = default;
|
||||
any_parser() = default;
|
||||
|
||||
template <typename Parser>
|
||||
requires
|
||||
(!std::is_same_v<std::remove_cvref_t<Parser>, any_parser>) &&
|
||||
X3Parser<Parser, It, It>
|
||||
[[deprecated(
|
||||
"`any_parser` is deprecated. Prefer static grammar "
|
||||
"(e.g. `a_prefix >> a_body | b_prefix >> b_body`) or "
|
||||
"static branching (e.g. `x3::eps[lazy_cond_func] >> a | b`)."
|
||||
)]]
|
||||
constexpr any_parser(Parser&& parser)
|
||||
: parser_(std::make_unique<holder<as_parser_plain_t<Parser>>>(
|
||||
std::forward<Parser>(parser)
|
||||
))
|
||||
{}
|
||||
template <typename Expr,
|
||||
typename Enable = typename enable_if<traits::is_parser<Expr>>::type>
|
||||
any_parser(Expr const& expr)
|
||||
: _content(new holder<Expr>(expr)) {}
|
||||
|
||||
constexpr any_parser(any_parser const& other)
|
||||
: parser_(other.parser_ ? other.parser_->clone() : nullptr)
|
||||
{}
|
||||
any_parser(any_parser const& other)
|
||||
: _content(other._content ? other._content->clone() : nullptr) {}
|
||||
|
||||
constexpr any_parser(any_parser&& other) = default;
|
||||
any_parser(any_parser&& other) = default;
|
||||
|
||||
constexpr any_parser& operator=(any_parser const& other)
|
||||
any_parser& operator=(any_parser const& other)
|
||||
{
|
||||
parser_.reset(other.parser_ ? other.parser_->clone() : nullptr);
|
||||
_content.reset(other._content ? other._content->clone() : nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
any_parser& operator=(any_parser&& other) = default;
|
||||
|
||||
// Runtime attribute is the same type as the predefined attribute type
|
||||
template <std::forward_iterator It_, std::sentinel_for<It_> Se_, typename Context_>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It_& first, Se_ const& last,
|
||||
Context_ const& context, unused_type, Attribute& attr
|
||||
) const
|
||||
template <typename Iterator_, typename Context_>
|
||||
bool parse(Iterator_& first, Iterator_ const& last
|
||||
, Context_ const& context, unused_type, Attribute& attr) const
|
||||
{
|
||||
static_assert(std::is_same_v<It_, It>, "Runtime iterator type must match `any_parser`'s iterator type");
|
||||
BOOST_ASSERT_MSG(parser_ != nullptr, "Invalid use of uninitialized any_parser");
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
(is_same<Iterator, Iterator_>::value)
|
||||
, "Incompatible iterator used"
|
||||
);
|
||||
|
||||
return parser_->parse(first, last, context, attr);
|
||||
BOOST_ASSERT_MSG(
|
||||
(_content != nullptr)
|
||||
, "Invalid use of uninitialized any_parser"
|
||||
);
|
||||
|
||||
return _content->parse(first, last, context, attr);
|
||||
}
|
||||
|
||||
// Runtime attribute is NOT the same type as the predefined attribute type
|
||||
template <std::forward_iterator It_, std::sentinel_for<It_> Se_, typename Context_, typename Attribute_>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It_& first, Se_ const& last,
|
||||
Context_ const& context, unused_type, Attribute_& attr_
|
||||
) const
|
||||
template <typename Iterator_, typename Context_, typename Attribute_>
|
||||
bool parse(Iterator_& first, Iterator_ const& last
|
||||
, Context_ const& context, unused_type, Attribute_& attr_) const
|
||||
{
|
||||
Attribute attr; // default-initialize
|
||||
if (this->parse(first, last, context, unused, attr))
|
||||
Attribute attr;
|
||||
if (parse(first, last, context, unused, attr))
|
||||
{
|
||||
traits::move_to(std::move(attr), attr_);
|
||||
traits::move_to(attr, attr_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::string get_x3_info() const
|
||||
std::string get_info() const
|
||||
{
|
||||
return parser_ ? parser_->get_x3_info() : "(uninitialized `any_parser`)";
|
||||
return _content ? _content->get_info() : "";
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct placeholder
|
||||
{
|
||||
constexpr virtual ~placeholder() = default;
|
||||
virtual placeholder* clone() const = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr virtual std::unique_ptr<placeholder> clone() const = 0;
|
||||
virtual bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, Attribute& attr) const = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr virtual bool parse(
|
||||
It& first, It const& last, Context const& context, Attribute& attr
|
||||
) const = 0;
|
||||
virtual std::string get_info() const = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr virtual std::string get_x3_info() const = 0;
|
||||
virtual ~placeholder() {}
|
||||
};
|
||||
|
||||
template <X3Parser<It, It> Parser>
|
||||
template <typename Expr>
|
||||
struct holder : placeholder
|
||||
{
|
||||
template <X3Subject Subject>
|
||||
requires is_parser_constructible_v<Parser, Subject>
|
||||
constexpr explicit holder(Subject&& subject)
|
||||
noexcept(is_parser_nothrow_constructible_v<Parser, Subject>)
|
||||
: parser_(as_parser(std::forward<Subject>(subject)))
|
||||
{}
|
||||
typedef typename extension::as_parser<Expr>::value_type parser_type;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::unique_ptr<placeholder> clone() const override
|
||||
explicit holder(Expr const& p)
|
||||
: _parser(as_parser(p)) {}
|
||||
|
||||
holder* clone() const override
|
||||
{
|
||||
return std::make_unique<holder>(*this);
|
||||
return new holder(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool parse(
|
||||
It& first, It const& last,
|
||||
Context const& context, Attribute& attr
|
||||
) const override
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, Attribute& attr) const override
|
||||
{
|
||||
static_assert(Parsable<Parser, It, It, Context, unused_type, Attribute>);
|
||||
return parser_.parse(first, last, context, unused, attr);
|
||||
return _parser.parse(first, last, context, unused, attr);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::string get_x3_info() const override
|
||||
std::string get_info() const override
|
||||
{
|
||||
return x3::what(parser_);
|
||||
return x3::what(_parser);
|
||||
}
|
||||
|
||||
private:
|
||||
Parser parser_;
|
||||
parser_type _parser;
|
||||
};
|
||||
|
||||
std::unique_ptr<placeholder> parser_;
|
||||
private:
|
||||
std::unique_ptr<placeholder> _content;
|
||||
};
|
||||
|
||||
} // boost::spirit::x3
|
||||
template <typename Iterator, typename Attribute, typename Context>
|
||||
struct get_info<any_parser<Iterator, Attribute, Context>>
|
||||
{
|
||||
typedef std::string result_type;
|
||||
std::string operator()(
|
||||
any_parser<Iterator, Attribute, Context> const& p) const
|
||||
{
|
||||
return p.get_info();
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2017 wanghan02
|
||||
Copyright (c) 2024-2025 Nana Sakisaka
|
||||
Copyright (c) 2024 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -12,79 +12,57 @@
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/error_handler_types.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
enum class error_handler_result
|
||||
{
|
||||
fail
|
||||
, retry
|
||||
, accept
|
||||
, rethrow // see BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE for alternative behaviors
|
||||
};
|
||||
|
||||
template <typename Subject, typename Handler>
|
||||
struct guard : unary_parser<Subject, guard<Subject, Handler>>
|
||||
{
|
||||
static_assert(
|
||||
!std::is_reference_v<Handler>,
|
||||
"Reference type is disallowed for `Handler` to prevent dangling reference"
|
||||
);
|
||||
typedef unary_parser<Subject, guard<Subject, Handler>> base_type;
|
||||
static bool const is_pass_through_unary = true;
|
||||
|
||||
using base_type = unary_parser<Subject, guard<Subject, Handler>>;
|
||||
static constexpr bool is_pass_through_unary = true;
|
||||
constexpr guard(Subject const& subject, Handler handler)
|
||||
: base_type(subject), handler(handler) {}
|
||||
|
||||
Handler handler;
|
||||
|
||||
template <typename SubjectT, typename HandlerT>
|
||||
requires std::is_constructible_v<Subject, SubjectT> && std::is_constructible_v<Handler, HandlerT>
|
||||
constexpr guard(SubjectT&& subject, HandlerT&& handler)
|
||||
noexcept(std::is_nothrow_constructible_v<Subject, SubjectT> && std::is_nothrow_constructible_v<Handler, HandlerT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
, handler(std::forward<HandlerT>(handler))
|
||||
{}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
// never noexcept; requires complex implementation details
|
||||
template <typename Iterator, typename Context
|
||||
, typename RuleContext, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RuleContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
static_assert(Parsable<Subject, It, Se, Context, RContext, Attribute>);
|
||||
|
||||
while (true)
|
||||
for (;;)
|
||||
{
|
||||
It saved_it = first;
|
||||
Iterator i = first;
|
||||
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
try
|
||||
#endif
|
||||
{
|
||||
if (this->subject.parse(saved_it, last, context, rcontext, attr))
|
||||
if (this->subject.parse(i, last, context, rcontext, attr))
|
||||
{
|
||||
first = saved_it;
|
||||
first = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
catch (expectation_failure<It> const& x) {
|
||||
catch (expectation_failure<Iterator> const& x) {
|
||||
#else
|
||||
if (x3::has_expectation_failure(context)) {
|
||||
auto const& x = x3::get_expectation_failure(context);
|
||||
if (has_expectation_failure(context)) {
|
||||
auto& x = get_expectation_failure(context);
|
||||
#endif
|
||||
static_assert(
|
||||
std::is_invocable_r_v<
|
||||
error_handler_result,
|
||||
Handler const&,
|
||||
It const&, Se const&,
|
||||
std::remove_cvref_t<decltype(x)> const&,
|
||||
Context const&
|
||||
>,
|
||||
"x3::guard: `Handler`'s signature is wrong"
|
||||
);
|
||||
|
||||
// X3 developer note: don't forget to sync this implementation with x3::detail::rule_parser
|
||||
switch (handler(std::as_const(first), std::as_const(last), x, context))
|
||||
switch (handler(first, last, x, context))
|
||||
{
|
||||
case error_handler_result::fail:
|
||||
x3::clear_expectation_failure(context);
|
||||
clear_expectation_failure(context);
|
||||
return false;
|
||||
|
||||
case error_handler_result::retry:
|
||||
@@ -104,7 +82,9 @@ namespace boost::spirit::x3
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Handler handler;
|
||||
};
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -8,56 +7,62 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_ANY_CHAR_APRIL_16_2006_1051AM)
|
||||
#define BOOST_SPIRIT_X3_ANY_CHAR_APRIL_16_2006_1051AM
|
||||
|
||||
#include <boost/type_traits/extent.hpp>
|
||||
#include <boost/spirit/home/x3/char/literal_char.hpp>
|
||||
#include <boost/spirit/home/x3/char/char_set.hpp>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Encoding>
|
||||
struct any_char : char_parser<any_char<Encoding>>
|
||||
{
|
||||
using char_type = typename Encoding::char_type;
|
||||
using encoding = Encoding;
|
||||
using attribute_type = char_type;
|
||||
static constexpr bool has_attribute = true;
|
||||
typedef typename Encoding::char_type char_type;
|
||||
typedef Encoding encoding;
|
||||
typedef char_type attribute_type;
|
||||
static bool const has_attribute = true;
|
||||
|
||||
template <typename Context>
|
||||
[[nodiscard]] static constexpr bool test(char_type ch, Context const&) noexcept
|
||||
template <typename Char, typename Context>
|
||||
bool test(Char ch_, Context const&) const
|
||||
{
|
||||
return encoding::ischar(ch);
|
||||
return encoding::ischar(ch_);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr literal_char<Encoding> operator()(char_type ch) noexcept
|
||||
template <typename Char>
|
||||
constexpr literal_char<Encoding> operator()(Char ch) const
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr literal_char<Encoding> operator()(char_type const (&ch)[2]) noexcept
|
||||
template <typename Char>
|
||||
constexpr literal_char<Encoding> operator()(const Char (&ch)[2]) const
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
[[nodiscard]] static constexpr char_set<Encoding> operator()(char_type const (&ch)[N]) noexcept
|
||||
template <typename Char, std::size_t N>
|
||||
constexpr char_set<Encoding> operator()(const Char (&ch)[N]) const
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr char_range<Encoding> operator()(char_type from, char_type to) noexcept
|
||||
template <typename Char>
|
||||
constexpr char_range<Encoding> operator()(Char from, Char to) const
|
||||
{
|
||||
return { from, to };
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr char_range<Encoding> operator()(char_type const (&from)[2], char_type const (&to)[2]) noexcept
|
||||
template <typename Char>
|
||||
constexpr char_range<Encoding> operator()(Char (&from)[2], Char (&to)[2]) const
|
||||
{
|
||||
return { static_cast<char_type>(from[0]), static_cast<char_type>(to[0]) };
|
||||
}
|
||||
|
||||
[[nodiscard]] static char_set<Encoding> operator()(std::basic_string_view<char_type> sv) noexcept
|
||||
template <typename Char>
|
||||
char_set<Encoding> operator()(std::basic_string<Char> const& s) const
|
||||
{
|
||||
return { std::move(sv) };
|
||||
return { s };
|
||||
}
|
||||
};
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -9,143 +8,84 @@
|
||||
#define BOOST_SPIRIT_X3_CHAR_APRIL_16_2006_1051AM
|
||||
|
||||
#include <boost/spirit/home/x3/char/any_char.hpp>
|
||||
#include <boost/spirit/home/x3/char/literal_char.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/string_traits.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/iso8859_1.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard_wide.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/char_encoding/detail/encoding_warning.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/ascii.hpp> // deprecated
|
||||
#include <boost/spirit/home/x3/char_encoding/iso8859_1.hpp> // deprecated
|
||||
#include <boost/spirit/home/x3/char_encoding/standard.hpp>
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
# include <boost/spirit/home/x3/char_encoding/standard_wide.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
# include <boost/spirit/home/x3/char_encoding/unicode.hpp>
|
||||
#endif
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
namespace standard
|
||||
{
|
||||
inline constexpr any_char<char_encoding::standard> char_{};
|
||||
typedef any_char<char_encoding::standard> char_type;
|
||||
constexpr auto char_ = char_type{};
|
||||
|
||||
inline namespace helpers
|
||||
constexpr literal_char<char_encoding::standard, unused_type>
|
||||
lit(char ch)
|
||||
{
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard, unused_type>
|
||||
lit(char ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
return { ch };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard, unused_type>
|
||||
lit(traits::X3VagueArrayOf2Chars<char> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
} // helpers
|
||||
constexpr literal_char<char_encoding::standard, unused_type>
|
||||
lit(wchar_t ch)
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
// If you see "no matching overload" on string literals (e.g. `"foo"`),
|
||||
// you may need to include `x3/string/literal_string.hpp`.
|
||||
// If you still see errors after the inclusion, that might be due to
|
||||
// mixing incompatible string literals. Don't do that.
|
||||
|
||||
constexpr void lit(traits::CharIncompatibleWith<char> auto const*) = delete; // Mixing incompatible character types is not allowed
|
||||
constexpr void lit(traits::CharIncompatibleWith<char> auto) = delete; // Mixing incompatible character types is not allowed
|
||||
}
|
||||
|
||||
inline constexpr auto const& char_ = standard::char_; // TODO: this can't overload other character types
|
||||
using standard::helpers::lit;
|
||||
using standard::char_type;
|
||||
using standard::char_;
|
||||
using standard::lit;
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
namespace standard_wide
|
||||
{
|
||||
inline constexpr any_char<char_encoding::standard_wide> char_{};
|
||||
typedef any_char<char_encoding::standard_wide> char_type;
|
||||
constexpr auto char_ = char_type{};
|
||||
|
||||
inline namespace helpers
|
||||
constexpr literal_char<char_encoding::standard_wide, unused_type>
|
||||
lit(wchar_t ch)
|
||||
{
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard_wide, unused_type>
|
||||
lit(wchar_t ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard_wide, unused_type>
|
||||
lit(traits::X3VagueArrayOf2Chars<wchar_t> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
} // helpers
|
||||
|
||||
constexpr void lit(traits::CharIncompatibleWith<wchar_t> auto const*) = delete; // Mixing incompatible character types is not allowed
|
||||
constexpr void lit(traits::CharIncompatibleWith<wchar_t> auto) = delete; // Mixing incompatible character types is not allowed
|
||||
return { ch };
|
||||
}
|
||||
}
|
||||
|
||||
using standard_wide::helpers::lit;
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
namespace unicode
|
||||
{
|
||||
inline constexpr any_char<char_encoding::unicode> char_{};
|
||||
|
||||
inline namespace helpers
|
||||
{
|
||||
// TODO: add `char8_t` and `char16_t` overloads
|
||||
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::unicode, unused_type>
|
||||
lit(char32_t ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::unicode, unused_type>
|
||||
lit(traits::X3VagueArrayOf2Chars<char32_t> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
} // helpers
|
||||
|
||||
constexpr void lit(traits::CharIncompatibleWith<char32_t> auto const*) = delete; // Mixing incompatible character types is not allowed
|
||||
constexpr void lit(traits::CharIncompatibleWith<char32_t> auto) = delete; // Mixing incompatible character types is not allowed
|
||||
}
|
||||
|
||||
using unicode::helpers::lit;
|
||||
#endif
|
||||
|
||||
namespace ascii
|
||||
{
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
inline constexpr any_char<char_encoding::ascii> char_{};
|
||||
typedef any_char<char_encoding::ascii> char_type;
|
||||
constexpr auto char_ = char_type{};
|
||||
|
||||
[[nodiscard, deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
constexpr literal_char<char_encoding::ascii, unused_type>
|
||||
lit(char ch) noexcept
|
||||
lit(char ch)
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
constexpr void lit(traits::CharIncompatibleWith<char> auto const*) = delete; // Mixing incompatible character types is not allowed
|
||||
constexpr void lit(traits::CharIncompatibleWith<char> auto) = delete; // Mixing incompatible character types is not allowed
|
||||
constexpr literal_char<char_encoding::ascii, unused_type>
|
||||
lit(wchar_t ch)
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
}
|
||||
|
||||
namespace iso8859_1
|
||||
{
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
inline constexpr any_char<char_encoding::iso8859_1> char_{};
|
||||
typedef any_char<char_encoding::iso8859_1> char_type;
|
||||
constexpr auto char_ = char_type{};
|
||||
|
||||
[[nodiscard, deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
constexpr literal_char<char_encoding::iso8859_1, unused_type>
|
||||
lit(char ch) noexcept
|
||||
lit(char ch)
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
constexpr void lit(traits::CharIncompatibleWith<char> auto const*) = delete; // Mixing incompatible character types is not allowed
|
||||
constexpr void lit(traits::CharIncompatibleWith<char> auto) = delete; // Mixing incompatible character types is not allowed
|
||||
constexpr literal_char<char_encoding::iso8859_1, unused_type>
|
||||
lit(wchar_t ch)
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
}
|
||||
|
||||
namespace extension
|
||||
@@ -153,23 +93,29 @@ namespace boost::spirit::x3
|
||||
template <>
|
||||
struct as_parser<char>
|
||||
{
|
||||
using type = literal_char<char_encoding::standard, unused_type>;
|
||||
using value_type = type;
|
||||
typedef literal_char<
|
||||
char_encoding::standard, unused_type>
|
||||
type;
|
||||
|
||||
[[nodiscard]] static constexpr type call(char ch) noexcept
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(char ch)
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
template <>
|
||||
struct as_parser<wchar_t>
|
||||
{
|
||||
using type = literal_char<char_encoding::standard_wide, unused_type>;
|
||||
using value_type = type;
|
||||
typedef literal_char<
|
||||
char_encoding::standard_wide, unused_type>
|
||||
type;
|
||||
|
||||
[[nodiscard]] static constexpr type call(wchar_t ch) noexcept
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(wchar_t ch)
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
@@ -179,30 +125,37 @@ namespace boost::spirit::x3
|
||||
template <>
|
||||
struct as_parser<char [2]>
|
||||
{
|
||||
using type = literal_char<char_encoding::standard, unused_type>;
|
||||
using value_type = type;
|
||||
typedef literal_char<
|
||||
char_encoding::standard, unused_type>
|
||||
type;
|
||||
|
||||
[[nodiscard]] static constexpr type call(char const ch[]) noexcept
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(char const ch[])
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
template <>
|
||||
struct as_parser<wchar_t [2]>
|
||||
{
|
||||
using type = literal_char<char_encoding::standard_wide, unused_type>;
|
||||
using value_type = type;
|
||||
typedef literal_char<
|
||||
char_encoding::standard_wide, unused_type>
|
||||
type;
|
||||
|
||||
[[nodiscard]] static constexpr type call(wchar_t const ch[]) noexcept
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(wchar_t const ch[] )
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -9,31 +8,30 @@
|
||||
#define BOOST_SPIRIT_X3_CHAR_CLASS_APRIL_16_2006_1051AM
|
||||
|
||||
#include <boost/spirit/home/x3/char/char_parser.hpp>
|
||||
#include <boost/spirit/home/x3/char/char_class_tags.hpp>
|
||||
#include <boost/spirit/home/x3/char/detail/cast_char.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/char_encoding/detail/encoding_warning.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/standard_wide.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/iso8859_1.hpp>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
#include <boost/spirit/home/support/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard_wide.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/iso8859_1.hpp>
|
||||
#include <boost/spirit/home/x3/char/char_class_tags.hpp>
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Encoding>
|
||||
struct char_class_base
|
||||
{
|
||||
using char_type = typename Encoding::classify_type;
|
||||
typedef typename Encoding::classify_type char_type;
|
||||
|
||||
#define BOOST_SPIRIT_X3_CLASSIFY(name) \
|
||||
template <typename Char> \
|
||||
[[nodiscard]] static constexpr bool \
|
||||
is(name##_tag, Char ch) noexcept \
|
||||
static bool \
|
||||
is(name##_tag, Char ch) \
|
||||
{ \
|
||||
return (Encoding::is##name) \
|
||||
return Encoding::is##name \
|
||||
BOOST_PREVENT_MACRO_SUBSTITUTION \
|
||||
(detail::cast_char<char_type>(ch)); \
|
||||
}
|
||||
} \
|
||||
/***/
|
||||
|
||||
BOOST_SPIRIT_X3_CLASSIFY(char)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(alnum)
|
||||
@@ -53,26 +51,28 @@ namespace boost::spirit::x3
|
||||
};
|
||||
|
||||
template <typename Encoding, typename Tag>
|
||||
struct char_class : char_parser<char_class<Encoding, Tag>>
|
||||
struct char_class
|
||||
: char_parser<char_class<Encoding, Tag>>
|
||||
{
|
||||
using encoding = Encoding;
|
||||
using tag = Tag;
|
||||
using char_type = typename Encoding::char_type;
|
||||
using attribute_type = char_type;
|
||||
static constexpr bool has_attribute = true;
|
||||
typedef Encoding encoding;
|
||||
typedef Tag tag;
|
||||
typedef typename Encoding::char_type char_type;
|
||||
typedef char_type attribute_type;
|
||||
static bool const has_attribute = true;
|
||||
|
||||
template <typename Char, typename Context>
|
||||
[[nodiscard]] constexpr bool test(Char ch, Context const& context) const noexcept
|
||||
bool test(Char ch, Context const& context) const
|
||||
{
|
||||
return encoding::ischar(ch)
|
||||
&& char_class_base<Encoding>::is(
|
||||
x3::get_case_compare<Encoding>(context).get_char_class_tag(tag()), ch);
|
||||
get_case_compare<Encoding>(context).get_char_class_tag(tag()), ch);
|
||||
}
|
||||
};
|
||||
|
||||
#define BOOST_SPIRIT_X3_CHAR_CLASS(encoding, name) \
|
||||
using name##_type = char_class<char_encoding::encoding, name##_tag>; \
|
||||
inline constexpr name##_type name{};
|
||||
typedef char_class<char_encoding::encoding, name##_tag> name##_type; \
|
||||
constexpr name##_type name = name##_type(); \
|
||||
/***/
|
||||
|
||||
#define BOOST_SPIRIT_X3_CHAR_CLASSES(encoding) \
|
||||
namespace encoding \
|
||||
@@ -89,46 +89,44 @@ namespace boost::spirit::x3
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(encoding, space) \
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(encoding, blank) \
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(encoding, upper) \
|
||||
}
|
||||
} \
|
||||
/***/
|
||||
|
||||
BOOST_SPIRIT_X3_CHAR_CLASSES(standard)
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
BOOST_SPIRIT_X3_CHAR_CLASSES(standard_wide)
|
||||
#endif
|
||||
|
||||
BOOST_SPIRIT_X3_CHAR_CLASSES(ascii)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASSES(iso8859_1)
|
||||
|
||||
#undef BOOST_SPIRIT_X3_CHAR_CLASS
|
||||
#undef BOOST_SPIRIT_X3_CHAR_CLASSES
|
||||
|
||||
using alnum_type = standard::alnum_type;
|
||||
using alpha_type = standard::alpha_type;
|
||||
using digit_type = standard::digit_type;
|
||||
using xdigit_type = standard::xdigit_type;
|
||||
using cntrl_type = standard::cntrl_type;
|
||||
using graph_type = standard::graph_type;
|
||||
using lower_type = standard::lower_type;
|
||||
using print_type = standard::print_type;
|
||||
using punct_type = standard::punct_type;
|
||||
using space_type = standard::space_type;
|
||||
using blank_type = standard::blank_type;
|
||||
using upper_type = standard::upper_type;
|
||||
using standard::alnum_type;
|
||||
using standard::alpha_type;
|
||||
using standard::digit_type;
|
||||
using standard::xdigit_type;
|
||||
using standard::cntrl_type;
|
||||
using standard::graph_type;
|
||||
using standard::lower_type;
|
||||
using standard::print_type;
|
||||
using standard::punct_type;
|
||||
using standard::space_type;
|
||||
using standard::blank_type;
|
||||
using standard::upper_type;
|
||||
|
||||
inline constexpr auto const& alnum = standard::alnum;
|
||||
inline constexpr auto const& alpha = standard::alpha;
|
||||
inline constexpr auto const& digit = standard::digit;
|
||||
inline constexpr auto const& xdigit = standard::xdigit;
|
||||
inline constexpr auto const& cntrl = standard::cntrl;
|
||||
inline constexpr auto const& graph = standard::graph;
|
||||
inline constexpr auto const& lower = standard::lower;
|
||||
inline constexpr auto const& print = standard::print;
|
||||
inline constexpr auto const& punct = standard::punct;
|
||||
inline constexpr auto const& space = standard::space;
|
||||
inline constexpr auto const& blank = standard::blank;
|
||||
inline constexpr auto const& upper = standard::upper;
|
||||
|
||||
} // boost::spirit::x3
|
||||
using standard::alnum;
|
||||
using standard::alpha;
|
||||
using standard::digit;
|
||||
using standard::xdigit;
|
||||
using standard::cntrl;
|
||||
using standard::graph;
|
||||
using standard::lower;
|
||||
using standard::print;
|
||||
using standard::punct;
|
||||
using standard::space;
|
||||
using standard::blank;
|
||||
using standard::upper;
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -13,28 +12,29 @@
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
#include <boost/spirit/home/x3/support/no_case.hpp>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The base char_parser
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Derived>
|
||||
struct char_parser : parser<Derived>
|
||||
{
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename Attribute>
|
||||
[[nodiscard]] constexpr bool parse(
|
||||
It& first, Se const& last, Context const& context, unused_type, Attribute& attr
|
||||
) const // I (saki7) don't think this can ever be noexcept, due to the nature of the operations below
|
||||
template <typename Iterator, typename Context, typename Attribute>
|
||||
bool parse(
|
||||
Iterator& first, Iterator const& last
|
||||
, Context const& context, unused_type, Attribute& attr) const
|
||||
{
|
||||
x3::skip_over(first, last, context);
|
||||
if (first != last && this->derived().test(*first, context))
|
||||
{
|
||||
x3::traits::move_to(std::iter_value_t<It>{*first}, attr);
|
||||
x3::traits::move_to(*first, attr);
|
||||
++first;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -10,73 +9,72 @@
|
||||
|
||||
#include <boost/spirit/home/x3/char/char_parser.hpp>
|
||||
#include <boost/spirit/home/x3/char/detail/cast_char.hpp>
|
||||
#include <boost/spirit/home/x3/char/detail/basic_chset.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/string_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/utf8.hpp>
|
||||
#include <boost/spirit/home/x3/support/no_case.hpp>
|
||||
#include <boost/spirit/home/support/char_set/basic_chset.hpp>
|
||||
|
||||
#include <ranges>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Parser for a character range
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Encoding, typename Attribute = typename Encoding::char_type>
|
||||
struct char_range : char_parser<char_range<Encoding, Attribute>>
|
||||
struct char_range
|
||||
: char_parser< char_range<Encoding, Attribute> >
|
||||
{
|
||||
using char_type = typename Encoding::char_type;
|
||||
using encoding = Encoding;
|
||||
using attribute_type = Attribute;
|
||||
static constexpr bool has_attribute = !std::is_same_v<unused_type, attribute_type>;
|
||||
|
||||
constexpr char_range(char_type from_, char_type to_) noexcept
|
||||
: from(from_), to(to_)
|
||||
{}
|
||||
typedef typename Encoding::char_type char_type;
|
||||
typedef Encoding encoding;
|
||||
typedef Attribute attribute_type;
|
||||
static bool const has_attribute =
|
||||
!is_same<unused_type, attribute_type>::value;
|
||||
|
||||
|
||||
constexpr char_range(char_type from_, char_type to_)
|
||||
: from(from_), to(to_) {}
|
||||
|
||||
template <typename Char, typename Context>
|
||||
requires (std::is_convertible_v<std::remove_cvref_t<Char>, char_type>)
|
||||
[[nodiscard]] constexpr bool test(Char ch_, Context const& context) const noexcept
|
||||
bool test(Char ch_, Context const& context) const
|
||||
{
|
||||
char_type ch = static_cast<char_type>(ch_); // optimize for token based parsing
|
||||
return (x3::get_case_compare<encoding>(context)(ch, from) >= 0)
|
||||
&& (x3::get_case_compare<encoding>(context)(ch , to) <= 0);
|
||||
|
||||
char_type ch = char_type(ch_); // optimize for token based parsing
|
||||
return (get_case_compare<encoding>(context)(ch, from) >= 0)
|
||||
&& (get_case_compare<encoding>(context)(ch , to) <= 0);
|
||||
}
|
||||
|
||||
char_type from, to;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Parser for a character set
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Encoding, typename Attribute = typename Encoding::char_type>
|
||||
struct char_set : char_parser<char_set<Encoding, Attribute>>
|
||||
{
|
||||
using char_type = typename Encoding::char_type;
|
||||
using encoding = Encoding;
|
||||
using attribute_type = Attribute;
|
||||
static constexpr bool has_attribute = !std::is_same_v<unused_type, attribute_type>;
|
||||
typedef typename Encoding::char_type char_type;
|
||||
typedef Encoding encoding;
|
||||
typedef Attribute attribute_type;
|
||||
static bool const has_attribute =
|
||||
!is_same<unused_type, attribute_type>::value;
|
||||
|
||||
template<std::ranges::forward_range R>
|
||||
constexpr char_set(R const& str)
|
||||
noexcept(detail::cast_char_noexcept<std::ranges::range_value_t<R>, char_type>)
|
||||
template <typename String>
|
||||
char_set(String const& str)
|
||||
{
|
||||
static_assert(detail::cast_char_viable<std::ranges::range_value_t<R>, char_type>);
|
||||
using spirit::x3::detail::cast_char;
|
||||
|
||||
using detail::cast_char; // ADL introduction
|
||||
|
||||
for (auto definition = std::ranges::begin(str); definition != std::ranges::end(str);)
|
||||
auto* definition = traits::get_c_string(str);
|
||||
auto ch = *definition++;
|
||||
while (ch)
|
||||
{
|
||||
auto const ch = *definition;
|
||||
auto next_definition = std::next(definition);
|
||||
if (next_definition == std::ranges::end(str))
|
||||
auto next = *definition++;
|
||||
if (next == '-')
|
||||
{
|
||||
chset.set(cast_char<char_type>(ch));
|
||||
break;
|
||||
}
|
||||
auto next_ch = *next_definition;
|
||||
if (next_ch == '-')
|
||||
{
|
||||
next_definition = std::next(next_definition);
|
||||
if (next_definition == std::ranges::end(str))
|
||||
next = *definition++;
|
||||
if (next == 0)
|
||||
{
|
||||
chset.set(cast_char<char_type>(ch));
|
||||
chset.set('-');
|
||||
@@ -84,47 +82,46 @@ namespace boost::spirit::x3
|
||||
}
|
||||
chset.set(
|
||||
cast_char<char_type>(ch),
|
||||
cast_char<char_type>(*next_definition)
|
||||
cast_char<char_type>(next)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
chset.set(cast_char<char_type>(ch));
|
||||
}
|
||||
definition = next_definition;
|
||||
ch = next;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char, typename Context>
|
||||
[[nodiscard]] constexpr bool test(Char ch_, Context const& context) const noexcept
|
||||
bool test(Char ch_, Context const& context) const
|
||||
{
|
||||
return x3::get_case_compare<encoding>(context).in_set(ch_, chset);
|
||||
return get_case_compare<encoding>(context).in_set(ch_, chset);
|
||||
}
|
||||
|
||||
detail::basic_chset<char_type> chset;
|
||||
support::detail::basic_chset<char_type> chset;
|
||||
};
|
||||
|
||||
template <typename Encoding, typename Attribute>
|
||||
struct get_info<char_set<Encoding, Attribute>>
|
||||
{
|
||||
using result_type = std::string;
|
||||
[[nodiscard]] constexpr std::string operator()(char_set<Encoding, Attribute> const& /* p */) const
|
||||
typedef std::string result_type;
|
||||
std::string operator()(char_set<Encoding, Attribute> const& /* p */) const
|
||||
{
|
||||
return "char-set"; // TODO: make more user-friendly
|
||||
return "char-set";
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Encoding, typename Attribute>
|
||||
struct get_info<char_range<Encoding, Attribute>>
|
||||
{
|
||||
using result_type = std::string;
|
||||
[[nodiscard]] constexpr std::string operator()(char_range<Encoding, Attribute> const& p) const
|
||||
typedef std::string result_type;
|
||||
std::string operator()(char_range<Encoding, Attribute> const& p) const
|
||||
{
|
||||
// TODO: make more user-friendly && make the format consistent with above
|
||||
return "char_range \"" + x3::to_utf8(Encoding::toucs4(p.from)) + '-' + x3::to_utf8(Encoding::toucs4(p.to))+ '"';
|
||||
return "char_range \"" + to_utf8(Encoding::toucs4(p.from)) + '-' + to_utf8(Encoding::toucs4(p.to))+ '"';
|
||||
}
|
||||
};
|
||||
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,235 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2001-2009 Daniel Nuffer
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CHAR_DETAIL_BASIC_CHSET_HPP
|
||||
#define BOOST_SPIRIT_X3_CHAR_DETAIL_BASIC_CHSET_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/char/detail/char_range_run.hpp>
|
||||
|
||||
#include <bitset>
|
||||
#include <climits>
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
{
|
||||
// basic character set implementation using char_range_run
|
||||
template <typename CharT>
|
||||
struct basic_chset
|
||||
{
|
||||
[[nodiscard]] constexpr bool
|
||||
test(CharT v) const noexcept
|
||||
{
|
||||
return rr.test(v);
|
||||
}
|
||||
|
||||
constexpr void
|
||||
set(CharT from, CharT to) noexcept
|
||||
{
|
||||
rr.set(char_range<CharT>(from, to));
|
||||
}
|
||||
|
||||
constexpr void
|
||||
set(CharT c) noexcept
|
||||
{
|
||||
rr.set(char_range<CharT>(c, c));
|
||||
}
|
||||
|
||||
constexpr void
|
||||
clear(CharT from, CharT to) noexcept
|
||||
{
|
||||
rr.clear(char_range<CharT>(from, to));
|
||||
}
|
||||
|
||||
constexpr void
|
||||
clear(CharT c) noexcept
|
||||
{
|
||||
rr.clear(char_range<CharT>(c, c));
|
||||
}
|
||||
|
||||
constexpr void
|
||||
clear() noexcept
|
||||
{
|
||||
rr.clear();
|
||||
}
|
||||
|
||||
constexpr void
|
||||
inverse() noexcept
|
||||
{
|
||||
basic_chset inv;
|
||||
inv.set(
|
||||
(std::numeric_limits<CharT>::min)(),
|
||||
(std::numeric_limits<CharT>::max)()
|
||||
);
|
||||
inv -= *this;
|
||||
swap(inv);
|
||||
}
|
||||
|
||||
constexpr void
|
||||
swap(basic_chset& x) noexcept
|
||||
{
|
||||
rr.swap(x.rr);
|
||||
}
|
||||
|
||||
|
||||
constexpr basic_chset&
|
||||
operator|=(basic_chset const& x) noexcept
|
||||
{
|
||||
typedef typename char_range_run<CharT>::const_iterator const_iterator;
|
||||
for (const_iterator iter = x.rr.begin(); iter != x.rr.end(); ++iter)
|
||||
rr.set(*iter);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr basic_chset&
|
||||
operator&=(basic_chset const& x) noexcept
|
||||
{
|
||||
basic_chset inv;
|
||||
inv.set(
|
||||
(std::numeric_limits<CharT>::min)(),
|
||||
(std::numeric_limits<CharT>::max)()
|
||||
);
|
||||
inv -= x;
|
||||
*this -= inv;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr basic_chset&
|
||||
operator-=(basic_chset const& x) noexcept
|
||||
{
|
||||
typedef typename char_range_run<CharT>::const_iterator const_iterator;
|
||||
for (const_iterator iter = x.rr.begin(); iter != x.rr.end(); ++iter)
|
||||
rr.clear(*iter);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr basic_chset&
|
||||
operator^=(basic_chset const& x) noexcept
|
||||
{
|
||||
basic_chset bma = x;
|
||||
bma -= *this;
|
||||
*this -= x;
|
||||
*this |= bma;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
char_range_run<CharT> rr;
|
||||
};
|
||||
|
||||
#if (CHAR_BIT == 8)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// basic_chset: specializations for 8 bit chars using std::bitset
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename CharT>
|
||||
struct basic_chset_8bit
|
||||
{
|
||||
[[nodiscard]] constexpr bool
|
||||
test(CharT v) const noexcept
|
||||
{
|
||||
return bset.test((unsigned char)v);
|
||||
}
|
||||
|
||||
constexpr void
|
||||
set(CharT from, CharT to) noexcept
|
||||
{
|
||||
for (int i = from; i <= to; ++i)
|
||||
bset.set((unsigned char)i);
|
||||
}
|
||||
|
||||
constexpr void
|
||||
set(CharT c) noexcept
|
||||
{
|
||||
bset.set((unsigned char)c);
|
||||
}
|
||||
|
||||
constexpr void
|
||||
clear(CharT from, CharT to) noexcept
|
||||
{
|
||||
for (int i = from; i <= to; ++i)
|
||||
bset.reset((unsigned char)i);
|
||||
}
|
||||
|
||||
constexpr void
|
||||
clear(CharT c) noexcept
|
||||
{
|
||||
bset.reset((unsigned char)c);
|
||||
}
|
||||
|
||||
constexpr void
|
||||
clear() noexcept
|
||||
{
|
||||
bset.reset();
|
||||
}
|
||||
|
||||
constexpr void
|
||||
inverse() noexcept
|
||||
{
|
||||
bset.flip();
|
||||
}
|
||||
|
||||
constexpr void
|
||||
swap(basic_chset_8bit& x) noexcept
|
||||
{
|
||||
std::swap(bset, x.bset);
|
||||
}
|
||||
|
||||
constexpr basic_chset_8bit&
|
||||
operator|=(basic_chset_8bit const& x) noexcept
|
||||
{
|
||||
bset |= x.bset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr basic_chset_8bit&
|
||||
operator&=(basic_chset_8bit const& x) noexcept
|
||||
{
|
||||
bset &= x.bset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr basic_chset_8bit&
|
||||
operator-=(basic_chset_8bit const& x) noexcept
|
||||
{
|
||||
bset &= ~x.bset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr basic_chset_8bit&
|
||||
operator^=(basic_chset_8bit const& x) noexcept
|
||||
{
|
||||
bset ^= x.bset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
std::bitset<256> bset;
|
||||
};
|
||||
|
||||
/////////////////////////////////
|
||||
template <>
|
||||
struct basic_chset<char>
|
||||
: basic_chset_8bit<char> {};
|
||||
|
||||
/////////////////////////////////
|
||||
template <>
|
||||
struct basic_chset<signed char>
|
||||
: basic_chset_8bit<signed char> {};
|
||||
|
||||
/////////////////////////////////
|
||||
template <>
|
||||
struct basic_chset<unsigned char>
|
||||
: basic_chset_8bit<unsigned char> {};
|
||||
|
||||
#endif // #if (CHAR_BIT == 8)
|
||||
|
||||
} // boost::spirit::x3::detail
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CAST_CHAR_NOVEMBER_10_2006_0907AM
|
||||
#if !defined(BOOST_SPIRIT_X3_CAST_CHAR_NOVEMBER_10_2006_0907AM)
|
||||
#define BOOST_SPIRIT_X3_CAST_CHAR_NOVEMBER_10_2006_0907AM
|
||||
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
#include <boost/type_traits/is_signed.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
#include <boost/type_traits/make_signed.hpp>
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
// Here's the thing... typical encodings (except ASCII) deal with unsigned
|
||||
// integers > 127 (ASCII uses only 127). Yet, most char and wchar_t are signed.
|
||||
@@ -24,19 +24,25 @@ namespace boost::spirit::x3::detail
|
||||
// optimizer will optimize the if-else branches}
|
||||
|
||||
template <typename TargetChar, typename SourceChar>
|
||||
[[nodiscard]] constexpr TargetChar cast_char(SourceChar ch) noexcept
|
||||
TargetChar cast_char(SourceChar ch)
|
||||
{
|
||||
if constexpr (std::is_signed_v<TargetChar> != std::is_signed_v<SourceChar>)
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
if (is_signed<TargetChar>::value != is_signed<SourceChar>::value)
|
||||
{
|
||||
if constexpr (std::is_signed_v<SourceChar>)
|
||||
if (is_signed<SourceChar>::value)
|
||||
{
|
||||
// source is signed, target is unsigned
|
||||
return TargetChar(static_cast<std::make_unsigned_t<SourceChar>>(ch));
|
||||
// source is signed, target is unsigned
|
||||
typedef typename make_unsigned<SourceChar>::type USourceChar;
|
||||
return TargetChar(USourceChar(ch));
|
||||
}
|
||||
else
|
||||
{
|
||||
// source is unsigned, target is signed
|
||||
return TargetChar(static_cast<std::make_signed_t<SourceChar>>(ch));
|
||||
// source is unsigned, target is signed
|
||||
typedef typename make_signed<SourceChar>::type SSourceChar;
|
||||
return TargetChar(SSourceChar(ch));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -44,17 +50,12 @@ namespace boost::spirit::x3::detail
|
||||
// source and target has same signedness
|
||||
return TargetChar(ch); // just cast
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename SourceChar, typename TargetChar>
|
||||
concept cast_char_viable = requires(SourceChar ch) {
|
||||
{ cast_char<TargetChar>(ch) } -> std::convertible_to<TargetChar>;
|
||||
};
|
||||
|
||||
template <typename SourceChar, typename TargetChar>
|
||||
concept cast_char_noexcept = requires(SourceChar ch) {
|
||||
{ cast_char<TargetChar>(ch) } noexcept -> std::convertible_to<TargetChar>;
|
||||
};
|
||||
} // boost::spirit::x3::detail
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CHAR_DETAIL_CHAR_RANGE_HPP
|
||||
#define BOOST_SPIRIT_X3_CHAR_DETAIL_CHAR_RANGE_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
{
|
||||
// A closed range [first, last]
|
||||
template <typename CharT>
|
||||
struct char_range
|
||||
{
|
||||
static_assert(std::is_default_constructible_v<CharT>);
|
||||
static_assert(std::is_copy_constructible_v<CharT> && std::is_copy_assignable_v<CharT>);
|
||||
|
||||
using value_type = CharT;
|
||||
|
||||
constexpr char_range() noexcept(std::is_nothrow_default_constructible_v<CharT>) = default;
|
||||
|
||||
template<class A, class B>
|
||||
requires std::is_constructible_v<CharT, A> && std::is_constructible_v<CharT, B>
|
||||
constexpr char_range(A&& first, B&& last)
|
||||
noexcept(std::is_nothrow_constructible_v<CharT, A> && std::is_nothrow_constructible_v<CharT, B>)
|
||||
: first(std::forward<A>(first))
|
||||
, last(std::forward<B>(last))
|
||||
{}
|
||||
|
||||
CharT first{};
|
||||
CharT last{};
|
||||
};
|
||||
} // boost::spirit::x3::detail
|
||||
|
||||
#endif
|
||||
@@ -1,108 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CHAR_DETAIL_CHAR_RANGE_FUNCTIONS_HPP
|
||||
#define BOOST_SPIRIT_X3_CHAR_DETAIL_CHAR_RANGE_FUNCTIONS_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/char/detail/char_range.hpp>
|
||||
|
||||
#include <limits>
|
||||
#include <concepts>
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
{
|
||||
template <typename CharT>
|
||||
[[nodiscard]] constexpr bool
|
||||
is_valid(char_range<CharT> const& range) noexcept
|
||||
{
|
||||
// test for valid ranges
|
||||
return range.first <= range.last;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
[[nodiscard]] constexpr bool
|
||||
includes(char_range<CharT> const& range, char_range<CharT> const& other) noexcept
|
||||
{
|
||||
// see if two ranges intersect
|
||||
return (range.first <= other.first) && (range.last >= other.last);
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
[[nodiscard]] constexpr bool
|
||||
includes(char_range<CharT> const& range, CharT val) noexcept
|
||||
{
|
||||
// see if val is in range
|
||||
return (range.first <= val) && (range.last >= val);
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
[[nodiscard]] constexpr bool
|
||||
can_merge(char_range<CharT> const& range, char_range<CharT> const& other) noexcept
|
||||
{
|
||||
// see if a 'range' overlaps, or is adjacent to
|
||||
// another range 'other', so we can merge them
|
||||
|
||||
using limits = std::numeric_limits<CharT>;
|
||||
|
||||
CharT const decr_first =
|
||||
range.first == (limits::min)()
|
||||
? range.first : range.first-1;
|
||||
|
||||
CharT const incr_last =
|
||||
range.last == (limits::max)()
|
||||
? range.last : range.last+1;
|
||||
|
||||
return (decr_first <= other.last) && (incr_last >= other.first);
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
constexpr void
|
||||
merge(char_range<CharT>& result, char_range<CharT> const& other) noexcept
|
||||
{
|
||||
// merge two ranges
|
||||
if (result.first > other.first)
|
||||
{
|
||||
result.first = other.first;
|
||||
}
|
||||
if (result.last < other.last)
|
||||
{
|
||||
result.last = other.last;
|
||||
}
|
||||
}
|
||||
|
||||
struct char_range_compare
|
||||
{
|
||||
using is_transparent = int;
|
||||
|
||||
template <typename CharT>
|
||||
[[nodiscard]] constexpr bool operator()(char_range<CharT> const& x, CharT const y) const noexcept
|
||||
{
|
||||
return x.first < y;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
[[nodiscard]] constexpr bool operator()(CharT const x, char_range<CharT> const& y) const noexcept
|
||||
{
|
||||
return x < y.first;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
[[nodiscard]] constexpr bool operator()(char_range<CharT> const& x, char_range<CharT> const& y) const noexcept
|
||||
{
|
||||
return x.first < y.first;
|
||||
}
|
||||
|
||||
// This overload is required to satsify `std::indirect_strict_weak_order`
|
||||
template <std::integral CharT> // hack: minimal constraint to avoid obvious mistakes
|
||||
[[nodiscard]] constexpr bool operator()(CharT const x, CharT const y) const noexcept
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
};
|
||||
} // boost::spirit::x3::detail
|
||||
|
||||
#endif
|
||||
@@ -1,193 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CHAR_DETAIL_CHAR_RANGE_RUN_HPP
|
||||
#define BOOST_SPIRIT_X3_CHAR_DETAIL_CHAR_RANGE_RUN_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/char/detail/char_range.hpp>
|
||||
#include <boost/spirit/home/x3/char/detail/char_range_functions.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <ranges>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
{
|
||||
// An implementation of a sparse bit (boolean) set. The set uses
|
||||
// a sorted vector of disjoint ranges. This class implements the
|
||||
// bare minimum essentials from which the full range of set
|
||||
// operators can be implemented. The set is constructed from
|
||||
// ranges. Internally, adjacent or overlapping ranges are
|
||||
// coalesced.
|
||||
//
|
||||
// range_runs are very space-economical in situations where there
|
||||
// are lots of ranges and a few individual disjoint values.
|
||||
// Searching is O(log n) where n is the number of ranges.
|
||||
template <typename CharT>
|
||||
class char_range_run
|
||||
{
|
||||
public:
|
||||
using range_type = char_range<CharT>;
|
||||
using storage_type = std::vector<range_type>; // TODO: use default_init_allocator as soon as constexpr placement new is available
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
try_merge(storage_type& run, typename storage_type::iterator iter, range_type const& range)
|
||||
noexcept(std::is_nothrow_move_assignable_v<CharT>)
|
||||
{
|
||||
// *iter intersects with or is adjacent to 'range'?
|
||||
if (!detail::can_merge(*iter, range)) return false;
|
||||
|
||||
// merge range and *iter
|
||||
detail::merge(*iter, range);
|
||||
|
||||
// collapse all subsequent ranges that can merge with *iter:
|
||||
auto it = std::next(iter);
|
||||
// 1. skip subsequent ranges completely included in *iter
|
||||
while (it != run.end() && it->last <= iter->last)
|
||||
{
|
||||
++it;
|
||||
}
|
||||
// 2. collapse next range if adjacent or overlapping with *iter
|
||||
if (it != run.end() && it->first-1 <= iter->last)
|
||||
{
|
||||
iter->last = it->last;
|
||||
++it;
|
||||
}
|
||||
|
||||
// erase all ranges that were collapsed
|
||||
run.erase(std::next(iter), it);
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool test(CharT val) const noexcept
|
||||
{
|
||||
if (run_.empty()) return false;
|
||||
|
||||
// search the ranges for one that potentially includes val
|
||||
auto const iter = std::ranges::upper_bound(
|
||||
run_, val,
|
||||
char_range_compare{}
|
||||
);
|
||||
|
||||
// return true if *(iter-1) includes val
|
||||
return iter != run_.begin() && detail::includes(*std::prev(iter), val);
|
||||
}
|
||||
|
||||
constexpr void swap(char_range_run& other) noexcept
|
||||
{
|
||||
run_.swap(other.run_);
|
||||
}
|
||||
|
||||
constexpr void set(range_type const& range)
|
||||
{
|
||||
BOOST_ASSERT(detail::is_valid(range));
|
||||
if (run_.empty())
|
||||
{
|
||||
// the vector is empty, insert 'range'
|
||||
run_.emplace_back(range);
|
||||
return;
|
||||
}
|
||||
|
||||
// search the ranges for one that potentially includes 'range'
|
||||
auto iter = std::ranges::upper_bound(run_, range, char_range_compare{});
|
||||
|
||||
if (iter != run_.begin())
|
||||
{
|
||||
// if *(iter-1) includes 'range', return early
|
||||
if (detail::includes(*std::prev(iter), range))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if *(iter-1) can merge with 'range', merge them and return
|
||||
if (this->try_merge(run_, std::prev(iter), range))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if *iter can merge with with 'range', merge them
|
||||
if (iter == run_.end() || !this->try_merge(run_, iter, range))
|
||||
{
|
||||
// no overlap, insert 'range'
|
||||
run_.insert(iter, range);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void clear(range_type const& range)
|
||||
{
|
||||
BOOST_ASSERT(detail::is_valid(range));
|
||||
if (run_.empty()) return;
|
||||
|
||||
// search the ranges for one that potentially includes 'range'
|
||||
auto iter = std::ranges::upper_bound(run_, range, char_range_compare{});
|
||||
|
||||
// 'range' starts with or after another range:
|
||||
if (iter != run_.begin())
|
||||
{
|
||||
auto const left_iter = std::prev(iter);
|
||||
|
||||
// 'range' starts after '*left_iter':
|
||||
if (left_iter->first < range.first)
|
||||
{
|
||||
// if 'range' is completely included inside '*left_iter':
|
||||
// need to break it apart into two ranges (punch a hole),
|
||||
if (left_iter->last > range.last)
|
||||
{
|
||||
auto const last_save = left_iter->last;
|
||||
left_iter->last = range.first-1;
|
||||
run_.insert(iter, range_type(range.last+1, last_save));
|
||||
return;
|
||||
}
|
||||
// if 'range' contains 'left_iter->last':
|
||||
// truncate '*left_iter' (clip its right)
|
||||
else if (left_iter->last >= range.first)
|
||||
{
|
||||
left_iter->last = range.first-1;
|
||||
}
|
||||
}
|
||||
|
||||
// 'range' has the same left bound as '*left_iter': it
|
||||
// must be removed or truncated by the code below
|
||||
else
|
||||
{
|
||||
iter = left_iter;
|
||||
}
|
||||
}
|
||||
|
||||
// remove or truncate subsequent ranges that overlap with 'range':
|
||||
auto it = iter;
|
||||
// 1. skip subsequent ranges completely included in 'range'
|
||||
while (it != run_.end() && it->last <= range.last)
|
||||
{
|
||||
++it;
|
||||
}
|
||||
// 2. clip left of next range if overlapping with 'range'
|
||||
if (it != run_.end() && it->first <= range.last)
|
||||
{
|
||||
it->first = range.last+1;
|
||||
}
|
||||
|
||||
// erase all ranges that 'range' contained
|
||||
run_.erase(iter, it);
|
||||
}
|
||||
|
||||
constexpr void clear() noexcept
|
||||
{
|
||||
run_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
storage_type run_;
|
||||
};
|
||||
} // boost::spirit::x3::detail
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -10,33 +9,27 @@
|
||||
|
||||
#include <boost/spirit/home/x3/char/char_parser.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/utf8.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Encoding, typename Attribute = typename Encoding::char_type>
|
||||
struct literal_char : char_parser<literal_char<Encoding, Attribute>>
|
||||
{
|
||||
using char_type = typename Encoding::char_type;
|
||||
using encoding = Encoding;
|
||||
using attribute_type = Attribute;
|
||||
static constexpr bool has_attribute = !std::is_same_v<unused_type, attribute_type>;
|
||||
typedef typename Encoding::char_type char_type;
|
||||
typedef Encoding encoding;
|
||||
typedef Attribute attribute_type;
|
||||
static bool const has_attribute =
|
||||
!is_same<unused_type, attribute_type>::value;
|
||||
|
||||
template <typename Char>
|
||||
requires std::convertible_to<Char, char_type>
|
||||
constexpr literal_char(Char ch) noexcept
|
||||
: ch(static_cast<char_type>(ch))
|
||||
{
|
||||
static_assert(std::same_as<char_type, Char>, "Mixing incompatible character types is not allowed");
|
||||
}
|
||||
constexpr literal_char(Char ch)
|
||||
: ch(static_cast<char_type>(ch)) {}
|
||||
|
||||
template <typename Char, typename Context>
|
||||
[[nodiscard]] constexpr bool test(Char ch_, Context const& context) const noexcept
|
||||
bool test(Char ch_, Context const& context) const
|
||||
{
|
||||
static_assert(std::same_as<char_type, Char>, "Mixing incompatible character types is not allowed");
|
||||
return x3::get_case_compare<encoding>(context)(ch, char_type(ch_)) == 0;
|
||||
return get_case_compare<encoding>(context)(ch, char_type(ch_)) == 0;
|
||||
}
|
||||
|
||||
char_type ch;
|
||||
@@ -45,12 +38,12 @@ namespace boost::spirit::x3
|
||||
template <typename Encoding, typename Attribute>
|
||||
struct get_info<literal_char<Encoding, Attribute>>
|
||||
{
|
||||
using result_type = std::string;
|
||||
[[nodiscard]] std::string operator()(literal_char<Encoding, Attribute> const& p) const
|
||||
typedef std::string result_type;
|
||||
std::string operator()(literal_char<Encoding, Attribute> const& p) const
|
||||
{
|
||||
return '\'' + x3::to_utf8(Encoding::toucs4(p.ch)) + '\'';
|
||||
return '\'' + to_utf8(Encoding::toucs4(p.ch)) + '\'';
|
||||
}
|
||||
};
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -9,12 +8,15 @@
|
||||
#define BOOST_SPIRIT_X3_UNICODE_JAN_20_2012_1218AM
|
||||
|
||||
#include <boost/spirit/home/x3/char/char_parser.hpp>
|
||||
#include <boost/spirit/home/x3/char/char.hpp>
|
||||
#include <boost/spirit/home/x3/char/detail/cast_char.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/unicode.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/unicode.hpp>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct char_tag;
|
||||
struct alnum_tag;
|
||||
struct alpha_tag;
|
||||
@@ -29,7 +31,9 @@ namespace boost::spirit::x3
|
||||
struct lower_tag;
|
||||
struct upper_tag;
|
||||
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct letter_tag {};
|
||||
struct mark_tag {};
|
||||
struct number_tag {};
|
||||
@@ -38,7 +42,9 @@ namespace boost::spirit::x3
|
||||
struct punctuation_tag {};
|
||||
struct symbol_tag {};
|
||||
|
||||
// Unicode General Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode General Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct uppercase_letter_tag {};
|
||||
struct lowercase_letter_tag {};
|
||||
struct titlecase_letter_tag {};
|
||||
@@ -76,7 +82,9 @@ namespace boost::spirit::x3
|
||||
struct modifier_symbol_tag {};
|
||||
struct other_symbol_tag {};
|
||||
|
||||
// Unicode Derived Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Derived Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct alphabetic_tag {};
|
||||
struct uppercase_tag {};
|
||||
struct lowercase_tag {};
|
||||
@@ -85,7 +93,9 @@ namespace boost::spirit::x3
|
||||
struct noncharacter_code_point_tag {};
|
||||
struct default_ignorable_code_point_tag {};
|
||||
|
||||
// Unicode Scripts
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Scripts
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct adlam_tag {};
|
||||
struct caucasian_albanian_tag {};
|
||||
struct ahom_tag {};
|
||||
@@ -252,10 +262,11 @@ namespace boost::spirit::x3
|
||||
struct common_tag {};
|
||||
struct unknown_tag {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct unicode_char_class_base
|
||||
{
|
||||
using encoding = char_encoding::unicode;
|
||||
using char_type = char_encoding::unicode::char_type;
|
||||
typedef char_encoding::unicode encoding;
|
||||
typedef char_encoding::unicode::char_type char_type;
|
||||
|
||||
#define BOOST_SPIRIT_X3_BASIC_CLASSIFY(name) \
|
||||
template <typename Char> \
|
||||
@@ -280,7 +291,9 @@ namespace boost::spirit::x3
|
||||
/***/
|
||||
|
||||
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
BOOST_SPIRIT_X3_BASIC_CLASSIFY(char)
|
||||
BOOST_SPIRIT_X3_BASIC_CLASSIFY(alnum)
|
||||
BOOST_SPIRIT_X3_BASIC_CLASSIFY(alpha)
|
||||
@@ -295,7 +308,9 @@ namespace boost::spirit::x3
|
||||
BOOST_SPIRIT_X3_BASIC_CLASSIFY(blank)
|
||||
BOOST_SPIRIT_X3_BASIC_CLASSIFY(upper)
|
||||
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
BOOST_SPIRIT_X3_CLASSIFY(letter)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(mark)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(number)
|
||||
@@ -304,7 +319,9 @@ namespace boost::spirit::x3
|
||||
BOOST_SPIRIT_X3_CLASSIFY(punctuation)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(symbol)
|
||||
|
||||
// Unicode General Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode General Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
BOOST_SPIRIT_X3_CLASSIFY(uppercase_letter)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(lowercase_letter)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(titlecase_letter)
|
||||
@@ -342,7 +359,9 @@ namespace boost::spirit::x3
|
||||
BOOST_SPIRIT_X3_CLASSIFY(modifier_symbol)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(other_symbol)
|
||||
|
||||
// Unicode Derived Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Derived Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
BOOST_SPIRIT_X3_CLASSIFY(alphabetic)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(uppercase)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(lowercase)
|
||||
@@ -351,7 +370,9 @@ namespace boost::spirit::x3
|
||||
BOOST_SPIRIT_X3_CLASSIFY(noncharacter_code_point)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(default_ignorable_code_point)
|
||||
|
||||
// Unicode Scripts
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Scripts
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
BOOST_SPIRIT_X3_CLASSIFY(adlam)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(caucasian_albanian)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(ahom)
|
||||
@@ -524,28 +545,34 @@ namespace boost::spirit::x3
|
||||
|
||||
template <typename Tag>
|
||||
struct unicode_char_class
|
||||
: char_parser<unicode_char_class<Tag>>
|
||||
: char_parser<unicode_char_class<Tag>>
|
||||
{
|
||||
using encoding = char_encoding::unicode;
|
||||
using tag = Tag;
|
||||
using char_type = typename encoding::char_type;
|
||||
using attribute_type = char_type;
|
||||
static constexpr bool has_attribute = true;
|
||||
typedef char_encoding::unicode encoding;
|
||||
typedef Tag tag;
|
||||
typedef typename encoding::char_type char_type;
|
||||
typedef char_type attribute_type;
|
||||
static bool const has_attribute = true;
|
||||
|
||||
template <typename Char, typename Context>
|
||||
[[nodiscard]] constexpr bool test(Char ch, Context const&) const noexcept
|
||||
bool test(Char ch, Context const&) const
|
||||
{
|
||||
return encoding::ischar(ch) && unicode_char_class_base::is(tag{}, ch);
|
||||
return encoding::ischar(ch) && unicode_char_class_base::is(tag(), ch);
|
||||
}
|
||||
};
|
||||
|
||||
#define BOOST_SPIRIT_X3_CHAR_CLASS(name) \
|
||||
using name##_type = unicode_char_class<name##_tag>; \
|
||||
inline constexpr name##_type name{};
|
||||
typedef unicode_char_class<name##_tag> name##_type; \
|
||||
constexpr name##_type name = name##_type(); \
|
||||
/***/
|
||||
|
||||
namespace unicode
|
||||
{
|
||||
// Unicode Major Categories
|
||||
typedef any_char<char_encoding::unicode> char_type;
|
||||
constexpr auto char_ = char_type{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(alnum)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(alpha)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(digit)
|
||||
@@ -559,7 +586,9 @@ namespace boost::spirit::x3
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(blank)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(upper)
|
||||
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(letter)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(mark)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(number)
|
||||
@@ -568,7 +597,9 @@ namespace boost::spirit::x3
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(punctuation)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(symbol)
|
||||
|
||||
// Unicode General Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode General Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(uppercase_letter)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(lowercase_letter)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(titlecase_letter)
|
||||
@@ -606,7 +637,9 @@ namespace boost::spirit::x3
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(modifier_symbol)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(other_symbol)
|
||||
|
||||
// Unicode Derived Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Derived Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(alphabetic)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(uppercase)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(lowercase)
|
||||
@@ -615,7 +648,9 @@ namespace boost::spirit::x3
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(noncharacter_code_point)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(default_ignorable_code_point)
|
||||
|
||||
// Unicode Scripts
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Scripts
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(adlam)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(caucasian_albanian)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(ahom)
|
||||
@@ -785,6 +820,6 @@ namespace boost::spirit::x3
|
||||
|
||||
#undef BOOST_SPIRIT_X3_CHAR_CLASS
|
||||
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,342 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CHAR_ENCODING_ASCII_HPP
|
||||
#define BOOST_SPIRIT_X3_CHAR_ENCODING_ASCII_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/char_encoding/detail/encoding_warning.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
|
||||
// constants used to classify the single characters
|
||||
#define BOOST_SPIRIT_X3_CC_DIGIT 0x0001
|
||||
#define BOOST_SPIRIT_X3_CC_XDIGIT 0x0002
|
||||
#define BOOST_SPIRIT_X3_CC_ALPHA 0x0004
|
||||
#define BOOST_SPIRIT_X3_CC_CTRL 0x0008
|
||||
#define BOOST_SPIRIT_X3_CC_LOWER 0x0010
|
||||
#define BOOST_SPIRIT_X3_CC_UPPER 0x0020
|
||||
#define BOOST_SPIRIT_X3_CC_SPACE 0x0040
|
||||
#define BOOST_SPIRIT_X3_CC_PUNCT 0x0080
|
||||
|
||||
namespace boost::spirit::x3::char_encoding
|
||||
{
|
||||
// The detection of isgraph(), isprint() and isblank() is done programmatically
|
||||
// to keep the character type table small. Additionally, these functions are
|
||||
// rather seldom used and the programmatic detection is very simple.
|
||||
|
||||
// Test characters for specified conditions (using ASCII)
|
||||
|
||||
struct ascii
|
||||
{
|
||||
using char_type = char;
|
||||
using classify_type = unsigned char;
|
||||
|
||||
// ASCII character classification table
|
||||
inline static constexpr unsigned char ascii_char_types[] =
|
||||
{
|
||||
/* NUL 0 0 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* SOH 1 1 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* STX 2 2 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* ETX 3 3 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* EOT 4 4 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* ENQ 5 5 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* ACK 6 6 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* BEL 7 7 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* BS 8 8 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* HT 9 9 */ BOOST_SPIRIT_X3_CC_CTRL|BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* NL 10 a */ BOOST_SPIRIT_X3_CC_CTRL|BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* VT 11 b */ BOOST_SPIRIT_X3_CC_CTRL|BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* NP 12 c */ BOOST_SPIRIT_X3_CC_CTRL|BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* CR 13 d */ BOOST_SPIRIT_X3_CC_CTRL|BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* SO 14 e */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* SI 15 f */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* DLE 16 10 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* DC1 17 11 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* DC2 18 12 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* DC3 19 13 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* DC4 20 14 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* NAK 21 15 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* SYN 22 16 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* ETB 23 17 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* CAN 24 18 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* EM 25 19 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* SUB 26 1a */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* ESC 27 1b */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* FS 28 1c */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* GS 29 1d */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* RS 30 1e */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* US 31 1f */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* SP 32 20 */ BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* ! 33 21 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* " 34 22 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* # 35 23 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* $ 36 24 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* % 37 25 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* & 38 26 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ' 39 27 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ( 40 28 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ) 41 29 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* * 42 2a */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* + 43 2b */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* , 44 2c */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* - 45 2d */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* . 46 2e */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* / 47 2f */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* 0 48 30 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 1 49 31 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 2 50 32 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 3 51 33 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 4 52 34 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 5 53 35 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 6 54 36 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 7 55 37 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 8 56 38 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 9 57 39 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* : 58 3a */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ; 59 3b */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* < 60 3c */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* = 61 3d */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* > 62 3e */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ? 63 3f */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* @ 64 40 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* A 65 41 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* B 66 42 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* C 67 43 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* D 68 44 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* E 69 45 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* F 70 46 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* G 71 47 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* H 72 48 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* I 73 49 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* J 74 4a */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* K 75 4b */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* L 76 4c */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* M 77 4d */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* N 78 4e */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* O 79 4f */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* P 80 50 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* Q 81 51 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* R 82 52 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* S 83 53 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* T 84 54 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* U 85 55 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* V 86 56 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* W 87 57 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* X 88 58 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* Y 89 59 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* Z 90 5a */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* [ 91 5b */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* \ 92 5c */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ] 93 5d */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ^ 94 5e */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* _ 95 5f */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ` 96 60 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* a 97 61 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* b 98 62 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* c 99 63 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* d 100 64 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* e 101 65 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* f 102 66 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* g 103 67 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* h 104 68 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* i 105 69 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* j 106 6a */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* k 107 6b */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* l 108 6c */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* m 109 6d */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* n 110 6e */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* o 111 6f */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* p 112 70 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* q 113 71 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* r 114 72 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* s 115 73 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* t 116 74 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* u 117 75 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* v 118 76 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* w 119 77 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* x 120 78 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* y 121 79 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* z 122 7a */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* { 123 7b */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* | 124 7c */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* } 125 7d */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ~ 126 7e */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* DEL 127 7f */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static bool
|
||||
isascii_(int ch)
|
||||
{
|
||||
return 0 == (ch & ~0x7f);
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
ischar(int ch)
|
||||
{
|
||||
return isascii_(ch);
|
||||
}
|
||||
|
||||
// *** Note on assertions: The precondition is that the calls to
|
||||
// these functions do not violate the required range of ch (type int)
|
||||
// which is that strict_ischar(ch) should be true. It is the
|
||||
// responsibility of the caller to make sure this precondition is not
|
||||
// violated.
|
||||
|
||||
static bool
|
||||
strict_ischar(int ch)
|
||||
{
|
||||
return ch >= 0 && ch <= 127;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isalnum(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return (ascii_char_types[ch] & BOOST_SPIRIT_X3_CC_ALPHA)
|
||||
|| (ascii_char_types[ch] & BOOST_SPIRIT_X3_CC_DIGIT);
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isalpha(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return (ascii_char_types[ch] & BOOST_SPIRIT_X3_CC_ALPHA) ? true : false;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isdigit(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return (ascii_char_types[ch] & BOOST_SPIRIT_X3_CC_DIGIT) ? true : false;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isxdigit(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return (ascii_char_types[ch] & BOOST_SPIRIT_X3_CC_XDIGIT) ? true : false;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
iscntrl(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return (ascii_char_types[ch] & BOOST_SPIRIT_X3_CC_CTRL) ? true : false;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isgraph(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return ('\x21' <= ch && ch <= '\x7e');
|
||||
}
|
||||
|
||||
static bool
|
||||
islower(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return (ascii_char_types[ch] & BOOST_SPIRIT_X3_CC_LOWER) ? true : false;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isprint(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return ('\x20' <= ch && ch <= '\x7e');
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
ispunct(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return (ascii_char_types[ch] & BOOST_SPIRIT_X3_CC_PUNCT) ? true : false;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isspace(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return (ascii_char_types[ch] & BOOST_SPIRIT_X3_CC_SPACE) ? true : false;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
(isblank)(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return ('\x09' == ch || '\x20' == ch);
|
||||
}
|
||||
|
||||
static bool
|
||||
isupper(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return (ascii_char_types[ch] & BOOST_SPIRIT_X3_CC_UPPER) ? true : false;
|
||||
}
|
||||
|
||||
// Simple character conversions
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static int
|
||||
tolower(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return isupper(ch) ? (ch - 'A' + 'a') : ch;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static int
|
||||
toupper(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return islower(ch) ? (ch - 'a' + 'A') : ch;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static std::uint32_t
|
||||
toucs4(int ch)
|
||||
{
|
||||
BOOST_ASSERT(strict_ischar(ch));
|
||||
return ch;
|
||||
}
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::char_encoding
|
||||
|
||||
// undefine macros
|
||||
#undef BOOST_SPIRIT_X3_CC_DIGIT
|
||||
#undef BOOST_SPIRIT_X3_CC_XDIGIT
|
||||
#undef BOOST_SPIRIT_X3_CC_ALPHA
|
||||
#undef BOOST_SPIRIT_X3_CC_CTRL
|
||||
#undef BOOST_SPIRIT_X3_CC_LOWER
|
||||
#undef BOOST_SPIRIT_X3_CC_UPPER
|
||||
#undef BOOST_SPIRIT_X3_CC_PUNCT
|
||||
#undef BOOST_SPIRIT_X3_CC_SPACE
|
||||
|
||||
#endif
|
||||
@@ -1,21 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_CHAR_ENCODING_DETAIL_ENCODING_WARNING_HPP
|
||||
#define BOOST_SPIRIT_X3_CHAR_ENCODING_DETAIL_ENCODING_WARNING_HPP
|
||||
|
||||
#define BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING \
|
||||
"Hard-coding ASCII or Latin-1 assumptions is almost always wrong " \
|
||||
"in modern applications and can introduce security vulnerabilities. " \
|
||||
"Unless the input is provably ASCII-only (e.g., fixed-format data from " \
|
||||
"the 1980s), the only correct interpretation uses the data's *original* " \
|
||||
"encoding. Prefer transcoding to Unicode or to the implementation-defined " \
|
||||
"execution character set before passing text to general-purpose parsers. " \
|
||||
"For more information, refer to authoritative sources on C++ character " \
|
||||
"encodings and Unicode fundamentals."
|
||||
|
||||
#endif
|
||||
@@ -1,734 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CHAR_ENCODING_ISO8859_1_HPP
|
||||
#define BOOST_SPIRIT_X3_CHAR_ENCODING_ISO8859_1_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/char_encoding/detail/encoding_warning.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
|
||||
// constants used to classify the single characters
|
||||
#define BOOST_SPIRIT_X3_CC_DIGIT 0x0001
|
||||
#define BOOST_SPIRIT_X3_CC_XDIGIT 0x0002
|
||||
#define BOOST_SPIRIT_X3_CC_ALPHA 0x0004
|
||||
#define BOOST_SPIRIT_X3_CC_CTRL 0x0008
|
||||
#define BOOST_SPIRIT_X3_CC_LOWER 0x0010
|
||||
#define BOOST_SPIRIT_X3_CC_UPPER 0x0020
|
||||
#define BOOST_SPIRIT_X3_CC_SPACE 0x0040
|
||||
#define BOOST_SPIRIT_X3_CC_PUNCT 0x0080
|
||||
|
||||
namespace boost::spirit::x3::char_encoding
|
||||
{
|
||||
// Test characters for specified conditions (using iso8859-1)
|
||||
|
||||
struct iso8859_1
|
||||
{
|
||||
using char_type = char;
|
||||
using classify_type = char;
|
||||
|
||||
private:
|
||||
// The detection of isgraph(), isprint() and isblank() is done programmatically
|
||||
// to keep the character type table small. Additionally, these functions are
|
||||
// rather seldom used and the programmatic detection is very simple.
|
||||
|
||||
// ISO 8859-1 character classification table
|
||||
//
|
||||
// the comments intentionally contain non-ascii characters
|
||||
// boostinspect:noascii
|
||||
inline static constexpr unsigned char iso8859_1_char_types[] =
|
||||
{
|
||||
/* NUL 0 0 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* SOH 1 1 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* STX 2 2 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* ETX 3 3 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* EOT 4 4 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* ENQ 5 5 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* ACK 6 6 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* BEL 7 7 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* BS 8 8 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* HT 9 9 */ BOOST_SPIRIT_X3_CC_CTRL|BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* NL 10 a */ BOOST_SPIRIT_X3_CC_CTRL|BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* VT 11 b */ BOOST_SPIRIT_X3_CC_CTRL|BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* NP 12 c */ BOOST_SPIRIT_X3_CC_CTRL|BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* CR 13 d */ BOOST_SPIRIT_X3_CC_CTRL|BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* SO 14 e */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* SI 15 f */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* DLE 16 10 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* DC1 17 11 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* DC2 18 12 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* DC3 19 13 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* DC4 20 14 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* NAK 21 15 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* SYN 22 16 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* ETB 23 17 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* CAN 24 18 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* EM 25 19 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* SUB 26 1a */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* ESC 27 1b */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* FS 28 1c */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* GS 29 1d */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* RS 30 1e */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* US 31 1f */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* SP 32 20 */ BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* ! 33 21 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* " 34 22 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* # 35 23 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* $ 36 24 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* % 37 25 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* & 38 26 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ' 39 27 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ( 40 28 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ) 41 29 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* * 42 2a */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* + 43 2b */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* , 44 2c */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* - 45 2d */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* . 46 2e */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* / 47 2f */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* 0 48 30 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 1 49 31 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 2 50 32 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 3 51 33 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 4 52 34 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 5 53 35 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 6 54 36 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 7 55 37 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 8 56 38 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* 9 57 39 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_XDIGIT,
|
||||
/* : 58 3a */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ; 59 3b */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* < 60 3c */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* = 61 3d */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* > 62 3e */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ? 63 3f */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* @ 64 40 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* A 65 41 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* B 66 42 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* C 67 43 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* D 68 44 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* E 69 45 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* F 70 46 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* G 71 47 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* H 72 48 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* I 73 49 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* J 74 4a */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* K 75 4b */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* L 76 4c */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* M 77 4d */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* N 78 4e */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* O 79 4f */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* P 80 50 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* Q 81 51 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* R 82 52 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* S 83 53 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* T 84 54 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* U 85 55 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* V 86 56 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* W 87 57 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* X 88 58 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* Y 89 59 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* Z 90 5a */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* [ 91 5b */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* \ 92 5c */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ] 93 5d */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ^ 94 5e */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* _ 95 5f */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ` 96 60 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* a 97 61 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* b 98 62 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* c 99 63 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* d 100 64 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* e 101 65 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* f 102 66 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_XDIGIT|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* g 103 67 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* h 104 68 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* i 105 69 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* j 106 6a */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* k 107 6b */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* l 108 6c */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* m 109 6d */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* n 110 6e */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* o 111 6f */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* p 112 70 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* q 113 71 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* r 114 72 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* s 115 73 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* t 116 74 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* u 117 75 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* v 118 76 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* w 119 77 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* x 120 78 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* y 121 79 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* z 122 7a */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* { 123 7b */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* | 124 7c */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* } 125 7d */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* ~ 126 7e */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* DEL 127 7f */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 128 80 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 129 81 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 130 82 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 131 83 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 132 84 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 133 85 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 134 86 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 135 87 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 136 88 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 137 89 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 138 8a */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 139 8b */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 140 8c */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 141 8d */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 142 8e */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 143 8f */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 144 90 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 145 91 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 146 92 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 147 93 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 148 94 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 149 95 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 150 96 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 151 97 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 152 98 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 153 99 */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 154 9a */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 155 9b */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 156 9c */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 157 9d */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 158 9e */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* -- 159 9f */ BOOST_SPIRIT_X3_CC_CTRL,
|
||||
/* 160 a0 */ BOOST_SPIRIT_X3_CC_SPACE,
|
||||
/* <20> 161 a1 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 162 a2 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 163 a3 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 164 a4 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 165 a5 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 166 a6 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 167 a7 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 168 a8 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 169 a9 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 170 aa */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 171 ab */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 172 ac */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 173 ad */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 174 ae */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 175 af */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 176 b0 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 177 b1 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 178 b2 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 179 b3 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 180 b4 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 181 b5 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 182 b6 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 183 b7 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 184 b8 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 185 b9 */ BOOST_SPIRIT_X3_CC_DIGIT|BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 186 ba */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 187 bb */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 188 bc */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 189 bd */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 190 be */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 191 bf */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 192 c0 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 193 c1 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 194 c2 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 195 c3 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 196 c4 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 197 c5 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 198 c6 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 199 c7 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 200 c8 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 201 c9 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 202 ca */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 203 cb */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 204 cc */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 205 cd */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 206 ce */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 207 cf */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 208 d0 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 209 d1 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 210 d2 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 211 d3 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 212 d4 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 213 d5 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 214 d6 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 215 d7 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 216 d8 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 217 d9 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 218 da */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 219 db */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 220 dc */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 221 dd */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 222 de */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_UPPER,
|
||||
/* <20> 223 df */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 224 e0 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 225 e1 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 226 e2 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 227 e3 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 228 e4 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 229 e5 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 230 e6 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 231 e7 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 232 e8 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 233 e9 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 234 ea */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 235 eb */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 236 ec */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 237 ed */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 238 ee */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 239 ef */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 240 f0 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 241 f1 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 242 f2 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 243 f3 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 244 f4 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 245 f5 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 246 f6 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 247 f7 */ BOOST_SPIRIT_X3_CC_PUNCT,
|
||||
/* <20> 248 f8 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 249 f9 */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 250 fa */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 251 fb */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 252 fc */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 253 fd */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 254 fe */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
/* <20> 255 ff */ BOOST_SPIRIT_X3_CC_ALPHA|BOOST_SPIRIT_X3_CC_LOWER,
|
||||
};
|
||||
|
||||
// ISO 8859-1 character conversion table
|
||||
inline static constexpr unsigned char iso8859_1_char_conversion[] =
|
||||
{
|
||||
/* NUL 0 0 */ '\0',
|
||||
/* SOH 1 1 */ '\0',
|
||||
/* STX 2 2 */ '\0',
|
||||
/* ETX 3 3 */ '\0',
|
||||
/* EOT 4 4 */ '\0',
|
||||
/* ENQ 5 5 */ '\0',
|
||||
/* ACK 6 6 */ '\0',
|
||||
/* BEL 7 7 */ '\0',
|
||||
/* BS 8 8 */ '\0',
|
||||
/* HT 9 9 */ '\0',
|
||||
/* NL 10 a */ '\0',
|
||||
/* VT 11 b */ '\0',
|
||||
/* NP 12 c */ '\0',
|
||||
/* CR 13 d */ '\0',
|
||||
/* SO 14 e */ '\0',
|
||||
/* SI 15 f */ '\0',
|
||||
/* DLE 16 10 */ '\0',
|
||||
/* DC1 17 11 */ '\0',
|
||||
/* DC2 18 12 */ '\0',
|
||||
/* DC3 19 13 */ '\0',
|
||||
/* DC4 20 14 */ '\0',
|
||||
/* NAK 21 15 */ '\0',
|
||||
/* SYN 22 16 */ '\0',
|
||||
/* ETB 23 17 */ '\0',
|
||||
/* CAN 24 18 */ '\0',
|
||||
/* EM 25 19 */ '\0',
|
||||
/* SUB 26 1a */ '\0',
|
||||
/* ESC 27 1b */ '\0',
|
||||
/* FS 28 1c */ '\0',
|
||||
/* GS 29 1d */ '\0',
|
||||
/* RS 30 1e */ '\0',
|
||||
/* US 31 1f */ '\0',
|
||||
/* SP 32 20 */ '\0',
|
||||
/* ! 33 21 */ '\0',
|
||||
/* " 34 22 */ '\0',
|
||||
/* # 35 23 */ '\0',
|
||||
/* $ 36 24 */ '\0',
|
||||
/* % 37 25 */ '\0',
|
||||
/* & 38 26 */ '\0',
|
||||
/* ' 39 27 */ '\0',
|
||||
/* ( 40 28 */ '\0',
|
||||
/* ) 41 29 */ '\0',
|
||||
/* * 42 2a */ '\0',
|
||||
/* + 43 2b */ '\0',
|
||||
/* , 44 2c */ '\0',
|
||||
/* - 45 2d */ '\0',
|
||||
/* . 46 2e */ '\0',
|
||||
/* / 47 2f */ '\0',
|
||||
/* 0 48 30 */ '\0',
|
||||
/* 1 49 31 */ '\0',
|
||||
/* 2 50 32 */ '\0',
|
||||
/* 3 51 33 */ '\0',
|
||||
/* 4 52 34 */ '\0',
|
||||
/* 5 53 35 */ '\0',
|
||||
/* 6 54 36 */ '\0',
|
||||
/* 7 55 37 */ '\0',
|
||||
/* 8 56 38 */ '\0',
|
||||
/* 9 57 39 */ '\0',
|
||||
/* : 58 3a */ '\0',
|
||||
/* ; 59 3b */ '\0',
|
||||
/* < 60 3c */ '\0',
|
||||
/* = 61 3d */ '\0',
|
||||
/* > 62 3e */ '\0',
|
||||
/* ? 63 3f */ '\0',
|
||||
/* @ 64 40 */ '\0',
|
||||
/* A 65 41 */ 'a',
|
||||
/* B 66 42 */ 'b',
|
||||
/* C 67 43 */ 'c',
|
||||
/* D 68 44 */ 'd',
|
||||
/* E 69 45 */ 'e',
|
||||
/* F 70 46 */ 'f',
|
||||
/* G 71 47 */ 'g',
|
||||
/* H 72 48 */ 'h',
|
||||
/* I 73 49 */ 'i',
|
||||
/* J 74 4a */ 'j',
|
||||
/* K 75 4b */ 'k',
|
||||
/* L 76 4c */ 'l',
|
||||
/* M 77 4d */ 'm',
|
||||
/* N 78 4e */ 'n',
|
||||
/* O 79 4f */ 'o',
|
||||
/* P 80 50 */ 'p',
|
||||
/* Q 81 51 */ 'q',
|
||||
/* R 82 52 */ 'r',
|
||||
/* S 83 53 */ 's',
|
||||
/* T 84 54 */ 't',
|
||||
/* U 85 55 */ 'u',
|
||||
/* V 86 56 */ 'v',
|
||||
/* W 87 57 */ 'w',
|
||||
/* X 88 58 */ 'x',
|
||||
/* Y 89 59 */ 'y',
|
||||
/* Z 90 5a */ 'z',
|
||||
/* [ 91 5b */ '\0',
|
||||
/* \ 92 5c */ '\0',
|
||||
/* ] 93 5d */ '\0',
|
||||
/* ^ 94 5e */ '\0',
|
||||
/* _ 95 5f */ '\0',
|
||||
/* ` 96 60 */ '\0',
|
||||
/* a 97 61 */ 'A',
|
||||
/* b 98 62 */ 'B',
|
||||
/* c 99 63 */ 'C',
|
||||
/* d 100 64 */ 'D',
|
||||
/* e 101 65 */ 'E',
|
||||
/* f 102 66 */ 'F',
|
||||
/* g 103 67 */ 'G',
|
||||
/* h 104 68 */ 'H',
|
||||
/* i 105 69 */ 'I',
|
||||
/* j 106 6a */ 'J',
|
||||
/* k 107 6b */ 'K',
|
||||
/* l 108 6c */ 'L',
|
||||
/* m 109 6d */ 'M',
|
||||
/* n 110 6e */ 'N',
|
||||
/* o 111 6f */ 'O',
|
||||
/* p 112 70 */ 'P',
|
||||
/* q 113 71 */ 'Q',
|
||||
/* r 114 72 */ 'R',
|
||||
/* s 115 73 */ 'S',
|
||||
/* t 116 74 */ 'T',
|
||||
/* u 117 75 */ 'U',
|
||||
/* v 118 76 */ 'V',
|
||||
/* w 119 77 */ 'W',
|
||||
/* x 120 78 */ 'X',
|
||||
/* y 121 79 */ 'Y',
|
||||
/* z 122 7a */ 'Z',
|
||||
/* { 123 7b */ '\0',
|
||||
/* | 124 7c */ '\0',
|
||||
/* } 125 7d */ '\0',
|
||||
/* ~ 126 7e */ '\0',
|
||||
/* DEL 127 7f */ '\0',
|
||||
/* -- 128 80 */ '\0',
|
||||
/* -- 129 81 */ '\0',
|
||||
/* -- 130 82 */ '\0',
|
||||
/* -- 131 83 */ '\0',
|
||||
/* -- 132 84 */ '\0',
|
||||
/* -- 133 85 */ '\0',
|
||||
/* -- 134 86 */ '\0',
|
||||
/* -- 135 87 */ '\0',
|
||||
/* -- 136 88 */ '\0',
|
||||
/* -- 137 89 */ '\0',
|
||||
/* -- 138 8a */ '\0',
|
||||
/* -- 139 8b */ '\0',
|
||||
/* -- 140 8c */ '\0',
|
||||
/* -- 141 8d */ '\0',
|
||||
/* -- 142 8e */ '\0',
|
||||
/* -- 143 8f */ '\0',
|
||||
/* -- 144 90 */ '\0',
|
||||
/* -- 145 91 */ '\0',
|
||||
/* -- 146 92 */ '\0',
|
||||
/* -- 147 93 */ '\0',
|
||||
/* -- 148 94 */ '\0',
|
||||
/* -- 149 95 */ '\0',
|
||||
/* -- 150 96 */ '\0',
|
||||
/* -- 151 97 */ '\0',
|
||||
/* -- 152 98 */ '\0',
|
||||
/* -- 153 99 */ '\0',
|
||||
/* -- 154 9a */ '\0',
|
||||
/* -- 155 9b */ '\0',
|
||||
/* -- 156 9c */ '\0',
|
||||
/* -- 157 9d */ '\0',
|
||||
/* -- 158 9e */ '\0',
|
||||
/* -- 159 9f */ '\0',
|
||||
/* 160 a0 */ '\0',
|
||||
/* <20> 161 a1 */ '\0',
|
||||
/* <20> 162 a2 */ '\0',
|
||||
/* <20> 163 a3 */ '\0',
|
||||
/* <20> 164 a4 */ '\0',
|
||||
/* <20> 165 a5 */ '\0',
|
||||
/* <20> 166 a6 */ '\0',
|
||||
/* <20> 167 a7 */ '\0',
|
||||
/* <20> 168 a8 */ '\0',
|
||||
/* <20> 169 a9 */ '\0',
|
||||
/* <20> 170 aa */ '\0',
|
||||
/* <20> 171 ab */ '\0',
|
||||
/* <20> 172 ac */ '\0',
|
||||
/* <20> 173 ad */ '\0',
|
||||
/* <20> 174 ae */ '\0',
|
||||
/* <20> 175 af */ '\0',
|
||||
/* <20> 176 b0 */ '\0',
|
||||
/* <20> 177 b1 */ '\0',
|
||||
/* <20> 178 b2 */ '\0',
|
||||
/* <20> 179 b3 */ '\0',
|
||||
/* <20> 180 b4 */ '\0',
|
||||
/* <20> 181 b5 */ '\0',
|
||||
/* <20> 182 b6 */ '\0',
|
||||
/* <20> 183 b7 */ '\0',
|
||||
/* <20> 184 b8 */ '\0',
|
||||
/* <20> 185 b9 */ '\0',
|
||||
/* <20> 186 ba */ '\0',
|
||||
/* <20> 187 bb */ '\0',
|
||||
/* <20> 188 bc */ '\0',
|
||||
/* <20> 189 bd */ '\0',
|
||||
/* <20> 190 be */ '\0',
|
||||
/* <20> 191 bf */ '\0',
|
||||
/* <20> 192 c0 */ 0xe0,
|
||||
/* <20> 193 c1 */ 0xe1,
|
||||
/* <20> 194 c2 */ 0xe2,
|
||||
/* <20> 195 c3 */ 0xe3,
|
||||
/* <20> 196 c4 */ 0xe4,
|
||||
/* <20> 197 c5 */ 0xe5,
|
||||
/* <20> 198 c6 */ 0xe6,
|
||||
/* <20> 199 c7 */ 0xe7,
|
||||
/* <20> 200 c8 */ 0xe8,
|
||||
/* <20> 201 c9 */ 0xe9,
|
||||
/* <20> 202 ca */ 0xea,
|
||||
/* <20> 203 cb */ 0xeb,
|
||||
/* <20> 204 cc */ 0xec,
|
||||
/* <20> 205 cd */ 0xed,
|
||||
/* <20> 206 ce */ 0xee,
|
||||
/* <20> 207 cf */ 0xef,
|
||||
/* <20> 208 d0 */ 0xf0,
|
||||
/* <20> 209 d1 */ 0xf1,
|
||||
/* <20> 210 d2 */ 0xf2,
|
||||
/* <20> 211 d3 */ 0xf3,
|
||||
/* <20> 212 d4 */ 0xf4,
|
||||
/* <20> 213 d5 */ 0xf5,
|
||||
/* <20> 214 d6 */ 0xf6,
|
||||
/* <20> 215 d7 */ '\0',
|
||||
/* <20> 216 d8 */ 0xf8,
|
||||
/* <20> 217 d9 */ 0xf9,
|
||||
/* <20> 218 da */ 0xfa,
|
||||
/* <20> 219 db */ 0xfb,
|
||||
/* <20> 220 dc */ 0xfc,
|
||||
/* <20> 221 dd */ 0xfd,
|
||||
/* <20> 222 de */ 0xfe,
|
||||
/* <20> 223 df */ '\0',
|
||||
/* <20> 224 e0 */ 0xc0,
|
||||
/* <20> 225 e1 */ 0xc1,
|
||||
/* <20> 226 e2 */ 0xc2,
|
||||
/* <20> 227 e3 */ 0xc3,
|
||||
/* <20> 228 e4 */ 0xc4,
|
||||
/* <20> 229 e5 */ 0xc5,
|
||||
/* <20> 230 e6 */ 0xc6,
|
||||
/* <20> 231 e7 */ 0xc7,
|
||||
/* <20> 232 e8 */ 0xc8,
|
||||
/* <20> 233 e9 */ 0xc9,
|
||||
/* <20> 234 ea */ 0xca,
|
||||
/* <20> 235 eb */ 0xcb,
|
||||
/* <20> 236 ec */ 0xcc,
|
||||
/* <20> 237 ed */ 0xcd,
|
||||
/* <20> 238 ee */ 0xce,
|
||||
/* <20> 239 ef */ 0xcf,
|
||||
/* <20> 240 f0 */ 0xd0,
|
||||
/* <20> 241 f1 */ 0xd1,
|
||||
/* <20> 242 f2 */ 0xd2,
|
||||
/* <20> 243 f3 */ 0xd3,
|
||||
/* <20> 244 f4 */ 0xd4,
|
||||
/* <20> 245 f5 */ 0xd5,
|
||||
/* <20> 246 f6 */ 0xd6,
|
||||
/* <20> 247 f7 */ '\0',
|
||||
/* <20> 248 f8 */ 0xd8,
|
||||
/* <20> 249 f9 */ 0xd9,
|
||||
/* <20> 250 fa */ 0xda,
|
||||
/* <20> 251 fb */ 0xdb,
|
||||
/* <20> 252 fc */ 0xdc,
|
||||
/* <20> 253 fd */ 0xdd,
|
||||
/* <20> 254 fe */ 0xde,
|
||||
/* <20> 255 ff */ '\0',
|
||||
};
|
||||
|
||||
public:
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isascii_(int ch)
|
||||
{
|
||||
return 0 == (ch & ~0x7f);
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
ischar(int ch)
|
||||
{
|
||||
// iso8859.1 uses all 8 bits
|
||||
// we have to watch out for sign extensions
|
||||
return (0 == (ch & ~0xff) || ~0 == (ch | 0xff)) != 0;
|
||||
}
|
||||
|
||||
// *** Note on assertions: The precondition is that the calls to
|
||||
// these functions do not violate the required range of ch (type int)
|
||||
// which is that strict_ischar(ch) should be true. It is the
|
||||
// responsibility of the caller to make sure this precondition is not
|
||||
// violated.
|
||||
|
||||
static bool
|
||||
strict_ischar(int ch)
|
||||
{
|
||||
return ch >= 0 && ch <= 255;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isalnum(int ch)
|
||||
{
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return (iso8859_1_char_types[ch] & BOOST_SPIRIT_X3_CC_ALPHA)
|
||||
|| (iso8859_1_char_types[ch] & BOOST_SPIRIT_X3_CC_DIGIT);
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isalpha(int ch)
|
||||
{
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return (iso8859_1_char_types[ch] & BOOST_SPIRIT_X3_CC_ALPHA) != 0;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isdigit(int ch)
|
||||
{
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return (iso8859_1_char_types[ch] & BOOST_SPIRIT_X3_CC_DIGIT) != 0;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isxdigit(int ch)
|
||||
{
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return (iso8859_1_char_types[ch] & BOOST_SPIRIT_X3_CC_XDIGIT) != 0;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
iscntrl(int ch)
|
||||
{
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return (iso8859_1_char_types[ch] & BOOST_SPIRIT_X3_CC_CTRL) != 0;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isgraph(int ch)
|
||||
{
|
||||
return ('\x21' <= ch && ch <= '\x7e') || ('\xa1' <= ch && ch <= '\xff');
|
||||
}
|
||||
|
||||
static bool
|
||||
islower(int ch)
|
||||
{
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return (iso8859_1_char_types[ch] & BOOST_SPIRIT_X3_CC_LOWER) != 0;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isprint(int ch)
|
||||
{
|
||||
return ('\x20' <= ch && ch <= '\x7e') || ('\xa0' <= ch && ch <= '\xff');
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
ispunct(int ch)
|
||||
{
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return (iso8859_1_char_types[ch] & BOOST_SPIRIT_X3_CC_PUNCT) != 0;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
isspace(int ch)
|
||||
{
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return (iso8859_1_char_types[ch] & BOOST_SPIRIT_X3_CC_SPACE) != 0;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static bool
|
||||
(isblank)(int ch)
|
||||
{
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return ('\x09' == ch || '\x20' == ch || '\xa0' == ch);
|
||||
}
|
||||
|
||||
static bool
|
||||
isupper(int ch)
|
||||
{
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return (iso8859_1_char_types[ch] & BOOST_SPIRIT_X3_CC_UPPER) != 0;
|
||||
}
|
||||
|
||||
// Simple character conversions
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static int
|
||||
tolower(int ch)
|
||||
{
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return iso8859_1::isupper(ch) && '\0' != iso8859_1_char_conversion[ch] ?
|
||||
iso8859_1_char_conversion[ch] : ch;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static int
|
||||
toupper(int ch)
|
||||
{
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return iso8859_1::islower(ch) && '\0' != iso8859_1_char_conversion[ch] ?
|
||||
iso8859_1_char_conversion[ch] : ch;
|
||||
}
|
||||
|
||||
[[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]]
|
||||
static std::uint32_t
|
||||
toucs4(int ch)
|
||||
{
|
||||
// The first 256 characters in Unicode and the UCS are
|
||||
// identical to those in ISO/IEC-8859-1.
|
||||
BOOST_ASSERT(iso8859_1::strict_ischar(ch));
|
||||
return ch;
|
||||
}
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::char_encoding
|
||||
|
||||
// undefine macros
|
||||
#undef BOOST_SPIRIT_X3_CC_DIGIT
|
||||
#undef BOOST_SPIRIT_X3_CC_XDIGIT
|
||||
#undef BOOST_SPIRIT_X3_CC_ALPHA
|
||||
#undef BOOST_SPIRIT_X3_CC_CTRL
|
||||
#undef BOOST_SPIRIT_X3_CC_LOWER
|
||||
#undef BOOST_SPIRIT_X3_CC_UPPER
|
||||
#undef BOOST_SPIRIT_X3_CC_PUNCT
|
||||
#undef BOOST_SPIRIT_X3_CC_SPACE
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CHAR_ENCODING_STANDARD_HPP
|
||||
#define BOOST_SPIRIT_X3_CHAR_ENCODING_STANDARD_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cctype>
|
||||
#include <climits>
|
||||
|
||||
namespace boost::spirit::x3::char_encoding
|
||||
{
|
||||
// Test characters for specified conditions (using std functions)
|
||||
struct standard
|
||||
{
|
||||
using char_type = char;
|
||||
using classify_type = unsigned char;
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
isascii_(int ch) noexcept
|
||||
{
|
||||
return 0 == (ch & ~0x7f);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
ischar(int ch) noexcept
|
||||
{
|
||||
// uses all 8 bits
|
||||
// we have to watch out for sign extensions
|
||||
return (0 == (ch & ~0xff) || ~0 == (ch | 0xff)) != 0;
|
||||
}
|
||||
|
||||
// *** Note on assertions: The precondition is that the calls to
|
||||
// these functions do not violate the required range of ch (int)
|
||||
// which is that strict_ischar(ch) should be true. It is the
|
||||
// responsibility of the caller to make sure this precondition is not
|
||||
// violated.
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
strict_ischar(int ch) noexcept
|
||||
{
|
||||
// ch should be representable as an unsigned char
|
||||
return ch >= 0 && ch <= UCHAR_MAX;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isalnum(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::isalnum(ch) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isalpha(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::isalpha(ch) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isdigit(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::isdigit(ch) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isxdigit(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::isxdigit(ch) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
iscntrl(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::iscntrl(ch) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isgraph(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::isgraph(ch) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
islower(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::islower(ch) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isprint(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::isprint(ch) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
ispunct(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::ispunct(ch) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isspace(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::isspace(ch) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
(isblank)(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return (ch == ' ' || ch == '\t');
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isupper(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::isupper(ch) != 0;
|
||||
}
|
||||
|
||||
// Simple character conversions
|
||||
|
||||
[[nodiscard]] static int // TODO: constexpr
|
||||
tolower(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::tolower(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static int // TODO: constexpr
|
||||
toupper(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return std::toupper(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr std::uint32_t
|
||||
toucs4(int ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(standard::strict_ischar(ch));
|
||||
return static_cast<std::uint32_t>(ch);
|
||||
}
|
||||
};
|
||||
} // boost::spirit::x3::char_encoding
|
||||
|
||||
#endif
|
||||
@@ -1,162 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CHAR_ENCODING_STANDARD_WIDE_HPP
|
||||
#define BOOST_SPIRIT_X3_CHAR_ENCODING_STANDARD_WIDE_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cwctype>
|
||||
|
||||
namespace boost::spirit::x3::char_encoding
|
||||
{
|
||||
// Test characters for specified conditions (using std wchar_t functions)
|
||||
|
||||
struct standard_wide
|
||||
{
|
||||
using char_type = wchar_t;
|
||||
using classify_type = wchar_t;
|
||||
|
||||
template <typename Char>
|
||||
[[nodiscard]] static constexpr typename std::char_traits<Char>::int_type
|
||||
to_int_type(Char ch) noexcept
|
||||
{
|
||||
return std::char_traits<Char>::to_int_type(ch);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
[[nodiscard]] static constexpr Char
|
||||
to_char_type(typename std::char_traits<Char>::int_type ch) noexcept
|
||||
{
|
||||
return std::char_traits<Char>::to_char_type(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
ischar(int ch) noexcept
|
||||
{
|
||||
static_assert(
|
||||
sizeof(wchar_t) == 1 || sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4,
|
||||
"Unsupported wchar_t size"
|
||||
);
|
||||
constexpr unsigned mask =
|
||||
sizeof(wchar_t) == 4 ? 0xffffffffu :
|
||||
sizeof(wchar_t) == 2 ? 0xffffu :
|
||||
0xffu;
|
||||
|
||||
// we have to watch out for sign extensions (casting is there to
|
||||
// silence certain compilers complaining about signed/unsigned
|
||||
// mismatch)
|
||||
return (
|
||||
std::size_t(0) ==
|
||||
std::size_t(ch & ~mask) ||
|
||||
std::size_t(~0) ==
|
||||
std::size_t(ch | mask)
|
||||
) != 0; // any wchar_t, but no other bits set
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isalnum(wchar_t ch) noexcept
|
||||
{
|
||||
return std::iswalnum(standard_wide::to_int_type(ch)) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isalpha(wchar_t ch) noexcept
|
||||
{
|
||||
return std::iswalpha(standard_wide::to_int_type(ch)) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
iscntrl(wchar_t ch) noexcept
|
||||
{
|
||||
return std::iswcntrl(standard_wide::to_int_type(ch)) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isdigit(wchar_t ch) noexcept
|
||||
{
|
||||
return std::iswdigit(standard_wide::to_int_type(ch)) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isgraph(wchar_t ch) noexcept
|
||||
{
|
||||
return std::iswgraph(standard_wide::to_int_type(ch)) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
islower(wchar_t ch) noexcept
|
||||
{
|
||||
return std::iswlower(standard_wide::to_int_type(ch)) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isprint(wchar_t ch) noexcept
|
||||
{
|
||||
return std::iswprint(standard_wide::to_int_type(ch)) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
ispunct(wchar_t ch) noexcept
|
||||
{
|
||||
return std::iswpunct(standard_wide::to_int_type(ch)) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isspace(wchar_t ch) noexcept
|
||||
{
|
||||
return std::iswspace(standard_wide::to_int_type(ch)) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isupper(wchar_t ch) noexcept
|
||||
{
|
||||
return std::iswupper(standard_wide::to_int_type(ch)) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool // TODO: constexpr
|
||||
isxdigit(wchar_t ch) noexcept
|
||||
{
|
||||
return std::iswxdigit(standard_wide::to_int_type(ch)) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
(isblank)(wchar_t ch) noexcept
|
||||
{
|
||||
return (ch == L' ' || ch == L'\t');
|
||||
}
|
||||
|
||||
// Simple character conversions
|
||||
|
||||
[[nodiscard]] static wchar_t // TODO: constexpr
|
||||
tolower(wchar_t ch) noexcept
|
||||
{
|
||||
return standard_wide::isupper(ch) ?
|
||||
standard_wide::to_char_type<wchar_t>(std::towlower(standard_wide::to_int_type(ch))) : ch;
|
||||
}
|
||||
|
||||
[[nodiscard]] static wchar_t // TODO: constexpr
|
||||
toupper(wchar_t ch) noexcept
|
||||
{
|
||||
return std::islower(ch) ?
|
||||
standard_wide::to_char_type<wchar_t>(std::towupper(standard_wide::to_int_type(ch))) : ch;
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr std::uint32_t
|
||||
toucs4(wchar_t ch) noexcept
|
||||
{
|
||||
return static_cast<std::make_unsigned_t<wchar_t>>(ch);
|
||||
}
|
||||
};
|
||||
} // boost::spirit::x3::char_encoding
|
||||
|
||||
#endif
|
||||
@@ -1,435 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CHAR_ENCODING_UNICODE_HPP
|
||||
#define BOOST_SPIRIT_X3_CHAR_ENCODING_UNICODE_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/char_encoding/unicode/classification.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost::spirit::x3::char_encoding
|
||||
{
|
||||
struct unicode
|
||||
{
|
||||
using char_type = char32_t;
|
||||
using classify_type = std::uint32_t;
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
isascii_(char_type ch) noexcept
|
||||
{
|
||||
return 0 == (ch & ~0x7f);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
ischar(char_type ch) noexcept
|
||||
{
|
||||
// unicode code points in the range 0x00 to 0x10FFFF
|
||||
return ch <= 0x10FFFF;
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
isalnum(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::is_alphanumeric(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
isalpha(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::is_alphabetic(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
isdigit(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::is_decimal_number(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
isxdigit(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::is_hex_digit(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
iscntrl(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::is_control(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
isgraph(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::is_graph(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
islower(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::is_lowercase(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
isprint(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::is_print(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
ispunct(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::is_punctuation(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
isspace(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::is_white_space(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
(isblank)(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::is_blank(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool
|
||||
isupper(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::is_uppercase(ch);
|
||||
}
|
||||
|
||||
// Mixing character encodings is semantically wrong
|
||||
static constexpr void isascii_(char) = delete;
|
||||
static constexpr void isascii_(wchar_t) = delete;
|
||||
static constexpr void ischar(char) = delete;
|
||||
static constexpr void ischar(wchar_t) = delete;
|
||||
static constexpr void isalnum(char) = delete;
|
||||
static constexpr void isalnum(wchar_t) = delete;
|
||||
static constexpr void isalpha(char) = delete;
|
||||
static constexpr void isalpha(wchar_t) = delete;
|
||||
static constexpr void isdigit(char) = delete;
|
||||
static constexpr void isdigit(wchar_t) = delete;
|
||||
static constexpr void isxdigit(char) = delete;
|
||||
static constexpr void isxdigit(wchar_t) = delete;
|
||||
static constexpr void iscntrl(char) = delete;
|
||||
static constexpr void iscntrl(wchar_t) = delete;
|
||||
static constexpr void isgraph(char) = delete;
|
||||
static constexpr void isgraph(wchar_t) = delete;
|
||||
static constexpr void islower(char) = delete;
|
||||
static constexpr void islower(wchar_t) = delete;
|
||||
static constexpr void isprint(char) = delete;
|
||||
static constexpr void isprint(wchar_t) = delete;
|
||||
static constexpr void ispunct(char) = delete;
|
||||
static constexpr void ispunct(wchar_t) = delete;
|
||||
static constexpr void isspace(char) = delete;
|
||||
static constexpr void isspace(wchar_t) = delete;
|
||||
static constexpr void isblank(char) = delete;
|
||||
static constexpr void isblank(wchar_t) = delete;
|
||||
static constexpr void isupper(char) = delete;
|
||||
static constexpr void isupper(wchar_t) = delete;
|
||||
|
||||
// Simple character conversions
|
||||
|
||||
[[nodiscard]] static constexpr char_type
|
||||
tolower(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::to_lowercase(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr char_type
|
||||
toupper(char_type ch) noexcept
|
||||
{
|
||||
return x3::unicode::to_uppercase(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr std::uint32_t
|
||||
toucs4(char_type ch) noexcept
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
|
||||
static constexpr void tolower(char) = delete;
|
||||
static constexpr void tolower(wchar_t) = delete;
|
||||
static constexpr void toupper(char) = delete;
|
||||
static constexpr void toupper(wchar_t) = delete;
|
||||
static constexpr void toucs4(char) = delete;
|
||||
static constexpr void toucs4(wchar_t) = delete;
|
||||
|
||||
// Major Categories
|
||||
#define BOOST_SPIRIT_X3_MAJOR_CATEGORY(name) \
|
||||
[[nodiscard]] static constexpr bool \
|
||||
is_##name(char_type ch) noexcept \
|
||||
{ \
|
||||
return x3::unicode::get_major_category(ch) == x3::unicode::properties::name; \
|
||||
} \
|
||||
static constexpr void is_##name(char) = delete; \
|
||||
static constexpr void is_##name(wchar_t) = delete;
|
||||
|
||||
BOOST_SPIRIT_X3_MAJOR_CATEGORY(letter)
|
||||
BOOST_SPIRIT_X3_MAJOR_CATEGORY(mark)
|
||||
BOOST_SPIRIT_X3_MAJOR_CATEGORY(number)
|
||||
BOOST_SPIRIT_X3_MAJOR_CATEGORY(separator)
|
||||
BOOST_SPIRIT_X3_MAJOR_CATEGORY(other)
|
||||
BOOST_SPIRIT_X3_MAJOR_CATEGORY(punctuation)
|
||||
BOOST_SPIRIT_X3_MAJOR_CATEGORY(symbol)
|
||||
|
||||
#undef BOOST_SPIRIT_X3_MAJOR_CATEGORY
|
||||
|
||||
// General Categories
|
||||
#define BOOST_SPIRIT_X3_CATEGORY(name) \
|
||||
[[nodiscard]] static constexpr bool \
|
||||
is_##name(char_type ch) noexcept \
|
||||
{ \
|
||||
return x3::unicode::get_category(ch) == x3::unicode::properties::name; \
|
||||
} \
|
||||
static constexpr void is_##name(char) = delete; \
|
||||
static constexpr void is_##name(wchar_t) = delete;
|
||||
|
||||
BOOST_SPIRIT_X3_CATEGORY(uppercase_letter)
|
||||
BOOST_SPIRIT_X3_CATEGORY(lowercase_letter)
|
||||
BOOST_SPIRIT_X3_CATEGORY(titlecase_letter)
|
||||
BOOST_SPIRIT_X3_CATEGORY(modifier_letter)
|
||||
BOOST_SPIRIT_X3_CATEGORY(other_letter)
|
||||
|
||||
BOOST_SPIRIT_X3_CATEGORY(nonspacing_mark)
|
||||
BOOST_SPIRIT_X3_CATEGORY(enclosing_mark)
|
||||
BOOST_SPIRIT_X3_CATEGORY(spacing_mark)
|
||||
|
||||
BOOST_SPIRIT_X3_CATEGORY(decimal_number)
|
||||
BOOST_SPIRIT_X3_CATEGORY(letter_number)
|
||||
BOOST_SPIRIT_X3_CATEGORY(other_number)
|
||||
|
||||
BOOST_SPIRIT_X3_CATEGORY(space_separator)
|
||||
BOOST_SPIRIT_X3_CATEGORY(line_separator)
|
||||
BOOST_SPIRIT_X3_CATEGORY(paragraph_separator)
|
||||
|
||||
BOOST_SPIRIT_X3_CATEGORY(control)
|
||||
BOOST_SPIRIT_X3_CATEGORY(format)
|
||||
BOOST_SPIRIT_X3_CATEGORY(private_use)
|
||||
BOOST_SPIRIT_X3_CATEGORY(surrogate)
|
||||
BOOST_SPIRIT_X3_CATEGORY(unassigned)
|
||||
|
||||
BOOST_SPIRIT_X3_CATEGORY(dash_punctuation)
|
||||
BOOST_SPIRIT_X3_CATEGORY(open_punctuation)
|
||||
BOOST_SPIRIT_X3_CATEGORY(close_punctuation)
|
||||
BOOST_SPIRIT_X3_CATEGORY(connector_punctuation)
|
||||
BOOST_SPIRIT_X3_CATEGORY(other_punctuation)
|
||||
BOOST_SPIRIT_X3_CATEGORY(initial_punctuation)
|
||||
BOOST_SPIRIT_X3_CATEGORY(final_punctuation)
|
||||
|
||||
BOOST_SPIRIT_X3_CATEGORY(math_symbol)
|
||||
BOOST_SPIRIT_X3_CATEGORY(currency_symbol)
|
||||
BOOST_SPIRIT_X3_CATEGORY(modifier_symbol)
|
||||
BOOST_SPIRIT_X3_CATEGORY(other_symbol)
|
||||
|
||||
#undef BOOST_SPIRIT_X3_CATEGORY
|
||||
|
||||
// Derived Categories
|
||||
#define BOOST_SPIRIT_X3_DERIVED_CATEGORY(name) \
|
||||
[[nodiscard]] static constexpr bool \
|
||||
is_##name(char_type ch) noexcept \
|
||||
{ \
|
||||
return x3::unicode::is_##name(ch); \
|
||||
} \
|
||||
static constexpr void is_##name(char) = delete; \
|
||||
static constexpr void is_##name(wchar_t) = delete;
|
||||
|
||||
BOOST_SPIRIT_X3_DERIVED_CATEGORY(alphabetic)
|
||||
BOOST_SPIRIT_X3_DERIVED_CATEGORY(uppercase)
|
||||
BOOST_SPIRIT_X3_DERIVED_CATEGORY(lowercase)
|
||||
BOOST_SPIRIT_X3_DERIVED_CATEGORY(white_space)
|
||||
BOOST_SPIRIT_X3_DERIVED_CATEGORY(hex_digit)
|
||||
BOOST_SPIRIT_X3_DERIVED_CATEGORY(noncharacter_code_point)
|
||||
BOOST_SPIRIT_X3_DERIVED_CATEGORY(default_ignorable_code_point)
|
||||
|
||||
#undef BOOST_SPIRIT_X3_DERIVED_CATEGORY
|
||||
|
||||
// Scripts
|
||||
#define BOOST_SPIRIT_X3_SCRIPT(name) \
|
||||
[[nodiscard]] static constexpr bool \
|
||||
is_##name(char_type ch) noexcept \
|
||||
{ \
|
||||
return x3::unicode::get_script(ch) == x3::unicode::properties::name; \
|
||||
} \
|
||||
static constexpr void is_##name(char) = delete; \
|
||||
static constexpr void is_##name(wchar_t) = delete;
|
||||
|
||||
BOOST_SPIRIT_X3_SCRIPT(adlam)
|
||||
BOOST_SPIRIT_X3_SCRIPT(caucasian_albanian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(ahom)
|
||||
BOOST_SPIRIT_X3_SCRIPT(arabic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(imperial_aramaic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(armenian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(avestan)
|
||||
BOOST_SPIRIT_X3_SCRIPT(balinese)
|
||||
BOOST_SPIRIT_X3_SCRIPT(bamum)
|
||||
BOOST_SPIRIT_X3_SCRIPT(bassa_vah)
|
||||
BOOST_SPIRIT_X3_SCRIPT(batak)
|
||||
BOOST_SPIRIT_X3_SCRIPT(bengali)
|
||||
BOOST_SPIRIT_X3_SCRIPT(bhaiksuki)
|
||||
BOOST_SPIRIT_X3_SCRIPT(bopomofo)
|
||||
BOOST_SPIRIT_X3_SCRIPT(brahmi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(braille)
|
||||
BOOST_SPIRIT_X3_SCRIPT(buginese)
|
||||
BOOST_SPIRIT_X3_SCRIPT(buhid)
|
||||
BOOST_SPIRIT_X3_SCRIPT(chakma)
|
||||
BOOST_SPIRIT_X3_SCRIPT(canadian_aboriginal)
|
||||
BOOST_SPIRIT_X3_SCRIPT(carian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(cham)
|
||||
BOOST_SPIRIT_X3_SCRIPT(cherokee)
|
||||
BOOST_SPIRIT_X3_SCRIPT(chorasmian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(coptic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(cypro_minoan)
|
||||
BOOST_SPIRIT_X3_SCRIPT(cypriot)
|
||||
BOOST_SPIRIT_X3_SCRIPT(cyrillic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(devanagari)
|
||||
BOOST_SPIRIT_X3_SCRIPT(dives_akuru)
|
||||
BOOST_SPIRIT_X3_SCRIPT(dogra)
|
||||
BOOST_SPIRIT_X3_SCRIPT(deseret)
|
||||
BOOST_SPIRIT_X3_SCRIPT(duployan)
|
||||
BOOST_SPIRIT_X3_SCRIPT(egyptian_hieroglyphs)
|
||||
BOOST_SPIRIT_X3_SCRIPT(elbasan)
|
||||
BOOST_SPIRIT_X3_SCRIPT(elymaic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(ethiopic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(georgian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(glagolitic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(gunjala_gondi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(masaram_gondi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(gothic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(grantha)
|
||||
BOOST_SPIRIT_X3_SCRIPT(greek)
|
||||
BOOST_SPIRIT_X3_SCRIPT(gujarati)
|
||||
BOOST_SPIRIT_X3_SCRIPT(gurmukhi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(hangul)
|
||||
BOOST_SPIRIT_X3_SCRIPT(han)
|
||||
BOOST_SPIRIT_X3_SCRIPT(hanunoo)
|
||||
BOOST_SPIRIT_X3_SCRIPT(hatran)
|
||||
BOOST_SPIRIT_X3_SCRIPT(hebrew)
|
||||
BOOST_SPIRIT_X3_SCRIPT(hiragana)
|
||||
BOOST_SPIRIT_X3_SCRIPT(anatolian_hieroglyphs)
|
||||
BOOST_SPIRIT_X3_SCRIPT(pahawh_hmong)
|
||||
BOOST_SPIRIT_X3_SCRIPT(nyiakeng_puachue_hmong)
|
||||
BOOST_SPIRIT_X3_SCRIPT(katakana_or_hiragana)
|
||||
BOOST_SPIRIT_X3_SCRIPT(old_hungarian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(old_italic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(javanese)
|
||||
BOOST_SPIRIT_X3_SCRIPT(kayah_li)
|
||||
BOOST_SPIRIT_X3_SCRIPT(katakana)
|
||||
BOOST_SPIRIT_X3_SCRIPT(kawi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(kharoshthi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(khmer)
|
||||
BOOST_SPIRIT_X3_SCRIPT(khojki)
|
||||
BOOST_SPIRIT_X3_SCRIPT(khitan_small_script)
|
||||
BOOST_SPIRIT_X3_SCRIPT(kannada)
|
||||
BOOST_SPIRIT_X3_SCRIPT(kaithi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(tai_tham)
|
||||
BOOST_SPIRIT_X3_SCRIPT(lao)
|
||||
BOOST_SPIRIT_X3_SCRIPT(latin)
|
||||
BOOST_SPIRIT_X3_SCRIPT(lepcha)
|
||||
BOOST_SPIRIT_X3_SCRIPT(limbu)
|
||||
BOOST_SPIRIT_X3_SCRIPT(linear_a)
|
||||
BOOST_SPIRIT_X3_SCRIPT(linear_b)
|
||||
BOOST_SPIRIT_X3_SCRIPT(lisu)
|
||||
BOOST_SPIRIT_X3_SCRIPT(lycian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(lydian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(mahajani)
|
||||
BOOST_SPIRIT_X3_SCRIPT(makasar)
|
||||
BOOST_SPIRIT_X3_SCRIPT(mandaic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(manichaean)
|
||||
BOOST_SPIRIT_X3_SCRIPT(marchen)
|
||||
BOOST_SPIRIT_X3_SCRIPT(medefaidrin)
|
||||
BOOST_SPIRIT_X3_SCRIPT(mende_kikakui)
|
||||
BOOST_SPIRIT_X3_SCRIPT(meroitic_cursive)
|
||||
BOOST_SPIRIT_X3_SCRIPT(meroitic_hieroglyphs)
|
||||
BOOST_SPIRIT_X3_SCRIPT(malayalam)
|
||||
BOOST_SPIRIT_X3_SCRIPT(modi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(mongolian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(mro)
|
||||
BOOST_SPIRIT_X3_SCRIPT(meetei_mayek)
|
||||
BOOST_SPIRIT_X3_SCRIPT(multani)
|
||||
BOOST_SPIRIT_X3_SCRIPT(myanmar)
|
||||
BOOST_SPIRIT_X3_SCRIPT(nag_mundari)
|
||||
BOOST_SPIRIT_X3_SCRIPT(nandinagari)
|
||||
BOOST_SPIRIT_X3_SCRIPT(old_north_arabian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(nabataean)
|
||||
BOOST_SPIRIT_X3_SCRIPT(newa)
|
||||
BOOST_SPIRIT_X3_SCRIPT(nko)
|
||||
BOOST_SPIRIT_X3_SCRIPT(nushu)
|
||||
BOOST_SPIRIT_X3_SCRIPT(ogham)
|
||||
BOOST_SPIRIT_X3_SCRIPT(ol_chiki)
|
||||
BOOST_SPIRIT_X3_SCRIPT(old_turkic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(oriya)
|
||||
BOOST_SPIRIT_X3_SCRIPT(osage)
|
||||
BOOST_SPIRIT_X3_SCRIPT(osmanya)
|
||||
BOOST_SPIRIT_X3_SCRIPT(old_uyghur)
|
||||
BOOST_SPIRIT_X3_SCRIPT(palmyrene)
|
||||
BOOST_SPIRIT_X3_SCRIPT(pau_cin_hau)
|
||||
BOOST_SPIRIT_X3_SCRIPT(old_permic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(phags_pa)
|
||||
BOOST_SPIRIT_X3_SCRIPT(inscriptional_pahlavi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(psalter_pahlavi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(phoenician)
|
||||
BOOST_SPIRIT_X3_SCRIPT(miao)
|
||||
BOOST_SPIRIT_X3_SCRIPT(inscriptional_parthian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(rejang)
|
||||
BOOST_SPIRIT_X3_SCRIPT(hanifi_rohingya)
|
||||
BOOST_SPIRIT_X3_SCRIPT(runic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(samaritan)
|
||||
BOOST_SPIRIT_X3_SCRIPT(old_south_arabian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(saurashtra)
|
||||
BOOST_SPIRIT_X3_SCRIPT(signwriting)
|
||||
BOOST_SPIRIT_X3_SCRIPT(shavian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(sharada)
|
||||
BOOST_SPIRIT_X3_SCRIPT(siddham)
|
||||
BOOST_SPIRIT_X3_SCRIPT(khudawadi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(sinhala)
|
||||
BOOST_SPIRIT_X3_SCRIPT(sogdian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(old_sogdian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(sora_sompeng)
|
||||
BOOST_SPIRIT_X3_SCRIPT(soyombo)
|
||||
BOOST_SPIRIT_X3_SCRIPT(sundanese)
|
||||
BOOST_SPIRIT_X3_SCRIPT(syloti_nagri)
|
||||
BOOST_SPIRIT_X3_SCRIPT(syriac)
|
||||
BOOST_SPIRIT_X3_SCRIPT(tagbanwa)
|
||||
BOOST_SPIRIT_X3_SCRIPT(takri)
|
||||
BOOST_SPIRIT_X3_SCRIPT(tai_le)
|
||||
BOOST_SPIRIT_X3_SCRIPT(new_tai_lue)
|
||||
BOOST_SPIRIT_X3_SCRIPT(tamil)
|
||||
BOOST_SPIRIT_X3_SCRIPT(tangut)
|
||||
BOOST_SPIRIT_X3_SCRIPT(tai_viet)
|
||||
BOOST_SPIRIT_X3_SCRIPT(telugu)
|
||||
BOOST_SPIRIT_X3_SCRIPT(tifinagh)
|
||||
BOOST_SPIRIT_X3_SCRIPT(tagalog)
|
||||
BOOST_SPIRIT_X3_SCRIPT(thaana)
|
||||
BOOST_SPIRIT_X3_SCRIPT(thai)
|
||||
BOOST_SPIRIT_X3_SCRIPT(tibetan)
|
||||
BOOST_SPIRIT_X3_SCRIPT(tirhuta)
|
||||
BOOST_SPIRIT_X3_SCRIPT(tangsa)
|
||||
BOOST_SPIRIT_X3_SCRIPT(toto)
|
||||
BOOST_SPIRIT_X3_SCRIPT(ugaritic)
|
||||
BOOST_SPIRIT_X3_SCRIPT(vai)
|
||||
BOOST_SPIRIT_X3_SCRIPT(vithkuqi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(warang_citi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(wancho)
|
||||
BOOST_SPIRIT_X3_SCRIPT(old_persian)
|
||||
BOOST_SPIRIT_X3_SCRIPT(cuneiform)
|
||||
BOOST_SPIRIT_X3_SCRIPT(yezidi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(yi)
|
||||
BOOST_SPIRIT_X3_SCRIPT(zanabazar_square)
|
||||
BOOST_SPIRIT_X3_SCRIPT(inherited)
|
||||
BOOST_SPIRIT_X3_SCRIPT(common)
|
||||
BOOST_SPIRIT_X3_SCRIPT(unknown)
|
||||
|
||||
#undef BOOST_SPIRIT_X3_SCRIPT
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::char_encoding
|
||||
|
||||
#endif
|
||||
@@ -1,377 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
Autogenerated by MultiStageTable.py (Unicode multi-stage
|
||||
table builder) (c) Peter Kankowski, 2008
|
||||
==============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CHAR_ENCODING_UNICODE_CLASSIFICATION_HPP
|
||||
#define BOOST_SPIRIT_X3_CHAR_ENCODING_UNICODE_CLASSIFICATION_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/char_encoding/unicode/detail/category_table.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/unicode/detail/script_table.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/unicode/detail/lowercase_table.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/unicode/detail/uppercase_table.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost::spirit::x3::unicode
|
||||
{
|
||||
// This header provides Basic (Level 1) Unicode Support
|
||||
// See http://unicode.org/reports/tr18/ for details
|
||||
|
||||
namespace properties
|
||||
{
|
||||
// bit pattern: xxMMMCCC
|
||||
// MMM: major_category
|
||||
// CCC: category
|
||||
|
||||
enum major_category
|
||||
{
|
||||
letter,
|
||||
mark,
|
||||
number,
|
||||
separator,
|
||||
other,
|
||||
punctuation,
|
||||
symbol
|
||||
};
|
||||
|
||||
enum category
|
||||
{
|
||||
uppercase_letter = 0, // [Lu] an uppercase letter
|
||||
lowercase_letter, // [Ll] a lowercase letter
|
||||
titlecase_letter, // [Lt] a digraphic character, with first part uppercase
|
||||
modifier_letter, // [Lm] a modifier letter
|
||||
other_letter, // [Lo] other letters, including syllables and ideographs
|
||||
|
||||
nonspacing_mark = 8, // [Mn] a nonspacing combining mark (zero advance width)
|
||||
enclosing_mark, // [Me] an enclosing combining mark
|
||||
spacing_mark, // [Mc] a spacing combining mark (positive advance width)
|
||||
|
||||
decimal_number = 16, // [Nd] a decimal digit
|
||||
letter_number, // [Nl] a letterlike numeric character
|
||||
other_number, // [No] a numeric character of other type
|
||||
|
||||
space_separator = 24, // [Zs] a space character (of various non-zero widths)
|
||||
line_separator, // [Zl] U+2028 LINE SEPARATOR only
|
||||
paragraph_separator, // [Zp] U+2029 PARAGRAPH SEPARATOR only
|
||||
|
||||
control = 32, // [Cc] a C0 or C1 control code
|
||||
format, // [Cf] a format control character
|
||||
private_use, // [Co] a private-use character
|
||||
surrogate, // [Cs] a surrogate code point
|
||||
unassigned, // [Cn] a reserved unassigned code point or a noncharacter
|
||||
|
||||
dash_punctuation = 40, // [Pd] a dash or hyphen punctuation mark
|
||||
open_punctuation, // [Ps] an opening punctuation mark (of a pair)
|
||||
close_punctuation, // [Pe] a closing punctuation mark (of a pair)
|
||||
connector_punctuation, // [Pc] a connecting punctuation mark, like a tie
|
||||
other_punctuation, // [Po] a punctuation mark of other type
|
||||
initial_punctuation, // [Pi] an initial quotation mark
|
||||
final_punctuation, // [Pf] a final quotation mark
|
||||
|
||||
math_symbol = 48, // [Sm] a symbol of primarily mathematical use
|
||||
currency_symbol, // [Sc] a currency sign
|
||||
modifier_symbol, // [Sk] a non-letterlike modifier symbol
|
||||
other_symbol // [So] a symbol of other type
|
||||
};
|
||||
|
||||
enum derived_properties
|
||||
{
|
||||
alphabetic = 64,
|
||||
uppercase = 128,
|
||||
lowercase = 256,
|
||||
white_space = 512,
|
||||
hex_digit = 1024,
|
||||
noncharacter_code_point = 2048,
|
||||
default_ignorable_code_point = 4096
|
||||
};
|
||||
|
||||
enum script
|
||||
{
|
||||
adlam,
|
||||
caucasian_albanian,
|
||||
ahom,
|
||||
arabic,
|
||||
imperial_aramaic,
|
||||
armenian,
|
||||
avestan,
|
||||
balinese,
|
||||
bamum,
|
||||
bassa_vah,
|
||||
batak,
|
||||
bengali,
|
||||
bhaiksuki,
|
||||
bopomofo,
|
||||
brahmi,
|
||||
braille,
|
||||
buginese,
|
||||
buhid,
|
||||
chakma,
|
||||
canadian_aboriginal,
|
||||
carian,
|
||||
cham,
|
||||
cherokee,
|
||||
chorasmian,
|
||||
coptic,
|
||||
cypro_minoan,
|
||||
cypriot,
|
||||
cyrillic,
|
||||
devanagari,
|
||||
dives_akuru,
|
||||
dogra,
|
||||
deseret,
|
||||
duployan,
|
||||
egyptian_hieroglyphs,
|
||||
elbasan,
|
||||
elymaic,
|
||||
ethiopic,
|
||||
georgian,
|
||||
glagolitic,
|
||||
gunjala_gondi,
|
||||
masaram_gondi,
|
||||
gothic,
|
||||
grantha,
|
||||
greek,
|
||||
gujarati,
|
||||
gurmukhi,
|
||||
hangul,
|
||||
han,
|
||||
hanunoo,
|
||||
hatran,
|
||||
hebrew,
|
||||
hiragana,
|
||||
anatolian_hieroglyphs,
|
||||
pahawh_hmong,
|
||||
nyiakeng_puachue_hmong,
|
||||
katakana_or_hiragana,
|
||||
old_hungarian,
|
||||
old_italic,
|
||||
javanese,
|
||||
kayah_li,
|
||||
katakana,
|
||||
kawi,
|
||||
kharoshthi,
|
||||
khmer,
|
||||
khojki,
|
||||
khitan_small_script,
|
||||
kannada,
|
||||
kaithi,
|
||||
tai_tham,
|
||||
lao,
|
||||
latin,
|
||||
lepcha,
|
||||
limbu,
|
||||
linear_a,
|
||||
linear_b,
|
||||
lisu,
|
||||
lycian,
|
||||
lydian,
|
||||
mahajani,
|
||||
makasar,
|
||||
mandaic,
|
||||
manichaean,
|
||||
marchen,
|
||||
medefaidrin,
|
||||
mende_kikakui,
|
||||
meroitic_cursive,
|
||||
meroitic_hieroglyphs,
|
||||
malayalam,
|
||||
modi,
|
||||
mongolian,
|
||||
mro,
|
||||
meetei_mayek,
|
||||
multani,
|
||||
myanmar,
|
||||
nag_mundari,
|
||||
nandinagari,
|
||||
old_north_arabian,
|
||||
nabataean,
|
||||
newa,
|
||||
nko,
|
||||
nushu,
|
||||
ogham,
|
||||
ol_chiki,
|
||||
old_turkic,
|
||||
oriya,
|
||||
osage,
|
||||
osmanya,
|
||||
old_uyghur,
|
||||
palmyrene,
|
||||
pau_cin_hau,
|
||||
old_permic,
|
||||
phags_pa,
|
||||
inscriptional_pahlavi,
|
||||
psalter_pahlavi,
|
||||
phoenician,
|
||||
miao,
|
||||
inscriptional_parthian,
|
||||
rejang,
|
||||
hanifi_rohingya,
|
||||
runic,
|
||||
samaritan,
|
||||
old_south_arabian,
|
||||
saurashtra,
|
||||
signwriting,
|
||||
shavian,
|
||||
sharada,
|
||||
siddham,
|
||||
khudawadi,
|
||||
sinhala,
|
||||
sogdian,
|
||||
old_sogdian,
|
||||
sora_sompeng,
|
||||
soyombo,
|
||||
sundanese,
|
||||
syloti_nagri,
|
||||
syriac,
|
||||
tagbanwa,
|
||||
takri,
|
||||
tai_le,
|
||||
new_tai_lue,
|
||||
tamil,
|
||||
tangut,
|
||||
tai_viet,
|
||||
telugu,
|
||||
tifinagh,
|
||||
tagalog,
|
||||
thaana,
|
||||
thai,
|
||||
tibetan,
|
||||
tirhuta,
|
||||
tangsa,
|
||||
toto,
|
||||
ugaritic,
|
||||
vai,
|
||||
vithkuqi,
|
||||
warang_citi,
|
||||
wancho,
|
||||
old_persian,
|
||||
cuneiform,
|
||||
yezidi,
|
||||
yi,
|
||||
zanabazar_square,
|
||||
inherited,
|
||||
common,
|
||||
unknown
|
||||
};
|
||||
} // properties
|
||||
|
||||
[[nodiscard]] constexpr properties::category get_category(std::uint32_t ch) noexcept
|
||||
{
|
||||
return static_cast<properties::category>(detail::category_lookup(ch) & 0x3F);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr properties::major_category get_major_category(std::uint32_t ch) noexcept
|
||||
{
|
||||
return static_cast<properties::major_category>(unicode::get_category(ch) >> 3);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_punctuation(std::uint32_t ch) noexcept
|
||||
{
|
||||
return unicode::get_major_category(ch) == properties::punctuation;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_decimal_number(std::uint32_t ch) noexcept
|
||||
{
|
||||
return unicode::get_category(ch) == properties::decimal_number;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_hex_digit(std::uint32_t ch) noexcept
|
||||
{
|
||||
return (detail::category_lookup(ch) & properties::hex_digit) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_control(std::uint32_t ch) noexcept
|
||||
{
|
||||
return unicode::get_category(ch) == properties::control;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_alphabetic(std::uint32_t ch) noexcept
|
||||
{
|
||||
return (detail::category_lookup(ch) & properties::alphabetic) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_alphanumeric(std::uint32_t ch) noexcept
|
||||
{
|
||||
return unicode::is_decimal_number(ch) || unicode::is_alphabetic(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_uppercase(std::uint32_t ch) noexcept
|
||||
{
|
||||
return (detail::category_lookup(ch) & properties::uppercase) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_lowercase(std::uint32_t ch) noexcept
|
||||
{
|
||||
return (detail::category_lookup(ch) & properties::lowercase) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_white_space(std::uint32_t ch) noexcept
|
||||
{
|
||||
return (detail::category_lookup(ch) & properties::white_space) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_blank(std::uint32_t ch) noexcept
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case '\n': case '\v': case '\f': case '\r':
|
||||
return false;
|
||||
default:
|
||||
return unicode::is_white_space(ch)
|
||||
&& !( unicode::get_category(ch) == properties::line_separator
|
||||
|| unicode::get_category(ch) == properties::paragraph_separator
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_graph(std::uint32_t ch) noexcept
|
||||
{
|
||||
return !( unicode::is_white_space(ch)
|
||||
|| unicode::get_category(ch) == properties::control
|
||||
|| unicode::get_category(ch) == properties::surrogate
|
||||
|| unicode::get_category(ch) == properties::unassigned
|
||||
);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_print(std::uint32_t ch) noexcept
|
||||
{
|
||||
return (unicode::is_graph(ch) || unicode::is_blank(ch)) && !unicode::is_control(ch);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_noncharacter_code_point(std::uint32_t ch) noexcept
|
||||
{
|
||||
return (detail::category_lookup(ch) & properties::noncharacter_code_point) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_default_ignorable_code_point(std::uint32_t ch) noexcept
|
||||
{
|
||||
return (detail::category_lookup(ch) & properties::default_ignorable_code_point) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr properties::script get_script(std::uint32_t ch) noexcept
|
||||
{
|
||||
return static_cast<properties::script>(detail::script_lookup(ch));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::uint32_t to_lowercase(std::uint32_t ch) noexcept
|
||||
{
|
||||
// The table returns 0 to signal that this code maps to itself
|
||||
std::uint32_t r = detail::lowercase_lookup(ch);
|
||||
return (r == 0)? ch : r;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::uint32_t to_uppercase(std::uint32_t ch) noexcept
|
||||
{
|
||||
// The table returns 0 to signal that this code maps to itself
|
||||
std::uint32_t r = detail::uppercase_lookup(ch);
|
||||
return (r == 0)? ch : r;
|
||||
}
|
||||
} // boost::spirit::x3::unicode
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,754 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
AUTOGENERATED. DO NOT EDIT!!!
|
||||
==============================================================================*/
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost::spirit::x3::unicode::detail
|
||||
{
|
||||
inline constexpr std::uint8_t lowercase_stage1[] = {
|
||||
|
||||
0, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
7, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 9, 6, 10, 11,
|
||||
6, 12, 6, 6, 13, 6, 6, 6, 6, 6, 6, 6, 14, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 15, 16, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 17,
|
||||
6, 6, 6, 6, 18, 19, 6, 6, 6, 6, 6, 6, 20, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 21, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 22, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 23, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
|
||||
};
|
||||
|
||||
inline constexpr std::uint32_t lowercase_stage2[] = {
|
||||
|
||||
// block 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
|
||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
|
||||
240, 241, 242, 243, 244, 245, 246, 0, 248, 249, 250, 251, 252, 253, 254, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 1
|
||||
257, 0, 259, 0, 261, 0, 263, 0, 265, 0, 267, 0, 269, 0, 271, 0,
|
||||
273, 0, 275, 0, 277, 0, 279, 0, 281, 0, 283, 0, 285, 0, 287, 0,
|
||||
289, 0, 291, 0, 293, 0, 295, 0, 297, 0, 299, 0, 301, 0, 303, 0,
|
||||
105, 0, 307, 0, 309, 0, 311, 0, 0, 314, 0, 316, 0, 318, 0, 320,
|
||||
0, 322, 0, 324, 0, 326, 0, 328, 0, 0, 331, 0, 333, 0, 335, 0,
|
||||
337, 0, 339, 0, 341, 0, 343, 0, 345, 0, 347, 0, 349, 0, 351, 0,
|
||||
353, 0, 355, 0, 357, 0, 359, 0, 361, 0, 363, 0, 365, 0, 367, 0,
|
||||
369, 0, 371, 0, 373, 0, 375, 0, 255, 378, 0, 380, 0, 382, 0, 0,
|
||||
0, 595, 387, 0, 389, 0, 596, 392, 0, 598, 599, 396, 0, 0, 477, 601,
|
||||
603, 402, 0, 608, 611, 0, 617, 616, 409, 0, 0, 0, 623, 626, 0, 629,
|
||||
417, 0, 419, 0, 421, 0, 640, 424, 0, 643, 0, 0, 429, 0, 648, 432,
|
||||
0, 650, 651, 436, 0, 438, 0, 658, 441, 0, 0, 0, 445, 0, 0, 0,
|
||||
0, 0, 0, 0, 454, 454, 0, 457, 457, 0, 460, 460, 0, 462, 0, 464,
|
||||
0, 466, 0, 468, 0, 470, 0, 472, 0, 474, 0, 476, 0, 0, 479, 0,
|
||||
481, 0, 483, 0, 485, 0, 487, 0, 489, 0, 491, 0, 493, 0, 495, 0,
|
||||
0, 499, 499, 0, 501, 0, 405, 447, 505, 0, 507, 0, 509, 0, 511, 0,
|
||||
|
||||
|
||||
// block 2
|
||||
513, 0, 515, 0, 517, 0, 519, 0, 521, 0, 523, 0, 525, 0, 527, 0,
|
||||
529, 0, 531, 0, 533, 0, 535, 0, 537, 0, 539, 0, 541, 0, 543, 0,
|
||||
414, 0, 547, 0, 549, 0, 551, 0, 553, 0, 555, 0, 557, 0, 559, 0,
|
||||
561, 0, 563, 0, 0, 0, 0, 0, 0, 0, 11365, 572, 0, 410, 11366, 0,
|
||||
0, 578, 0, 384, 649, 652, 583, 0, 585, 0, 587, 0, 589, 0, 591, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 3
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
881, 0, 883, 0, 0, 0, 887, 0, 0, 0, 0, 0, 0, 0, 0, 1011,
|
||||
0, 0, 0, 0, 0, 0, 940, 0, 941, 942, 943, 0, 972, 0, 973, 974,
|
||||
0, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959,
|
||||
960, 961, 0, 963, 964, 965, 966, 967, 968, 969, 970, 971, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 983,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 985, 0, 987, 0, 989, 0, 991, 0,
|
||||
993, 0, 995, 0, 997, 0, 999, 0, 1001, 0, 1003, 0, 1005, 0, 1007, 0,
|
||||
0, 0, 0, 0, 952, 0, 0, 1016, 0, 1010, 1019, 0, 0, 891, 892, 893,
|
||||
|
||||
|
||||
// block 4
|
||||
1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119,
|
||||
1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087,
|
||||
1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1121, 0, 1123, 0, 1125, 0, 1127, 0, 1129, 0, 1131, 0, 1133, 0, 1135, 0,
|
||||
1137, 0, 1139, 0, 1141, 0, 1143, 0, 1145, 0, 1147, 0, 1149, 0, 1151, 0,
|
||||
1153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1163, 0, 1165, 0, 1167, 0,
|
||||
1169, 0, 1171, 0, 1173, 0, 1175, 0, 1177, 0, 1179, 0, 1181, 0, 1183, 0,
|
||||
1185, 0, 1187, 0, 1189, 0, 1191, 0, 1193, 0, 1195, 0, 1197, 0, 1199, 0,
|
||||
1201, 0, 1203, 0, 1205, 0, 1207, 0, 1209, 0, 1211, 0, 1213, 0, 1215, 0,
|
||||
1231, 1218, 0, 1220, 0, 1222, 0, 1224, 0, 1226, 0, 1228, 0, 1230, 0, 0,
|
||||
1233, 0, 1235, 0, 1237, 0, 1239, 0, 1241, 0, 1243, 0, 1245, 0, 1247, 0,
|
||||
1249, 0, 1251, 0, 1253, 0, 1255, 0, 1257, 0, 1259, 0, 1261, 0, 1263, 0,
|
||||
1265, 0, 1267, 0, 1269, 0, 1271, 0, 1273, 0, 1275, 0, 1277, 0, 1279, 0,
|
||||
|
||||
|
||||
// block 5
|
||||
1281, 0, 1283, 0, 1285, 0, 1287, 0, 1289, 0, 1291, 0, 1293, 0, 1295, 0,
|
||||
1297, 0, 1299, 0, 1301, 0, 1303, 0, 1305, 0, 1307, 0, 1309, 0, 1311, 0,
|
||||
1313, 0, 1315, 0, 1317, 0, 1319, 0, 1321, 0, 1323, 0, 1325, 0, 1327, 0,
|
||||
0, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391,
|
||||
1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407,
|
||||
1408, 1409, 1410, 1411, 1412, 1413, 1414, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 6
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 7
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
11520, 11521, 11522, 11523, 11524, 11525, 11526, 11527, 11528, 11529, 11530, 11531, 11532, 11533, 11534, 11535,
|
||||
11536, 11537, 11538, 11539, 11540, 11541, 11542, 11543, 11544, 11545, 11546, 11547, 11548, 11549, 11550, 11551,
|
||||
11552, 11553, 11554, 11555, 11556, 11557, 0, 11559, 0, 0, 0, 0, 0, 11565, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 8
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
43888, 43889, 43890, 43891, 43892, 43893, 43894, 43895, 43896, 43897, 43898, 43899, 43900, 43901, 43902, 43903,
|
||||
43904, 43905, 43906, 43907, 43908, 43909, 43910, 43911, 43912, 43913, 43914, 43915, 43916, 43917, 43918, 43919,
|
||||
43920, 43921, 43922, 43923, 43924, 43925, 43926, 43927, 43928, 43929, 43930, 43931, 43932, 43933, 43934, 43935,
|
||||
43936, 43937, 43938, 43939, 43940, 43941, 43942, 43943, 43944, 43945, 43946, 43947, 43948, 43949, 43950, 43951,
|
||||
43952, 43953, 43954, 43955, 43956, 43957, 43958, 43959, 43960, 43961, 43962, 43963, 43964, 43965, 43966, 43967,
|
||||
5112, 5113, 5114, 5115, 5116, 5117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 9
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319,
|
||||
4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335,
|
||||
4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 0, 0, 4349, 4350, 4351,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 10
|
||||
7681, 0, 7683, 0, 7685, 0, 7687, 0, 7689, 0, 7691, 0, 7693, 0, 7695, 0,
|
||||
7697, 0, 7699, 0, 7701, 0, 7703, 0, 7705, 0, 7707, 0, 7709, 0, 7711, 0,
|
||||
7713, 0, 7715, 0, 7717, 0, 7719, 0, 7721, 0, 7723, 0, 7725, 0, 7727, 0,
|
||||
7729, 0, 7731, 0, 7733, 0, 7735, 0, 7737, 0, 7739, 0, 7741, 0, 7743, 0,
|
||||
7745, 0, 7747, 0, 7749, 0, 7751, 0, 7753, 0, 7755, 0, 7757, 0, 7759, 0,
|
||||
7761, 0, 7763, 0, 7765, 0, 7767, 0, 7769, 0, 7771, 0, 7773, 0, 7775, 0,
|
||||
7777, 0, 7779, 0, 7781, 0, 7783, 0, 7785, 0, 7787, 0, 7789, 0, 7791, 0,
|
||||
7793, 0, 7795, 0, 7797, 0, 7799, 0, 7801, 0, 7803, 0, 7805, 0, 7807, 0,
|
||||
7809, 0, 7811, 0, 7813, 0, 7815, 0, 7817, 0, 7819, 0, 7821, 0, 7823, 0,
|
||||
7825, 0, 7827, 0, 7829, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 0,
|
||||
7841, 0, 7843, 0, 7845, 0, 7847, 0, 7849, 0, 7851, 0, 7853, 0, 7855, 0,
|
||||
7857, 0, 7859, 0, 7861, 0, 7863, 0, 7865, 0, 7867, 0, 7869, 0, 7871, 0,
|
||||
7873, 0, 7875, 0, 7877, 0, 7879, 0, 7881, 0, 7883, 0, 7885, 0, 7887, 0,
|
||||
7889, 0, 7891, 0, 7893, 0, 7895, 0, 7897, 0, 7899, 0, 7901, 0, 7903, 0,
|
||||
7905, 0, 7907, 0, 7909, 0, 7911, 0, 7913, 0, 7915, 0, 7917, 0, 7919, 0,
|
||||
7921, 0, 7923, 0, 7925, 0, 7927, 0, 7929, 0, 7931, 0, 7933, 0, 7935, 0,
|
||||
|
||||
|
||||
// block 11
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 7936, 7937, 7938, 7939, 7940, 7941, 7942, 7943,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 7952, 7953, 7954, 7955, 7956, 7957, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 7984, 7985, 7986, 7987, 7988, 7989, 7990, 7991,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 8000, 8001, 8002, 8003, 8004, 8005, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 8017, 0, 8019, 0, 8021, 0, 8023,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 8064, 8065, 8066, 8067, 8068, 8069, 8070, 8071,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 8096, 8097, 8098, 8099, 8100, 8101, 8102, 8103,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 8112, 8113, 8048, 8049, 8115, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 8050, 8051, 8052, 8053, 8131, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 8144, 8145, 8054, 8055, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 8160, 8161, 8058, 8059, 8165, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 8056, 8057, 8060, 8061, 8179, 0, 0, 0,
|
||||
|
||||
|
||||
// block 12
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 969, 0, 0, 0, 107, 229, 0, 0, 0, 0,
|
||||
0, 0, 8526, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8560, 8561, 8562, 8563, 8564, 8565, 8566, 8567, 8568, 8569, 8570, 8571, 8572, 8573, 8574, 8575,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 8580, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 13
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 9424, 9425, 9426, 9427, 9428, 9429, 9430, 9431, 9432, 9433,
|
||||
9434, 9435, 9436, 9437, 9438, 9439, 9440, 9441, 9442, 9443, 9444, 9445, 9446, 9447, 9448, 9449,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 14
|
||||
11312, 11313, 11314, 11315, 11316, 11317, 11318, 11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, 11327,
|
||||
11328, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342, 11343,
|
||||
11344, 11345, 11346, 11347, 11348, 11349, 11350, 11351, 11352, 11353, 11354, 11355, 11356, 11357, 11358, 11359,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
11361, 0, 619, 7549, 637, 0, 0, 11368, 0, 11370, 0, 11372, 0, 593, 625, 592,
|
||||
594, 0, 11379, 0, 0, 11382, 0, 0, 0, 0, 0, 0, 0, 0, 575, 576,
|
||||
11393, 0, 11395, 0, 11397, 0, 11399, 0, 11401, 0, 11403, 0, 11405, 0, 11407, 0,
|
||||
11409, 0, 11411, 0, 11413, 0, 11415, 0, 11417, 0, 11419, 0, 11421, 0, 11423, 0,
|
||||
11425, 0, 11427, 0, 11429, 0, 11431, 0, 11433, 0, 11435, 0, 11437, 0, 11439, 0,
|
||||
11441, 0, 11443, 0, 11445, 0, 11447, 0, 11449, 0, 11451, 0, 11453, 0, 11455, 0,
|
||||
11457, 0, 11459, 0, 11461, 0, 11463, 0, 11465, 0, 11467, 0, 11469, 0, 11471, 0,
|
||||
11473, 0, 11475, 0, 11477, 0, 11479, 0, 11481, 0, 11483, 0, 11485, 0, 11487, 0,
|
||||
11489, 0, 11491, 0, 0, 0, 0, 0, 0, 0, 0, 11500, 0, 11502, 0, 0,
|
||||
0, 0, 11507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 15
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
42561, 0, 42563, 0, 42565, 0, 42567, 0, 42569, 0, 42571, 0, 42573, 0, 42575, 0,
|
||||
42577, 0, 42579, 0, 42581, 0, 42583, 0, 42585, 0, 42587, 0, 42589, 0, 42591, 0,
|
||||
42593, 0, 42595, 0, 42597, 0, 42599, 0, 42601, 0, 42603, 0, 42605, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
42625, 0, 42627, 0, 42629, 0, 42631, 0, 42633, 0, 42635, 0, 42637, 0, 42639, 0,
|
||||
42641, 0, 42643, 0, 42645, 0, 42647, 0, 42649, 0, 42651, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 16
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 42787, 0, 42789, 0, 42791, 0, 42793, 0, 42795, 0, 42797, 0, 42799, 0,
|
||||
0, 0, 42803, 0, 42805, 0, 42807, 0, 42809, 0, 42811, 0, 42813, 0, 42815, 0,
|
||||
42817, 0, 42819, 0, 42821, 0, 42823, 0, 42825, 0, 42827, 0, 42829, 0, 42831, 0,
|
||||
42833, 0, 42835, 0, 42837, 0, 42839, 0, 42841, 0, 42843, 0, 42845, 0, 42847, 0,
|
||||
42849, 0, 42851, 0, 42853, 0, 42855, 0, 42857, 0, 42859, 0, 42861, 0, 42863, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 42874, 0, 42876, 0, 7545, 42879, 0,
|
||||
42881, 0, 42883, 0, 42885, 0, 42887, 0, 0, 0, 0, 42892, 0, 613, 0, 0,
|
||||
42897, 0, 42899, 0, 0, 0, 42903, 0, 42905, 0, 42907, 0, 42909, 0, 42911, 0,
|
||||
42913, 0, 42915, 0, 42917, 0, 42919, 0, 42921, 0, 614, 604, 609, 620, 618, 0,
|
||||
670, 647, 669, 43859, 42933, 0, 42935, 0, 42937, 0, 42939, 0, 42941, 0, 42943, 0,
|
||||
42945, 0, 42947, 0, 42900, 642, 7566, 42952, 0, 42954, 0, 0, 0, 0, 0, 0,
|
||||
42961, 0, 0, 0, 0, 0, 42967, 0, 42969, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 42998, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 17
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 65345, 65346, 65347, 65348, 65349, 65350, 65351, 65352, 65353, 65354, 65355, 65356, 65357, 65358, 65359,
|
||||
65360, 65361, 65362, 65363, 65364, 65365, 65366, 65367, 65368, 65369, 65370, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 18
|
||||
66600, 66601, 66602, 66603, 66604, 66605, 66606, 66607, 66608, 66609, 66610, 66611, 66612, 66613, 66614, 66615,
|
||||
66616, 66617, 66618, 66619, 66620, 66621, 66622, 66623, 66624, 66625, 66626, 66627, 66628, 66629, 66630, 66631,
|
||||
66632, 66633, 66634, 66635, 66636, 66637, 66638, 66639, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
66776, 66777, 66778, 66779, 66780, 66781, 66782, 66783, 66784, 66785, 66786, 66787, 66788, 66789, 66790, 66791,
|
||||
66792, 66793, 66794, 66795, 66796, 66797, 66798, 66799, 66800, 66801, 66802, 66803, 66804, 66805, 66806, 66807,
|
||||
66808, 66809, 66810, 66811, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 19
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
66967, 66968, 66969, 66970, 66971, 66972, 66973, 66974, 66975, 66976, 66977, 0, 66979, 66980, 66981, 66982,
|
||||
66983, 66984, 66985, 66986, 66987, 66988, 66989, 66990, 66991, 66992, 66993, 0, 66995, 66996, 66997, 66998,
|
||||
66999, 67000, 67001, 0, 67003, 67004, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 20
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
68800, 68801, 68802, 68803, 68804, 68805, 68806, 68807, 68808, 68809, 68810, 68811, 68812, 68813, 68814, 68815,
|
||||
68816, 68817, 68818, 68819, 68820, 68821, 68822, 68823, 68824, 68825, 68826, 68827, 68828, 68829, 68830, 68831,
|
||||
68832, 68833, 68834, 68835, 68836, 68837, 68838, 68839, 68840, 68841, 68842, 68843, 68844, 68845, 68846, 68847,
|
||||
68848, 68849, 68850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 21
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
71872, 71873, 71874, 71875, 71876, 71877, 71878, 71879, 71880, 71881, 71882, 71883, 71884, 71885, 71886, 71887,
|
||||
71888, 71889, 71890, 71891, 71892, 71893, 71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902, 71903,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 22
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
93792, 93793, 93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802, 93803, 93804, 93805, 93806, 93807,
|
||||
93808, 93809, 93810, 93811, 93812, 93813, 93814, 93815, 93816, 93817, 93818, 93819, 93820, 93821, 93822, 93823,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 23
|
||||
125218, 125219, 125220, 125221, 125222, 125223, 125224, 125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232, 125233,
|
||||
125234, 125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242, 125243, 125244, 125245, 125246, 125247, 125248, 125249,
|
||||
125250, 125251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
[[nodiscard]] constexpr std::uint32_t lowercase_lookup(std::uint32_t ch) noexcept
|
||||
{
|
||||
std::uint32_t block_offset = lowercase_stage1[ch / 256] * 256;
|
||||
return lowercase_stage2[block_offset + ch % 256];
|
||||
}
|
||||
|
||||
} // boost::spirit::x3::unicode::detail
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,811 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
AUTOGENERATED. DO NOT EDIT!!!
|
||||
==============================================================================*/
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost::spirit::x3::unicode::detail
|
||||
{
|
||||
inline constexpr std::uint8_t uppercase_stage1[] = {
|
||||
|
||||
0, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
7, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 9, 10, 11, 12,
|
||||
6, 13, 6, 6, 14, 6, 6, 6, 6, 6, 6, 6, 15, 16, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 17, 18, 6, 6, 6, 19, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 20,
|
||||
6, 6, 6, 6, 21, 22, 6, 6, 6, 6, 6, 6, 23, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 24, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 25, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 26, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
|
||||
};
|
||||
|
||||
inline constexpr std::uint32_t uppercase_stage2[] = {
|
||||
|
||||
// block 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 924, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
|
||||
208, 209, 210, 211, 212, 213, 214, 0, 216, 217, 218, 219, 220, 221, 222, 376,
|
||||
|
||||
|
||||
// block 1
|
||||
0, 256, 0, 258, 0, 260, 0, 262, 0, 264, 0, 266, 0, 268, 0, 270,
|
||||
0, 272, 0, 274, 0, 276, 0, 278, 0, 280, 0, 282, 0, 284, 0, 286,
|
||||
0, 288, 0, 290, 0, 292, 0, 294, 0, 296, 0, 298, 0, 300, 0, 302,
|
||||
0, 73, 0, 306, 0, 308, 0, 310, 0, 0, 313, 0, 315, 0, 317, 0,
|
||||
319, 0, 321, 0, 323, 0, 325, 0, 327, 0, 0, 330, 0, 332, 0, 334,
|
||||
0, 336, 0, 338, 0, 340, 0, 342, 0, 344, 0, 346, 0, 348, 0, 350,
|
||||
0, 352, 0, 354, 0, 356, 0, 358, 0, 360, 0, 362, 0, 364, 0, 366,
|
||||
0, 368, 0, 370, 0, 372, 0, 374, 0, 0, 377, 0, 379, 0, 381, 83,
|
||||
579, 0, 0, 386, 0, 388, 0, 0, 391, 0, 0, 0, 395, 0, 0, 0,
|
||||
0, 0, 401, 0, 0, 502, 0, 0, 0, 408, 573, 0, 0, 0, 544, 0,
|
||||
0, 416, 0, 418, 0, 420, 0, 0, 423, 0, 0, 0, 0, 428, 0, 0,
|
||||
431, 0, 0, 0, 435, 0, 437, 0, 0, 440, 0, 0, 0, 444, 0, 503,
|
||||
0, 0, 0, 0, 0, 452, 452, 0, 455, 455, 0, 458, 458, 0, 461, 0,
|
||||
463, 0, 465, 0, 467, 0, 469, 0, 471, 0, 473, 0, 475, 398, 0, 478,
|
||||
0, 480, 0, 482, 0, 484, 0, 486, 0, 488, 0, 490, 0, 492, 0, 494,
|
||||
0, 0, 497, 497, 0, 500, 0, 0, 0, 504, 0, 506, 0, 508, 0, 510,
|
||||
|
||||
|
||||
// block 2
|
||||
0, 512, 0, 514, 0, 516, 0, 518, 0, 520, 0, 522, 0, 524, 0, 526,
|
||||
0, 528, 0, 530, 0, 532, 0, 534, 0, 536, 0, 538, 0, 540, 0, 542,
|
||||
0, 0, 0, 546, 0, 548, 0, 550, 0, 552, 0, 554, 0, 556, 0, 558,
|
||||
0, 560, 0, 562, 0, 0, 0, 0, 0, 0, 0, 0, 571, 0, 0, 11390,
|
||||
11391, 0, 577, 0, 0, 0, 0, 582, 0, 584, 0, 586, 0, 588, 0, 590,
|
||||
11375, 11373, 11376, 385, 390, 0, 393, 394, 0, 399, 0, 400, 42923, 0, 0, 0,
|
||||
403, 42924, 0, 404, 0, 42893, 42922, 0, 407, 406, 42926, 11362, 42925, 0, 0, 412,
|
||||
0, 11374, 413, 0, 0, 415, 0, 0, 0, 0, 0, 0, 0, 11364, 0, 0,
|
||||
422, 0, 42949, 425, 0, 0, 0, 42929, 430, 580, 433, 434, 581, 0, 0, 0,
|
||||
0, 0, 439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42930, 42928, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 3
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 921, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 880, 0, 882, 0, 0, 0, 886, 0, 0, 0, 1021, 1022, 1023, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 902, 904, 905, 906,
|
||||
0, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927,
|
||||
928, 929, 931, 931, 932, 933, 934, 935, 936, 937, 938, 939, 908, 910, 911, 0,
|
||||
914, 920, 0, 0, 0, 934, 928, 975, 0, 984, 0, 986, 0, 988, 0, 990,
|
||||
0, 992, 0, 994, 0, 996, 0, 998, 0, 1000, 0, 1002, 0, 1004, 0, 1006,
|
||||
922, 929, 1017, 895, 0, 917, 0, 0, 1015, 0, 0, 1018, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 4
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055,
|
||||
1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071,
|
||||
1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039,
|
||||
0, 1120, 0, 1122, 0, 1124, 0, 1126, 0, 1128, 0, 1130, 0, 1132, 0, 1134,
|
||||
0, 1136, 0, 1138, 0, 1140, 0, 1142, 0, 1144, 0, 1146, 0, 1148, 0, 1150,
|
||||
0, 1152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1162, 0, 1164, 0, 1166,
|
||||
0, 1168, 0, 1170, 0, 1172, 0, 1174, 0, 1176, 0, 1178, 0, 1180, 0, 1182,
|
||||
0, 1184, 0, 1186, 0, 1188, 0, 1190, 0, 1192, 0, 1194, 0, 1196, 0, 1198,
|
||||
0, 1200, 0, 1202, 0, 1204, 0, 1206, 0, 1208, 0, 1210, 0, 1212, 0, 1214,
|
||||
0, 0, 1217, 0, 1219, 0, 1221, 0, 1223, 0, 1225, 0, 1227, 0, 1229, 1216,
|
||||
0, 1232, 0, 1234, 0, 1236, 0, 1238, 0, 1240, 0, 1242, 0, 1244, 0, 1246,
|
||||
0, 1248, 0, 1250, 0, 1252, 0, 1254, 0, 1256, 0, 1258, 0, 1260, 0, 1262,
|
||||
0, 1264, 0, 1266, 0, 1268, 0, 1270, 0, 1272, 0, 1274, 0, 1276, 0, 1278,
|
||||
|
||||
|
||||
// block 5
|
||||
0, 1280, 0, 1282, 0, 1284, 0, 1286, 0, 1288, 0, 1290, 0, 1292, 0, 1294,
|
||||
0, 1296, 0, 1298, 0, 1300, 0, 1302, 0, 1304, 0, 1306, 0, 1308, 0, 1310,
|
||||
0, 1312, 0, 1314, 0, 1316, 0, 1318, 0, 1320, 0, 1322, 0, 1324, 0, 1326,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343,
|
||||
1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359,
|
||||
1360, 1361, 1362, 1363, 1364, 1365, 1366, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 6
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 7
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
7312, 7313, 7314, 7315, 7316, 7317, 7318, 7319, 7320, 7321, 7322, 7323, 7324, 7325, 7326, 7327,
|
||||
7328, 7329, 7330, 7331, 7332, 7333, 7334, 7335, 7336, 7337, 7338, 7339, 7340, 7341, 7342, 7343,
|
||||
7344, 7345, 7346, 7347, 7348, 7349, 7350, 7351, 7352, 7353, 7354, 0, 0, 7357, 7358, 7359,
|
||||
|
||||
|
||||
// block 8
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 5104, 5105, 5106, 5107, 5108, 5109, 0, 0,
|
||||
|
||||
|
||||
// block 9
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1042, 1044, 1054, 1057, 1058, 1058, 1066, 1122, 42570, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 10
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 42877, 0, 0, 0, 11363, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42950, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 11
|
||||
0, 7680, 0, 7682, 0, 7684, 0, 7686, 0, 7688, 0, 7690, 0, 7692, 0, 7694,
|
||||
0, 7696, 0, 7698, 0, 7700, 0, 7702, 0, 7704, 0, 7706, 0, 7708, 0, 7710,
|
||||
0, 7712, 0, 7714, 0, 7716, 0, 7718, 0, 7720, 0, 7722, 0, 7724, 0, 7726,
|
||||
0, 7728, 0, 7730, 0, 7732, 0, 7734, 0, 7736, 0, 7738, 0, 7740, 0, 7742,
|
||||
0, 7744, 0, 7746, 0, 7748, 0, 7750, 0, 7752, 0, 7754, 0, 7756, 0, 7758,
|
||||
0, 7760, 0, 7762, 0, 7764, 0, 7766, 0, 7768, 0, 7770, 0, 7772, 0, 7774,
|
||||
0, 7776, 0, 7778, 0, 7780, 0, 7782, 0, 7784, 0, 7786, 0, 7788, 0, 7790,
|
||||
0, 7792, 0, 7794, 0, 7796, 0, 7798, 0, 7800, 0, 7802, 0, 7804, 0, 7806,
|
||||
0, 7808, 0, 7810, 0, 7812, 0, 7814, 0, 7816, 0, 7818, 0, 7820, 0, 7822,
|
||||
0, 7824, 0, 7826, 0, 7828, 0, 0, 0, 0, 0, 7776, 0, 0, 0, 0,
|
||||
0, 7840, 0, 7842, 0, 7844, 0, 7846, 0, 7848, 0, 7850, 0, 7852, 0, 7854,
|
||||
0, 7856, 0, 7858, 0, 7860, 0, 7862, 0, 7864, 0, 7866, 0, 7868, 0, 7870,
|
||||
0, 7872, 0, 7874, 0, 7876, 0, 7878, 0, 7880, 0, 7882, 0, 7884, 0, 7886,
|
||||
0, 7888, 0, 7890, 0, 7892, 0, 7894, 0, 7896, 0, 7898, 0, 7900, 0, 7902,
|
||||
0, 7904, 0, 7906, 0, 7908, 0, 7910, 0, 7912, 0, 7914, 0, 7916, 0, 7918,
|
||||
0, 7920, 0, 7922, 0, 7924, 0, 7926, 0, 7928, 0, 7930, 0, 7932, 0, 7934,
|
||||
|
||||
|
||||
// block 12
|
||||
7944, 7945, 7946, 7947, 7948, 7949, 7950, 7951, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
7960, 7961, 7962, 7963, 7964, 7965, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
7976, 7977, 7978, 7979, 7980, 7981, 7982, 7983, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
7992, 7993, 7994, 7995, 7996, 7997, 7998, 7999, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8008, 8009, 8010, 8011, 8012, 8013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 8025, 0, 8027, 0, 8029, 0, 8031, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8040, 8041, 8042, 8043, 8044, 8045, 8046, 8047, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8122, 8123, 8136, 8137, 8138, 8139, 8154, 8155, 8184, 8185, 8170, 8171, 8186, 8187, 0, 0,
|
||||
8072, 8073, 8074, 8075, 8076, 8077, 8078, 8079, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8088, 8089, 8090, 8091, 8092, 8093, 8094, 8095, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8120, 8121, 0, 8124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 921, 0,
|
||||
0, 0, 0, 8140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8152, 8153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8168, 8169, 0, 0, 0, 8172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 8188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 13
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8498, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8544, 8545, 8546, 8547, 8548, 8549, 8550, 8551, 8552, 8553, 8554, 8555, 8556, 8557, 8558, 8559,
|
||||
0, 0, 0, 0, 8579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 14
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9398, 9399, 9400, 9401, 9402, 9403, 9404, 9405, 9406, 9407, 9408, 9409, 9410, 9411, 9412, 9413,
|
||||
9414, 9415, 9416, 9417, 9418, 9419, 9420, 9421, 9422, 9423, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 15
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
11264, 11265, 11266, 11267, 11268, 11269, 11270, 11271, 11272, 11273, 11274, 11275, 11276, 11277, 11278, 11279,
|
||||
11280, 11281, 11282, 11283, 11284, 11285, 11286, 11287, 11288, 11289, 11290, 11291, 11292, 11293, 11294, 11295,
|
||||
11296, 11297, 11298, 11299, 11300, 11301, 11302, 11303, 11304, 11305, 11306, 11307, 11308, 11309, 11310, 11311,
|
||||
0, 11360, 0, 0, 0, 570, 574, 0, 11367, 0, 11369, 0, 11371, 0, 0, 0,
|
||||
0, 0, 0, 11378, 0, 0, 11381, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 11392, 0, 11394, 0, 11396, 0, 11398, 0, 11400, 0, 11402, 0, 11404, 0, 11406,
|
||||
0, 11408, 0, 11410, 0, 11412, 0, 11414, 0, 11416, 0, 11418, 0, 11420, 0, 11422,
|
||||
0, 11424, 0, 11426, 0, 11428, 0, 11430, 0, 11432, 0, 11434, 0, 11436, 0, 11438,
|
||||
0, 11440, 0, 11442, 0, 11444, 0, 11446, 0, 11448, 0, 11450, 0, 11452, 0, 11454,
|
||||
0, 11456, 0, 11458, 0, 11460, 0, 11462, 0, 11464, 0, 11466, 0, 11468, 0, 11470,
|
||||
0, 11472, 0, 11474, 0, 11476, 0, 11478, 0, 11480, 0, 11482, 0, 11484, 0, 11486,
|
||||
0, 11488, 0, 11490, 0, 0, 0, 0, 0, 0, 0, 0, 11499, 0, 11501, 0,
|
||||
0, 0, 0, 11506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 16
|
||||
4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271,
|
||||
4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287,
|
||||
4288, 4289, 4290, 4291, 4292, 4293, 0, 4295, 0, 0, 0, 0, 0, 4301, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 17
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 42560, 0, 42562, 0, 42564, 0, 42566, 0, 42568, 0, 42570, 0, 42572, 0, 42574,
|
||||
0, 42576, 0, 42578, 0, 42580, 0, 42582, 0, 42584, 0, 42586, 0, 42588, 0, 42590,
|
||||
0, 42592, 0, 42594, 0, 42596, 0, 42598, 0, 42600, 0, 42602, 0, 42604, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 42624, 0, 42626, 0, 42628, 0, 42630, 0, 42632, 0, 42634, 0, 42636, 0, 42638,
|
||||
0, 42640, 0, 42642, 0, 42644, 0, 42646, 0, 42648, 0, 42650, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 18
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 42786, 0, 42788, 0, 42790, 0, 42792, 0, 42794, 0, 42796, 0, 42798,
|
||||
0, 0, 0, 42802, 0, 42804, 0, 42806, 0, 42808, 0, 42810, 0, 42812, 0, 42814,
|
||||
0, 42816, 0, 42818, 0, 42820, 0, 42822, 0, 42824, 0, 42826, 0, 42828, 0, 42830,
|
||||
0, 42832, 0, 42834, 0, 42836, 0, 42838, 0, 42840, 0, 42842, 0, 42844, 0, 42846,
|
||||
0, 42848, 0, 42850, 0, 42852, 0, 42854, 0, 42856, 0, 42858, 0, 42860, 0, 42862,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42873, 0, 42875, 0, 0, 42878,
|
||||
0, 42880, 0, 42882, 0, 42884, 0, 42886, 0, 0, 0, 0, 42891, 0, 0, 0,
|
||||
0, 42896, 0, 42898, 42948, 0, 0, 42902, 0, 42904, 0, 42906, 0, 42908, 0, 42910,
|
||||
0, 42912, 0, 42914, 0, 42916, 0, 42918, 0, 42920, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 42932, 0, 42934, 0, 42936, 0, 42938, 0, 42940, 0, 42942,
|
||||
0, 42944, 0, 42946, 0, 0, 0, 0, 42951, 0, 42953, 0, 0, 0, 0, 0,
|
||||
0, 42960, 0, 0, 0, 0, 0, 42966, 0, 42968, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 42997, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 19
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 42931, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039,
|
||||
5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055,
|
||||
5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071,
|
||||
5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087,
|
||||
5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 20
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 65313, 65314, 65315, 65316, 65317, 65318, 65319, 65320, 65321, 65322, 65323, 65324, 65325, 65326, 65327,
|
||||
65328, 65329, 65330, 65331, 65332, 65333, 65334, 65335, 65336, 65337, 65338, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 21
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 66560, 66561, 66562, 66563, 66564, 66565, 66566, 66567,
|
||||
66568, 66569, 66570, 66571, 66572, 66573, 66574, 66575, 66576, 66577, 66578, 66579, 66580, 66581, 66582, 66583,
|
||||
66584, 66585, 66586, 66587, 66588, 66589, 66590, 66591, 66592, 66593, 66594, 66595, 66596, 66597, 66598, 66599,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 66736, 66737, 66738, 66739, 66740, 66741, 66742, 66743,
|
||||
66744, 66745, 66746, 66747, 66748, 66749, 66750, 66751, 66752, 66753, 66754, 66755, 66756, 66757, 66758, 66759,
|
||||
66760, 66761, 66762, 66763, 66764, 66765, 66766, 66767, 66768, 66769, 66770, 66771, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 22
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 66928, 66929, 66930, 66931, 66932, 66933, 66934, 66935, 66936,
|
||||
66937, 66938, 0, 66940, 66941, 66942, 66943, 66944, 66945, 66946, 66947, 66948, 66949, 66950, 66951, 66952,
|
||||
66953, 66954, 0, 66956, 66957, 66958, 66959, 66960, 66961, 66962, 0, 66964, 66965, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 23
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
68736, 68737, 68738, 68739, 68740, 68741, 68742, 68743, 68744, 68745, 68746, 68747, 68748, 68749, 68750, 68751,
|
||||
68752, 68753, 68754, 68755, 68756, 68757, 68758, 68759, 68760, 68761, 68762, 68763, 68764, 68765, 68766, 68767,
|
||||
68768, 68769, 68770, 68771, 68772, 68773, 68774, 68775, 68776, 68777, 68778, 68779, 68780, 68781, 68782, 68783,
|
||||
68784, 68785, 68786, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 24
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
71840, 71841, 71842, 71843, 71844, 71845, 71846, 71847, 71848, 71849, 71850, 71851, 71852, 71853, 71854, 71855,
|
||||
71856, 71857, 71858, 71859, 71860, 71861, 71862, 71863, 71864, 71865, 71866, 71867, 71868, 71869, 71870, 71871,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 25
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
93760, 93761, 93762, 93763, 93764, 93765, 93766, 93767, 93768, 93769, 93770, 93771, 93772, 93773, 93774, 93775,
|
||||
93776, 93777, 93778, 93779, 93780, 93781, 93782, 93783, 93784, 93785, 93786, 93787, 93788, 93789, 93790, 93791,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
|
||||
// block 26
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 125184, 125185, 125186, 125187, 125188, 125189, 125190, 125191, 125192, 125193, 125194, 125195, 125196, 125197,
|
||||
125198, 125199, 125200, 125201, 125202, 125203, 125204, 125205, 125206, 125207, 125208, 125209, 125210, 125211, 125212, 125213,
|
||||
125214, 125215, 125216, 125217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
[[nodiscard]] constexpr std::uint32_t uppercase_lookup(std::uint32_t ch) noexcept
|
||||
{
|
||||
std::uint32_t block_offset = uppercase_stage1[ch / 256] * 256;
|
||||
return uppercase_stage2[block_offset + ch % 256];
|
||||
}
|
||||
|
||||
} // boost::spirit::x3::unicode::detail
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -10,243 +9,102 @@
|
||||
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
|
||||
#include <boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp>
|
||||
#include <boost/spirit/home/x3/core/call.hpp>
|
||||
#include <boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp>
|
||||
#include <boost/range/iterator_range_core.hpp>
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
|
||||
# pragma message("Use of `boost::iterator_range` is deprecated in X3. #define BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE")
|
||||
# include <boost/range/iterator_range_core.hpp>
|
||||
#endif
|
||||
|
||||
#include <ranges>
|
||||
#include <iterator>
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
struct raw_attribute_type; // TODO: move this to detail
|
||||
struct raw_attribute_type;
|
||||
struct parse_pass_context_tag;
|
||||
|
||||
// Ideally we should have a context-agnostic concept that can be used
|
||||
// like `X3ActionFunctor<F>`, but we technically can't.
|
||||
//
|
||||
// In order to check `std::invocable`, we need to know the actual context
|
||||
// type passed to the `.parse(...)` function but it is unknown until
|
||||
// runtime.
|
||||
//
|
||||
// Even if we make up the most trivial context type (i.e. `unused_type`),
|
||||
// such concept will be useless because a user-provided functor always
|
||||
// operates on user-specific precondition that assumes the context
|
||||
// holds exact specific type provided to the entry point (`x3::parse`).
|
||||
template <typename Context>
|
||||
inline bool& _pass(Context const& context)
|
||||
{
|
||||
return x3::get<parse_pass_context_tag>(context);
|
||||
}
|
||||
|
||||
template <typename Subject, typename Action>
|
||||
struct action : unary_parser<Subject, action<Subject, Action>>
|
||||
{
|
||||
static_assert(
|
||||
!std::is_reference_v<Action>,
|
||||
"Reference type is disallowed for semantic action functor to prevent dangling reference"
|
||||
);
|
||||
typedef unary_parser<Subject, action<Subject, Action>> base_type;
|
||||
static bool const is_pass_through_unary = true;
|
||||
static bool const has_action = true;
|
||||
|
||||
using base_type = unary_parser<Subject, action<Subject, Action>>;
|
||||
static constexpr bool is_pass_through_unary = true;
|
||||
static constexpr bool has_action = true;
|
||||
constexpr action(Subject const& subject, Action f)
|
||||
: base_type(subject), f(f) {}
|
||||
|
||||
Action f;
|
||||
|
||||
template <typename SubjectT, typename ActionT>
|
||||
requires std::is_constructible_v<base_type, SubjectT> && std::is_constructible_v<Action, ActionT>
|
||||
constexpr action(SubjectT&& subject, ActionT&& f)
|
||||
noexcept(std::is_nothrow_constructible_v<base_type, SubjectT> && std::is_nothrow_constructible_v<Action, ActionT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
, f(std::forward<ActionT>(f))
|
||||
template <typename Iterator, typename Context, typename RuleContext, typename Attribute>
|
||||
bool call_action(
|
||||
Iterator& first, Iterator const& last
|
||||
, Context const& context, RuleContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
}
|
||||
|
||||
// attr==unused, action wants attribute
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It& first, Se const& last, Context const& context, RContext& rcontext, unused_type
|
||||
) const noexcept(
|
||||
std::is_nothrow_default_constructible_v<traits::attribute_of_t<action<Subject, Action>, Context>> &&
|
||||
noexcept(this->parse_main(first, last, context, rcontext, std::declval<traits::attribute_of_t<action<Subject, Action>, Context>&>()))
|
||||
)
|
||||
{
|
||||
using attribute_type = traits::attribute_of_t<action<Subject, Action>, Context>;
|
||||
|
||||
// Synthesize the attribute since one is not supplied
|
||||
attribute_type attribute; // default-initialize
|
||||
return this->parse_main(first, last, context, rcontext, attribute);
|
||||
}
|
||||
|
||||
// Catch-all overload for non-unused_type attribute
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr
|
||||
) const noexcept(noexcept(this->parse_main(first, last, context, rcontext, attr)))
|
||||
{
|
||||
return this->parse_main(first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
private:
|
||||
// Compose attr(where(val(pass(context))))
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
using composed_context_t = x3::context<
|
||||
attr_context_tag,
|
||||
Attribute,
|
||||
x3::context<
|
||||
where_context_tag,
|
||||
#ifdef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
|
||||
std::ranges::subrange<It, Se> const,
|
||||
#else
|
||||
boost::iterator_range<It> const,
|
||||
#endif
|
||||
x3::context<
|
||||
rule_val_context_tag,
|
||||
RContext,
|
||||
x3::context<
|
||||
parse_pass_context_tag,
|
||||
bool,
|
||||
Context
|
||||
>
|
||||
>
|
||||
>
|
||||
>;
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires std::invocable<Action const&, composed_context_t<It, Se, Context, RContext, Attribute> const&>
|
||||
[[nodiscard]] constexpr bool
|
||||
call_action(
|
||||
It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) const noexcept(false) // construction of `subrange` is never noexcept as per the standard
|
||||
{
|
||||
#ifdef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
|
||||
using where_range_t = std::ranges::subrange<It, Se>;
|
||||
#else
|
||||
using where_range_t = boost::iterator_range<It>;
|
||||
#endif
|
||||
|
||||
static_assert(
|
||||
std::is_void_v<std::invoke_result_t<Action const&, composed_context_t<It, Se, Context, RContext, Attribute> const&>>,
|
||||
"Semantic action should not return value. Check your function signature."
|
||||
);
|
||||
|
||||
bool pass = true;
|
||||
auto const pass_context = x3::make_context<parse_pass_context_tag>(pass, context);
|
||||
|
||||
auto const val_context = x3::make_context<rule_val_context_tag>(rcontext, pass_context);
|
||||
|
||||
// TODO: Provide some trait to detect whether this is actually needed for
|
||||
// each semantic actions.
|
||||
//
|
||||
// Although this can be assumed to be eliminated in optimized code,
|
||||
// this still may introduce compile time overhead (and also runtime
|
||||
// overhead, as constructing `subrange` is never noexcept).
|
||||
where_range_t const where_rng(first, last);
|
||||
auto const where_context = x3::make_context<where_context_tag>(where_rng, val_context);
|
||||
|
||||
auto const attr_context = x3::make_context<attr_context_tag>(attr, where_context);
|
||||
|
||||
// Sanity check (internal check to detect implementation divergence)
|
||||
static_assert(std::same_as<
|
||||
std::remove_cvref_t<decltype(attr_context)>,
|
||||
composed_context_t<It, Se, Context, RContext, Attribute>
|
||||
>);
|
||||
|
||||
this->f(attr_context);
|
||||
auto action_context = make_context<parse_pass_context_tag>(pass, context);
|
||||
call(f, first, last, action_context, rcontext, attr);
|
||||
return pass;
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires (!std::invocable<Action const&, composed_context_t<It, Se, Context, RContext, Attribute> const&>)
|
||||
[[nodiscard]] constexpr bool
|
||||
call_action(
|
||||
It&, Se const&,
|
||||
Context const&, RContext&, Attribute&
|
||||
) const noexcept(std::is_nothrow_invocable_v<Action const&>)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RuleContext, typename Attribute>
|
||||
bool parse_main(Iterator& first, Iterator const& last
|
||||
, Context const& context, RuleContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
// Explicitly make this hard error instead of emitting "no matching overload".
|
||||
// This provides much more human-friendly errors.
|
||||
static_assert(
|
||||
std::invocable<Action const&>,
|
||||
"Neither `f(ctx)` nor `f()` is well-formed for your semantic action. "
|
||||
"Check your function signature. Note that some functors might need "
|
||||
"`const` qualifier to satisfy the constraints."
|
||||
);
|
||||
|
||||
static_assert(
|
||||
std::is_void_v<std::invoke_result_t<Action const&>>,
|
||||
"Semantic action should not return value. Check your function signature."
|
||||
);
|
||||
this->f();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse_main(
|
||||
It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr
|
||||
) const noexcept(
|
||||
std::is_copy_assignable_v<It> &&
|
||||
is_nothrow_parsable_v<Subject, It, Se, Context, RContext, Attribute> &&
|
||||
noexcept(this->call_action(first, last, context, rcontext, attr))
|
||||
)
|
||||
{
|
||||
It const saved_first = first;
|
||||
Iterator save = first;
|
||||
if (this->subject.parse(first, last, context, rcontext, attr))
|
||||
{
|
||||
if (this->call_action(first, last, context, rcontext, attr))
|
||||
{
|
||||
if (call_action(first, last, context, rcontext, attr))
|
||||
return true;
|
||||
}
|
||||
|
||||
// reset iterators if semantic action failed the match
|
||||
// retrospectively
|
||||
first = saved_first;
|
||||
first = save;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// attr==raw_attribute_type, action wants iterator_range (see raw.hpp)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse_main(
|
||||
It& first, Se const& last, Context const& context, RContext& rcontext, raw_attribute_type&
|
||||
) const noexcept(false) // construction of `subrange` is never noexcept as per the standard
|
||||
template <typename Iterator, typename Context, typename RuleContext>
|
||||
bool parse_main(Iterator& first, Iterator const& last
|
||||
, Context const& context, RuleContext& rcontext, raw_attribute_type&) const
|
||||
{
|
||||
#ifdef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
|
||||
std::ranges::subrange<It, Se> rng;
|
||||
#else
|
||||
boost::iterator_range<It> rng;
|
||||
#endif
|
||||
boost::iterator_range<Iterator> rng;
|
||||
// synthesize the attribute since one is not supplied
|
||||
return this->parse_main(first, last, context, rcontext, rng);
|
||||
return parse_main(first, last, context, rcontext, rng);
|
||||
}
|
||||
|
||||
// attr==unused, action wants attribute
|
||||
template <typename Iterator, typename Context, typename RuleContext>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RuleContext& rcontext, unused_type) const
|
||||
{
|
||||
typedef typename
|
||||
traits::attribute_of<action<Subject, Action>, Context>::type
|
||||
attribute_type;
|
||||
|
||||
// synthesize the attribute since one is not supplied
|
||||
attribute_type attribute{};
|
||||
return parse_main(first, last, context, rcontext, attribute);
|
||||
}
|
||||
|
||||
// main parse function
|
||||
template <typename Iterator, typename Context
|
||||
, typename RuleContext, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RuleContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
return parse_main(first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
Action f;
|
||||
};
|
||||
|
||||
template <X3Subject Subject, typename Action>
|
||||
[[nodiscard, deprecated(
|
||||
"Use `operator[]` instead. The symbol `/` normally means \"ordered choice\" "
|
||||
"in PEG, and is irrelevant to semantic actions. Furthermore, using C++'s "
|
||||
"`operator/` for this purpose may introduce surprising behavior when it's "
|
||||
"mixed with ordinary PEG operators, for instance, the unary `operator+`, "
|
||||
"due to precedence."
|
||||
)]]
|
||||
constexpr action<as_parser_plain_t<Subject>, std::remove_cvref_t<Action>>
|
||||
operator/(Subject&& p, Action&& f)
|
||||
noexcept(
|
||||
is_parser_nothrow_castable_v<Subject> &&
|
||||
std::is_nothrow_constructible_v<
|
||||
action<as_parser_plain_t<Subject>, std::remove_cvref_t<Action>>,
|
||||
as_parser_t<Subject>, Action
|
||||
>
|
||||
)
|
||||
template <typename P, typename Action>
|
||||
constexpr action<typename extension::as_parser<P>::value_type, Action>
|
||||
operator/(P const& p, Action f)
|
||||
{
|
||||
return { as_parser(std::forward<Subject>(p)), std::forward<Action>(f) };
|
||||
return { as_parser(p), f };
|
||||
}
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -8,38 +7,70 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_CALL_CONTEXT_MAY_26_2014_0234PM)
|
||||
#define BOOST_SPIRIT_X3_CALL_CONTEXT_MAY_26_2014_0234PM
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/is_callable.hpp>
|
||||
#include <boost/range/iterator_range_core.hpp>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
struct parse_pass_context_tag; // _pass
|
||||
struct rule_val_context_tag; // _val
|
||||
struct where_context_tag; // _where
|
||||
struct attr_context_tag; // _attr
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
struct rule_val_context_tag;
|
||||
|
||||
template <typename Context>
|
||||
[[nodiscard]] constexpr bool& _pass(Context const& context) noexcept
|
||||
{
|
||||
return x3::get<parse_pass_context_tag>(context);
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
[[nodiscard]] constexpr auto&& _val(Context const& context) noexcept
|
||||
inline decltype(auto) _val(Context const& context)
|
||||
{
|
||||
return x3::get<rule_val_context_tag>(context);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
struct where_context_tag;
|
||||
|
||||
template <typename Context>
|
||||
[[nodiscard]] constexpr auto&& _where(Context const& context) noexcept
|
||||
inline decltype(auto) _where(Context const& context)
|
||||
{
|
||||
return x3::get<where_context_tag>(context);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
struct attr_context_tag;
|
||||
|
||||
template <typename Context>
|
||||
[[nodiscard]] constexpr auto&& _attr(Context const& context) noexcept
|
||||
inline decltype(auto) _attr(Context const& context)
|
||||
{
|
||||
return x3::get<attr_context_tag>(context);
|
||||
}
|
||||
} // boost::spirit::x3
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
{
|
||||
template <typename F, typename Context>
|
||||
auto call(F f, Context const& context, mpl::true_)
|
||||
{
|
||||
return f(context);
|
||||
}
|
||||
|
||||
template <typename F, typename Context>
|
||||
auto call(F f, Context const& /* context */, mpl::false_)
|
||||
{
|
||||
return f();
|
||||
}
|
||||
}
|
||||
|
||||
template <
|
||||
typename F, typename Iterator
|
||||
, typename Context, typename RuleContext, typename Attribute>
|
||||
auto call(
|
||||
F f, Iterator& first, Iterator const& last
|
||||
, Context const& context, RuleContext& rcontext, Attribute& attr)
|
||||
{
|
||||
boost::iterator_range<Iterator> rng(first, last);
|
||||
auto val_context = make_context<rule_val_context_tag>(rcontext, context);
|
||||
auto where_context = make_context<where_context_tag>(rng, val_context);
|
||||
auto attr_context = make_context<attr_context_tag>(attr, where_context);
|
||||
return detail::call(f, attr_context, is_callable<F(decltype(attr_context) const&)>());
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CORE_CONFIG_HPP
|
||||
#define BOOST_SPIRIT_X3_CORE_CONFIG_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#if _MSC_VER
|
||||
# include <CppCoreCheck/Warnings.h>
|
||||
# pragma warning(default: CPPCORECHECK_LIFETIME_WARNINGS)
|
||||
#endif
|
||||
|
||||
// <https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/#c++20-[[no_unique_address]]>
|
||||
|
||||
#if _MSC_VER && _MSC_VER < 1929 // VS 2019 v16.9 or before
|
||||
# error "Too old MSVC version; we don't support this because it leads to ODR violation regarding the existence of [[(msvc::)no_unique_address]]"
|
||||
#endif
|
||||
|
||||
#if _MSC_VER && __INTELLISENSE__ // Memory Layout view shows wrong layout without this workaround
|
||||
# define BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS [[msvc::no_unique_address, no_unique_address]]
|
||||
|
||||
#elif _MSC_VER // normal MSVC
|
||||
# define BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
|
||||
|
||||
#else // other compilers
|
||||
# define BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS [[no_unique_address]]
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_LIFETIMEBOUND
|
||||
# if defined(__clang__)
|
||||
# define BOOST_SPIRIT_X3_LIFETIMEBOUND [[clang::lifetimebound]]
|
||||
# elif defined(_MSC_VER)
|
||||
# define BOOST_SPIRIT_X3_LIFETIMEBOUND [[msvc::lifetimebound]]
|
||||
# else
|
||||
# define BOOST_SPIRIT_X3_LIFETIMEBOUND
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -8,6 +7,8 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_PARSE_INTO_CONTAINER_JAN_15_2013_0957PM)
|
||||
#define BOOST_SPIRIT_X3_PARSE_INTO_CONTAINER_JAN_15_2013_0957PM
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/container_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/pseudo_attribute.hpp>
|
||||
@@ -15,23 +16,14 @@
|
||||
#include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/fusion/include/at_key.hpp>
|
||||
#include <boost/fusion/include/front.hpp>
|
||||
#include <boost/fusion/include/back.hpp>
|
||||
|
||||
// TODO: remove Boost.Variant usage
|
||||
#include <boost/variant/variant.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <iterator> // for std::make_move_iterator
|
||||
|
||||
#include <ranges>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
template <typename Attribute, typename Value>
|
||||
struct saver_visitor;
|
||||
@@ -41,265 +33,277 @@ namespace boost::spirit::x3::detail
|
||||
struct save_to_assoc_attr
|
||||
{
|
||||
template <typename Value, typename Attribute>
|
||||
static constexpr void call(Key const&, Value&& value, Attribute& attr)
|
||||
noexcept(noexcept(traits::move_to(std::move(value), fusion::at_key<Key>(attr))))
|
||||
static void call(const Key, Value& value, Attribute& attr)
|
||||
{
|
||||
static_assert(std::is_rvalue_reference_v<Value&&>);
|
||||
traits::move_to(std::move(value), fusion::at_key<Key>(attr));
|
||||
traits::move_to(value, fusion::at_key<Key>(attr));
|
||||
}
|
||||
};
|
||||
|
||||
// save to associative fusion container where Key
|
||||
// is variant over possible keys
|
||||
template <typename... Ts>
|
||||
struct save_to_assoc_attr<variant<Ts...>>
|
||||
template <typename ...T>
|
||||
struct save_to_assoc_attr<variant<T...> >
|
||||
{
|
||||
typedef variant<T...> variant_t;
|
||||
|
||||
template <typename Value, typename Attribute>
|
||||
static constexpr void call(variant<Ts...> const& key, Value&& value, Attribute& attr)
|
||||
static void call(const variant_t key, Value& value, Attribute& attr)
|
||||
{
|
||||
static_assert(std::is_rvalue_reference_v<Value&&>);
|
||||
boost::apply_visitor(saver_visitor<Attribute, Value>(attr, std::move(value)), key);
|
||||
apply_visitor(saver_visitor<Attribute, Value>(attr, value), key);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Attribute, typename Value>
|
||||
struct saver_visitor : boost::static_visitor<void>
|
||||
struct saver_visitor : boost::static_visitor<void>
|
||||
{
|
||||
constexpr saver_visitor(Attribute& attr, Value&& value) noexcept
|
||||
: attr(attr)
|
||||
, value(std::move(value))
|
||||
{};
|
||||
saver_visitor(Attribute& attr, Value& value)
|
||||
: attr(attr), value(value) {};
|
||||
|
||||
Attribute& attr;
|
||||
Value&& value;
|
||||
Value& value;
|
||||
|
||||
template <typename Key>
|
||||
constexpr void operator()(Key const& key) const
|
||||
noexcept(noexcept(save_to_assoc_attr<Key>::call(key, std::move(value), attr)))
|
||||
void operator()(Key) const
|
||||
{
|
||||
save_to_assoc_attr<Key>::call(key, std::move(value), attr);
|
||||
save_to_assoc_attr<Key>::call(Key(), value,attr);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Parser, typename Container, typename Context>
|
||||
struct parser_accepts_container
|
||||
: traits::is_substitute<traits::attribute_of_t<Parser, Context>, Container>
|
||||
: traits::is_substitute<
|
||||
typename traits::attribute_of<Parser, Context>::type
|
||||
, Container
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Parser, typename Container, typename Context>
|
||||
constexpr bool parser_accepts_container_v = parser_accepts_container<Parser, Container, Context>::value;
|
||||
|
||||
template <typename Parser>
|
||||
struct parse_into_container_base_impl
|
||||
{
|
||||
private:
|
||||
|
||||
// Parser has attribute (synthesize; Attribute is a container)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires (!parser_accepts_container_v<Parser, Attribute, Context>)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call_synthesize(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) // never noexcept (requires container insertion)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
static bool call_synthesize_x(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
|
||||
{
|
||||
// synthesized attribute needs to be value initialized
|
||||
using value_type = traits::container_value_t<Attribute>;
|
||||
value_type val; // default-initialize
|
||||
using value_type = typename traits::container_value<Attribute>::type;
|
||||
value_type val{};
|
||||
|
||||
static_assert(Parsable<Parser, It, Se, Context, RContext, value_type>);
|
||||
if (!parser.parse(first, last, context, rcontext, val))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// push the parsed value into our attribute
|
||||
traits::push_back(attr, std::move(val));
|
||||
traits::push_back(attr, static_cast<value_type&&>(val));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parser has attribute (synthesize; Attribute is a container)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires parser_accepts_container_v<Parser, Attribute, Context>
|
||||
[[nodiscard]] static constexpr bool
|
||||
call_synthesize(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) noexcept(is_nothrow_parsable_v<Parser, It, Se, Context, RContext, Attribute>)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
static bool call_synthesize_x(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
|
||||
{
|
||||
static_assert(Parsable<Parser, It, Se, Context, RContext, Attribute>);
|
||||
return parser.parse(first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
// Parser has attribute && it is NOT fusion sequence
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires
|
||||
traits::has_attribute_v<Parser, Context> &&
|
||||
(!fusion::traits::is_sequence<Attribute>::value)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
)
|
||||
// Parser has attribute (synthesize; Attribute is a container)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
static bool call_synthesize(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr)
|
||||
{
|
||||
// TODO: reduce call stack while keeping maintainability
|
||||
return parse_into_container_base_impl::call_synthesize(parser, first, last, context, rcontext, attr);
|
||||
typedef
|
||||
parser_accepts_container<Parser, Attribute, Context>
|
||||
parser_accepts_container;
|
||||
|
||||
return call_synthesize_x(parser, first, last, context, rcontext, attr
|
||||
, parser_accepts_container());
|
||||
}
|
||||
|
||||
// Parser has attribute && it is fusion sequence (NOT associative)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires
|
||||
traits::has_attribute_v<Parser, Context> &&
|
||||
fusion::traits::is_sequence<Attribute>::value &&
|
||||
(!fusion::traits::is_associative<Attribute>::value)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) noexcept(noexcept(parse_into_container_base_impl::call_synthesize(parser, first, last, context, rcontext, fusion::front(attr))))
|
||||
// Parser has attribute (synthesize; Attribute is a single element fusion sequence)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
static bool call_synthesize_into_fusion_seq(Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr, mpl::false_ /* is_associative */)
|
||||
{
|
||||
static_assert(traits::has_size_v<Attribute, 1>, "Expecting a single element fusion sequence");
|
||||
// TODO: reduce call stack while keeping maintainability
|
||||
return parse_into_container_base_impl::call_synthesize(parser, first, last, context, rcontext, fusion::front(attr));
|
||||
static_assert(traits::has_size<Attribute, 1>::value,
|
||||
"Expecting a single element fusion sequence");
|
||||
return call_synthesize(parser, first, last, context, rcontext,
|
||||
fusion::front(attr));
|
||||
}
|
||||
|
||||
// Parser has attribute && it is fusion sequence (associative)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires
|
||||
traits::has_attribute_v<Parser, Context> &&
|
||||
fusion::traits::is_sequence<Attribute>::value &&
|
||||
fusion::traits::is_associative<Attribute>::value
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) // never noexcept (requires container insertion)
|
||||
// Parser has attribute (synthesize; Attribute is fusion map sequence)
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
static bool call_synthesize_into_fusion_seq(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr, mpl::true_ /*is_associative*/)
|
||||
{
|
||||
using attribute_type = traits::attribute_of_t<Parser, Context>;
|
||||
static_assert(traits::has_size_v<attribute_type, 2>, "To parse directly into fusion map, parser must produce 2 element attr");
|
||||
using attribute_type = typename traits::attribute_of<Parser, Context>::type;
|
||||
static_assert(traits::has_size<attribute_type, 2>::value,
|
||||
"To parse directly into fusion map parser must produce 2 element attr");
|
||||
|
||||
attribute_type attr_; // default-initialize
|
||||
static_assert(Parsable<Parser, It, Se, Context, RContext, attribute_type>);
|
||||
// use type of first element of attribute as key
|
||||
using key = typename std::remove_reference<
|
||||
typename fusion::result_of::front<attribute_type>::type>::type;
|
||||
|
||||
attribute_type attr_;
|
||||
if (!parser.parse(first, last, context, rcontext, attr_))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use the type of first element of attribute as key
|
||||
using key = std::remove_reference_t<
|
||||
typename fusion::result_of::front<attribute_type>::type
|
||||
>;
|
||||
|
||||
save_to_assoc_attr<key>::call(std::move(fusion::front(attr_)), std::move(fusion::back(attr_)), attr);
|
||||
save_to_assoc_attr<key>::call(fusion::front(attr_), fusion::back(attr_), attr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parser has no attribute (pass unused)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires (!traits::has_attribute_v<Parser, Context>)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& /* attr */
|
||||
) noexcept(is_nothrow_parsable_v<Parser, It, Se, Context, RContext, unused_type>)
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
static bool call_synthesize_dispatch_by_seq(Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr, mpl::true_ /*is_sequence*/)
|
||||
{
|
||||
return call_synthesize_into_fusion_seq(
|
||||
parser, first, last, context, rcontext, attr
|
||||
, fusion::traits::is_associative<Attribute>());
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
static bool call_synthesize_dispatch_by_seq(Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr, mpl::false_ /*is_sequence*/)
|
||||
{
|
||||
return call_synthesize(parser, first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
// Parser has attribute (synthesize)
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
static bool call(Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr, mpl::true_)
|
||||
{
|
||||
return call_synthesize_dispatch_by_seq(parser, first, last, context, rcontext, attr
|
||||
, fusion::traits::is_sequence<Attribute>());
|
||||
}
|
||||
|
||||
// Parser has no attribute (pass unused)
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
static bool call(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& /* attr */, mpl::false_)
|
||||
{
|
||||
static_assert(Parsable<Parser, It, Se, Context, RContext, unused_type>);
|
||||
return parser.parse(first, last, context, rcontext, unused);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
static bool call(Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr)
|
||||
{
|
||||
return call(parser, first, last, context, rcontext, attr
|
||||
, mpl::bool_<traits::has_attribute<Parser, Context>::value>());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Parser, typename Context, typename RContext, typename Enable = void>
|
||||
struct parse_into_container_impl : parse_into_container_base_impl<Parser> {};
|
||||
|
||||
template <typename Parser, typename Iterator, typename Container, typename Context>
|
||||
struct parser_attr_is_substitute_for_container_value
|
||||
: traits::is_substitute<
|
||||
typename traits::pseudo_attribute<
|
||||
Context
|
||||
, typename traits::attribute_of<Parser, Context>::type
|
||||
, Iterator
|
||||
>::type
|
||||
, typename traits::container_value<Container>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Parser, typename Context, typename RContext>
|
||||
requires traits::handles_container_v<Parser, Context>
|
||||
struct parse_into_container_impl<Parser, Context, RContext>
|
||||
struct parse_into_container_impl<Parser, Context, RContext,
|
||||
typename enable_if<traits::handles_container<Parser, Context>>::type>
|
||||
{
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
static constexpr bool pass_attibute_as_is = std::disjunction_v<
|
||||
parser_accepts_container<Parser, Attribute, Context>,
|
||||
|
||||
std::negation<traits::is_substitute< // parser attribute is substitute for container value?
|
||||
traits::pseudo_attribute_t<
|
||||
Context,
|
||||
traits::attribute_of_t<Parser, Context>,
|
||||
It, Se
|
||||
>,
|
||||
traits::container_value_t<Attribute>
|
||||
>>
|
||||
>;
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
requires (!pass_attibute_as_is<It, Se, Attribute>)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) noexcept(noexcept(parse_into_container_base_impl<Parser>::call(
|
||||
parser, first, last, context, rcontext, attr
|
||||
)))
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
|
||||
{
|
||||
return parse_into_container_base_impl<Parser>::call(
|
||||
parser, first, last, context, rcontext, attr
|
||||
);
|
||||
parser, first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se>
|
||||
requires pass_attibute_as_is<It, Se, unused_type>
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, unused_type
|
||||
) noexcept(is_nothrow_parsable_v<Parser, It, Se, Context, RContext, unused_type>)
|
||||
template <typename Iterator>
|
||||
static bool call(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, unused_type attr, mpl::true_)
|
||||
{
|
||||
static_assert(Parsable<Parser, It, Se, Context, RContext, unused_type>);
|
||||
return parser.parse(first, last, context, rcontext, unused);
|
||||
return parser.parse(first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
requires pass_attibute_as_is<It, Se, Attribute>
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) // never noexcept (requires container insertion)
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
|
||||
{
|
||||
static_assert(Parsable<Parser, It, Se, Context, RContext, Attribute>);
|
||||
if (traits::is_empty(attr))
|
||||
{
|
||||
return parser.parse(first, last, context, rcontext, attr);
|
||||
}
|
||||
Attribute rest;
|
||||
bool r = parser.parse(first, last, context, rcontext, rest);
|
||||
if (r)
|
||||
traits::append(attr, std::make_move_iterator(rest.begin()),
|
||||
std::make_move_iterator(rest.end()));
|
||||
return r;
|
||||
}
|
||||
|
||||
Attribute rest; // default-initialize
|
||||
if (!parser.parse(first, last, context, rcontext, rest))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
traits::append(
|
||||
attr,
|
||||
std::make_move_iterator(std::ranges::begin(rest)),
|
||||
std::make_move_iterator(std::ranges::end(rest))
|
||||
);
|
||||
return true;
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr)
|
||||
{
|
||||
typedef parser_accepts_container<
|
||||
Parser, Attribute, Context>
|
||||
parser_accepts_container;
|
||||
|
||||
typedef parser_attr_is_substitute_for_container_value<
|
||||
Parser, Iterator, Attribute, Context>
|
||||
parser_attr_is_substitute_for_container_value;
|
||||
|
||||
typedef mpl::or_<
|
||||
parser_accepts_container
|
||||
, mpl::not_<parser_attr_is_substitute_for_container_value>>
|
||||
pass_attibute_as_is;
|
||||
|
||||
return call(parser, first, last, context, rcontext, attr,
|
||||
pass_attibute_as_is());
|
||||
}
|
||||
};
|
||||
|
||||
template <
|
||||
typename Parser, std::forward_iterator It, std::sentinel_for<It> Se,
|
||||
typename Context, typename RContext, typename Attribute
|
||||
>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse_into_container(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) noexcept(noexcept(parse_into_container_impl<Parser, Context, RContext>::call(
|
||||
parser, first, last, context, rcontext, attr
|
||||
)))
|
||||
template <typename Parser, typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse_into_container(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr)
|
||||
{
|
||||
return parse_into_container_impl<Parser, Context, RContext>::call(
|
||||
parser, first, last, context, rcontext, attr
|
||||
);
|
||||
parser, first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
} // boost::spirit::x3::detail
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2024-2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CORE_ERROR_HANDLER_TYPES_HPP
|
||||
#define BOOST_SPIRIT_X3_CORE_ERROR_HANDLER_TYPES_HPP
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
// Enum type used in `on_error`.
|
||||
enum class error_handler_result
|
||||
{
|
||||
fail,
|
||||
retry,
|
||||
accept,
|
||||
rethrow, // see BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE for alternative behaviors
|
||||
};
|
||||
|
||||
// Note for X3 developers:
|
||||
// You must at least sync the implementation of `rule_parser` and `guard`
|
||||
// when you modify the semantics of error handlers.
|
||||
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -9,173 +8,80 @@
|
||||
#define BOOST_SPIRIT_X3_PARSE_APRIL_16_2006_0442PM
|
||||
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/parse_result.hpp>
|
||||
#include <boost/spirit/home/x3/core/skip_over.hpp>
|
||||
#include <boost/iterator/iterator_concepts.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <iterator>
|
||||
#include <ranges>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, X3Parser<It, Se> Parser, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename Parser, typename Attribute>
|
||||
inline bool
|
||||
parse_main(
|
||||
It& first,
|
||||
Se last,
|
||||
Parser&& p,
|
||||
Attribute& attr
|
||||
)
|
||||
Iterator& first
|
||||
, Iterator last
|
||||
, Parser const& p
|
||||
, Attribute& attr)
|
||||
{
|
||||
static_assert(Parsable<as_parser_plain_t<Parser>, It, Se, unused_type, unused_type, Attribute>);
|
||||
return as_parser(std::forward<Parser>(p)).parse(first, last, unused, unused, attr);
|
||||
}
|
||||
// Make sure the iterator is at least a readable forward traversal iterator.
|
||||
// If you got a compilation error here, then you are using a weaker iterator
|
||||
// while calling this function, you need to supply a readable forward traversal
|
||||
// iterator instead.
|
||||
BOOST_CONCEPT_ASSERT((boost_concepts::ReadableIteratorConcept<Iterator>));
|
||||
BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversalConcept<Iterator>));
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, X3Parser<It, Se> Parser, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It& first,
|
||||
Se last,
|
||||
Parser&& p,
|
||||
Attribute& attr
|
||||
)
|
||||
{
|
||||
return x3::parse_main(first, last, std::forward<Parser>(p), attr);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, X3Parser<It, Se> Parser, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It const& first_,
|
||||
Se last,
|
||||
Parser&& p,
|
||||
Attribute& attr
|
||||
)
|
||||
{
|
||||
It first = first_;
|
||||
return x3::parse_main(first, last, std::forward<Parser>(p), attr);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, X3Parser<It, Se> Parser>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It& first,
|
||||
Se last,
|
||||
Parser&& p
|
||||
)
|
||||
{
|
||||
return x3::parse_main(first, last, std::forward<Parser>(p), unused);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, X3Parser<It, Se> Parser>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It const& first_,
|
||||
Se last,
|
||||
Parser&& p
|
||||
)
|
||||
{
|
||||
It first = first_;
|
||||
return x3::parse_main(first, last, std::forward<Parser>(p), unused);
|
||||
// If you get an error no matching function for call to 'as_parser'
|
||||
// here, then p is not a parser or there is no suitable conversion
|
||||
// from p to a parser.
|
||||
return as_parser(p).parse(first, last, unused, unused, attr);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <std::ranges::forward_range R, X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Parser, typename Attribute>
|
||||
[[nodiscard]] constexpr parse_result_for<R>
|
||||
parse_main(
|
||||
R& range,
|
||||
Parser&& p,
|
||||
Attribute& attr
|
||||
)
|
||||
{
|
||||
using It = std::ranges::iterator_t<R>;
|
||||
using Se = std::ranges::sentinel_t<R>;
|
||||
|
||||
std::optional<x3::expectation_failure<It>> expect_failure;
|
||||
auto failure_ctx = x3::make_context<expectation_failure_tag>(expect_failure);
|
||||
using Context = decltype(failure_ctx);
|
||||
|
||||
static_assert(Parsable<as_parser_plain_t<Parser>, It, Se, Context, unused_type, Attribute>);
|
||||
|
||||
It first = std::ranges::begin(range);
|
||||
Se last = std::ranges::end(range);
|
||||
bool const ok = as_parser(std::forward<Parser>(p)).parse(first, last, failure_ctx, unused, attr);
|
||||
return parse_result_for<R>{
|
||||
.ok = ok,
|
||||
.expect_failure = std::move(expect_failure),
|
||||
.remainder = {std::move(first), std::move(last)}
|
||||
};
|
||||
}
|
||||
|
||||
template <std::ranges::forward_range R, X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Parser, typename Attribute>
|
||||
constexpr void
|
||||
parse_main(
|
||||
parse_result_for<R>& res
|
||||
, R& range
|
||||
, Parser&& p
|
||||
template <typename Iterator, typename Parser, typename Attribute>
|
||||
inline bool
|
||||
parse(
|
||||
Iterator& first
|
||||
, Iterator last
|
||||
, Parser const& p
|
||||
, Attribute& attr)
|
||||
{
|
||||
using It = std::ranges::iterator_t<R>;
|
||||
using Se = std::ranges::sentinel_t<R>;
|
||||
|
||||
res.expect_failure.reset();
|
||||
auto failure_ctx = x3::make_context<expectation_failure_tag>(res.expect_failure);
|
||||
using Context = decltype(failure_ctx);
|
||||
|
||||
static_assert(Parsable<as_parser_plain_t<Parser>, It, Se, Context, unused_type, Attribute>);
|
||||
|
||||
It first = std::ranges::begin(range);
|
||||
Se last = std::ranges::end(range);
|
||||
res.ok = as_parser(std::forward<Parser>(p)).parse(first, last, failure_ctx, unused, attr);
|
||||
res.remainder = {std::move(first), std::move(last)};
|
||||
return parse_main(first, last, p, attr);
|
||||
}
|
||||
|
||||
template <std::ranges::forward_range R, X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Parser, typename Attribute>
|
||||
[[nodiscard]] constexpr parse_result_for<R>
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename Parser, typename Attribute>
|
||||
inline bool
|
||||
parse(
|
||||
R& range
|
||||
, Parser&& p
|
||||
Iterator const& first_
|
||||
, Iterator last
|
||||
, Parser const& p
|
||||
, Attribute& attr)
|
||||
{
|
||||
return x3::parse_main(range, std::forward<Parser>(p), attr);
|
||||
Iterator first = first_;
|
||||
return parse_main(first, last, p, attr);
|
||||
}
|
||||
|
||||
template <std::ranges::forward_range R, X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Parser>
|
||||
[[nodiscard]] constexpr parse_result_for<R>
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename Parser>
|
||||
inline bool
|
||||
parse(
|
||||
R& range
|
||||
, Parser&& p)
|
||||
Iterator& first
|
||||
, Iterator last
|
||||
, Parser const& p)
|
||||
{
|
||||
return x3::parse_main(range, std::forward<Parser>(p), unused);
|
||||
return parse_main(first, last, p, unused);
|
||||
}
|
||||
|
||||
template <std::ranges::forward_range R, X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Parser, typename Attribute>
|
||||
constexpr void
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename Parser>
|
||||
inline bool
|
||||
parse(
|
||||
parse_result_for<R>& res,
|
||||
R& range,
|
||||
Parser&& p,
|
||||
Attribute& attr
|
||||
)
|
||||
Iterator const& first_
|
||||
, Iterator last
|
||||
, Parser const& p)
|
||||
{
|
||||
return x3::parse_main(res, range, std::forward<Parser>(p), attr);
|
||||
}
|
||||
|
||||
template <std::ranges::forward_range R, X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Parser>
|
||||
constexpr void
|
||||
parse(
|
||||
parse_result_for<R>& res,
|
||||
R& range,
|
||||
Parser&& p
|
||||
)
|
||||
{
|
||||
return x3::parse_main(res, range, std::forward<Parser>(p), unused);
|
||||
Iterator first = first_;
|
||||
return parse_main(first, last, p, unused);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -185,306 +91,101 @@ namespace boost::spirit::x3
|
||||
dont_post_skip // inhibit post-skipping in phrase_parse()
|
||||
};
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, X3Parser<It, Se> Parser, X3Parser<It, Se> Skipper, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename Parser, typename Skipper, typename Attribute>
|
||||
inline bool
|
||||
phrase_parse_main(
|
||||
It& first,
|
||||
Se last,
|
||||
Parser&& p,
|
||||
Skipper&& s,
|
||||
Attribute& attr,
|
||||
skip_flag post_skip = skip_flag::post_skip
|
||||
)
|
||||
Iterator& first
|
||||
, Iterator last
|
||||
, Parser const& p
|
||||
, Skipper const& s
|
||||
, Attribute& attr
|
||||
, skip_flag post_skip = skip_flag::post_skip)
|
||||
{
|
||||
auto skipper_ctx = x3::make_context<skipper_tag>(as_parser(std::forward<Skipper>(s)));
|
||||
using Context = decltype(skipper_ctx);
|
||||
static_assert(Parsable<as_parser_plain_t<Parser>, It, Se, Context, unused_type, Attribute>);
|
||||
// Make sure the iterator is at least a readable forward traversal iterator.
|
||||
// If you got a compilation error here, then you are using a weaker iterator
|
||||
// while calling this function, you need to supply a readable forward traversal
|
||||
// iterator instead.
|
||||
BOOST_CONCEPT_ASSERT((boost_concepts::ReadableIteratorConcept<Iterator>));
|
||||
BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversalConcept<Iterator>));
|
||||
|
||||
static_assert(!std::is_same<Skipper, unused_type>::value,
|
||||
"Error! Skipper cannot be unused_type.");
|
||||
|
||||
bool const ok = as_parser(std::forward<Parser>(p)).parse(first, last, skipper_ctx, unused, attr);
|
||||
// If you get an error no matching function for call to 'as_parser'
|
||||
// here, for either p or s, then p or s is not a parser or there is
|
||||
// no suitable conversion from p to a parser.
|
||||
auto skipper_ctx = make_context<skipper_tag>(as_parser(s));
|
||||
bool r = as_parser(p).parse(first, last, skipper_ctx, unused, attr);
|
||||
if (post_skip == skip_flag::post_skip)
|
||||
{
|
||||
x3::skip_over(first, last, skipper_ctx);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, X3Parser<It, Se> Parser, X3Parser<It, Se> Skipper, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
phrase_parse(
|
||||
It& first,
|
||||
Se last,
|
||||
Parser&& p,
|
||||
Skipper&& s,
|
||||
Attribute& attr,
|
||||
skip_flag post_skip = skip_flag::post_skip
|
||||
)
|
||||
{
|
||||
return x3::phrase_parse_main(first, last, std::forward<Parser>(p), std::forward<Skipper>(s), attr, post_skip);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, X3Parser<It, Se> Parser, X3Parser<It, Se> Skipper, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
phrase_parse(
|
||||
It const& first_,
|
||||
Se last,
|
||||
Parser&& p,
|
||||
Skipper&& s,
|
||||
Attribute& attr,
|
||||
skip_flag post_skip = skip_flag::post_skip
|
||||
)
|
||||
{
|
||||
It first = first_;
|
||||
return x3::phrase_parse_main(first, last, std::forward<Parser>(p), std::forward<Skipper>(s), attr, post_skip);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, X3Parser<It, Se> Parser, X3Parser<It, Se> Skipper>
|
||||
[[nodiscard]] constexpr bool
|
||||
phrase_parse(
|
||||
It& first,
|
||||
Se last,
|
||||
Parser&& p,
|
||||
Skipper&& s,
|
||||
skip_flag post_skip = skip_flag::post_skip
|
||||
)
|
||||
{
|
||||
return x3::phrase_parse_main(first, last, std::forward<Parser>(p), std::forward<Skipper>(s), unused, post_skip);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, X3Parser<It, Se> Parser, X3Parser<It, Se> Skipper>
|
||||
[[nodiscard]] constexpr bool
|
||||
phrase_parse(
|
||||
It const& first_,
|
||||
Se last,
|
||||
Parser&& p,
|
||||
Skipper&& s,
|
||||
skip_flag post_skip = skip_flag::post_skip
|
||||
)
|
||||
{
|
||||
It first = first_;
|
||||
return x3::phrase_parse_main(first, last, std::forward<Parser>(p), std::forward<Skipper>(s), unused, post_skip);
|
||||
return r;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <
|
||||
std::ranges::forward_range R,
|
||||
X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Parser,
|
||||
X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Skipper,
|
||||
typename Attribute
|
||||
>
|
||||
[[nodiscard]] constexpr parse_result_for<R>
|
||||
phrase_parse_main(
|
||||
R& range,
|
||||
Parser&& p,
|
||||
Skipper&& s,
|
||||
Attribute& attr,
|
||||
skip_flag post_skip = skip_flag::post_skip
|
||||
)
|
||||
{
|
||||
using It = std::ranges::iterator_t<R>;
|
||||
using Se = std::ranges::sentinel_t<R>;
|
||||
|
||||
auto skipper_ctx = x3::make_context<skipper_tag>(as_parser(std::forward<Skipper>(s)));
|
||||
|
||||
std::optional<x3::expectation_failure<It>> expect_failure;
|
||||
auto ctx = x3::make_context<expectation_failure_tag>(expect_failure, skipper_ctx);
|
||||
|
||||
using Context = decltype(ctx);
|
||||
static_assert(Parsable<as_parser_plain_t<Parser>, It, Se, Context, unused_type, Attribute>);
|
||||
|
||||
It first = std::ranges::begin(range);
|
||||
Se last = std::ranges::end(range);
|
||||
bool ok = as_parser(std::forward<Parser>(p)).parse(first, last, ctx, unused, attr);
|
||||
if (post_skip == skip_flag::post_skip)
|
||||
{
|
||||
x3::skip_over(first, last, ctx);
|
||||
if (expect_failure) ok = false;
|
||||
}
|
||||
return parse_result_for<R>{
|
||||
.ok = ok,
|
||||
.expect_failure = std::move(expect_failure),
|
||||
.remainder = {std::move(first), std::move(last)}
|
||||
};
|
||||
}
|
||||
|
||||
template <
|
||||
std::ranges::forward_range R,
|
||||
X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Parser,
|
||||
X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Skipper,
|
||||
typename Attribute
|
||||
>
|
||||
constexpr void
|
||||
phrase_parse_main(
|
||||
parse_result_for<R>& res,
|
||||
R& range,
|
||||
Parser&& p,
|
||||
Skipper&& s,
|
||||
Attribute& attr,
|
||||
skip_flag post_skip = skip_flag::post_skip
|
||||
)
|
||||
{
|
||||
using It = std::ranges::iterator_t<R>;
|
||||
using Se = std::ranges::sentinel_t<R>;
|
||||
|
||||
auto skipper_ctx = x3::make_context<skipper_tag>(as_parser(std::forward<Skipper>(s)));
|
||||
|
||||
res.expect_failure.reset();
|
||||
auto ctx = x3::make_context<expectation_failure_tag>(res.expect_failure, skipper_ctx);
|
||||
|
||||
using Context = decltype(ctx);
|
||||
static_assert(Parsable<as_parser_plain_t<Parser>, It, Se, Context, unused_type, Attribute>);
|
||||
|
||||
It first = std::ranges::begin(range);
|
||||
Se last = std::ranges::end(range);
|
||||
res.ok = as_parser(std::forward<Parser>(p)).parse(first, last, ctx, unused, attr);
|
||||
if (post_skip == skip_flag::post_skip)
|
||||
{
|
||||
x3::skip_over(first, last, ctx);
|
||||
if (res.expect_failure) res.ok = false;
|
||||
}
|
||||
res.remainder = {std::move(first), std::move(last)};
|
||||
}
|
||||
|
||||
template <
|
||||
std::ranges::forward_range R,
|
||||
X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Parser,
|
||||
X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Skipper,
|
||||
typename Attribute
|
||||
>
|
||||
[[nodiscard]] constexpr parse_result_for<R>
|
||||
template <typename Iterator, typename Parser, typename Skipper, typename Attribute>
|
||||
inline bool
|
||||
phrase_parse(
|
||||
R& range,
|
||||
Parser&& p,
|
||||
Skipper&& s,
|
||||
Attribute& attr,
|
||||
skip_flag post_skip = skip_flag::post_skip
|
||||
)
|
||||
Iterator& first
|
||||
, Iterator last
|
||||
, Parser const& p
|
||||
, Skipper const& s
|
||||
, Attribute& attr
|
||||
, skip_flag post_skip = skip_flag::post_skip)
|
||||
{
|
||||
return x3::phrase_parse_main(range, std::forward<Parser>(p), std::forward<Skipper>(s), attr, post_skip);
|
||||
return phrase_parse_main(first, last, p, s, attr, post_skip);
|
||||
}
|
||||
|
||||
template <
|
||||
std::ranges::forward_range R,
|
||||
X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Parser,
|
||||
X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Skipper,
|
||||
typename Attribute
|
||||
>
|
||||
[[nodiscard]] constexpr parse_result_for<R>
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename Parser, typename Skipper, typename Attribute>
|
||||
inline bool
|
||||
phrase_parse(
|
||||
R& range,
|
||||
Parser&& p,
|
||||
Skipper&& s,
|
||||
skip_flag post_skip = skip_flag::post_skip
|
||||
)
|
||||
Iterator const& first_
|
||||
, Iterator last
|
||||
, Parser const& p
|
||||
, Skipper const& s
|
||||
, Attribute& attr
|
||||
, skip_flag post_skip = skip_flag::post_skip)
|
||||
{
|
||||
return x3::phrase_parse_main(range, std::forward<Parser>(p), std::forward<Skipper>(s), unused, post_skip);
|
||||
Iterator first = first_;
|
||||
return phrase_parse_main(first, last, p, s, attr, post_skip);
|
||||
}
|
||||
|
||||
template <
|
||||
std::ranges::forward_range R,
|
||||
X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Parser,
|
||||
X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Skipper,
|
||||
typename Attribute
|
||||
>
|
||||
constexpr void
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename Parser, typename Skipper>
|
||||
inline bool
|
||||
phrase_parse(
|
||||
parse_result_for<R>& res,
|
||||
R& range,
|
||||
Parser&& p,
|
||||
Skipper&& s,
|
||||
Attribute& attr,
|
||||
skip_flag post_skip = skip_flag::post_skip
|
||||
)
|
||||
Iterator& first
|
||||
, Iterator last
|
||||
, Parser const& p
|
||||
, Skipper const& s
|
||||
, skip_flag post_skip = skip_flag::post_skip)
|
||||
{
|
||||
return x3::phrase_parse_main(res, range, std::forward<Parser>(p), std::forward<Skipper>(s), attr, post_skip);
|
||||
return phrase_parse_main(first, last, p, s, unused, post_skip);
|
||||
}
|
||||
|
||||
template <
|
||||
std::ranges::forward_range R,
|
||||
X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Parser,
|
||||
X3Parser<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>> Skipper,
|
||||
typename Attribute
|
||||
>
|
||||
constexpr void
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename Parser, typename Skipper>
|
||||
inline bool
|
||||
phrase_parse(
|
||||
parse_result_for<R>& res,
|
||||
R& range,
|
||||
Parser&& p,
|
||||
Skipper&& s,
|
||||
skip_flag post_skip = skip_flag::post_skip
|
||||
)
|
||||
Iterator const& first_
|
||||
, Iterator last
|
||||
, Parser const& p
|
||||
, Skipper const& s
|
||||
, skip_flag post_skip = skip_flag::post_skip)
|
||||
{
|
||||
return x3::phrase_parse_main(res, range, std::forward<Parser>(p), std::forward<Skipper>(s), unused, post_skip);
|
||||
Iterator first = first_;
|
||||
return phrase_parse_main(first, last, p, s, unused, post_skip);
|
||||
}
|
||||
|
||||
|
||||
template <typename Skipper, typename ItOrRange, typename Se = void>
|
||||
struct phrase_parse_context;
|
||||
|
||||
template <typename Skipper, typename ItOrRange, typename Se = void>
|
||||
using phrase_parse_context_t = typename phrase_parse_context<Skipper, ItOrRange, Se>::type;
|
||||
|
||||
template <typename Skipper, std::forward_iterator It, class Se>
|
||||
struct phrase_parse_context<Skipper, It, Se>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Skipper>
|
||||
struct phrase_parse_context
|
||||
{
|
||||
using iterator_t = It;
|
||||
using sentinel_t = std::conditional_t<std::is_void_v<Se>, It, Se>;
|
||||
static_assert(X3Parser<Skipper, It, sentinel_t>);
|
||||
|
||||
using skipper_ctx_type = decltype(x3::make_context<skipper_tag>(as_parser(std::declval<Skipper const&>())));
|
||||
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
using type = skipper_ctx_type;
|
||||
#else
|
||||
using type = decltype(x3::make_context<expectation_failure_tag>(
|
||||
std::declval<std::optional<expectation_failure<It>>&>(),
|
||||
std::declval<skipper_ctx_type const&>()
|
||||
));
|
||||
#endif
|
||||
typedef decltype(
|
||||
make_context<skipper_tag>(as_parser(std::declval<Skipper>())))
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Skipper, std::ranges::forward_range R>
|
||||
struct phrase_parse_context<Skipper, R>
|
||||
{
|
||||
using iterator_t = std::ranges::iterator_t<R>;
|
||||
using sentinel_t = std::ranges::sentinel_t<R>;
|
||||
static_assert(X3Parser<Skipper, iterator_t, sentinel_t>);
|
||||
|
||||
using skipper_ctx_type = decltype(x3::make_context<skipper_tag>(as_parser(std::declval<Skipper const&>())));
|
||||
|
||||
using type = decltype(x3::make_context<expectation_failure_tag>(
|
||||
std::declval<std::optional<expectation_failure<iterator_t>>&>(),
|
||||
std::declval<skipper_ctx_type const&>()
|
||||
));
|
||||
};
|
||||
|
||||
|
||||
template <typename ItOrRange, typename Se = void>
|
||||
struct parse_context;
|
||||
|
||||
template <typename ItOrRange, typename Se = void>
|
||||
using parse_context_t = typename parse_context<ItOrRange, Se>::type;
|
||||
|
||||
template <std::forward_iterator It>
|
||||
struct parse_context<It>
|
||||
{
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
using type = unused_type;
|
||||
#else
|
||||
using type = decltype(x3::make_context<expectation_failure_tag>(
|
||||
std::declval<std::optional<expectation_failure<It>>&>()
|
||||
));
|
||||
#endif
|
||||
};
|
||||
|
||||
template <std::ranges::forward_range R>
|
||||
struct parse_context<R>
|
||||
{
|
||||
using type = decltype(x3::make_context<expectation_failure_tag>(
|
||||
std::declval<std::optional<expectation_failure<std::ranges::iterator_t<R>>>&>()
|
||||
));
|
||||
};
|
||||
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_CORE_PARSE_RESULT_HPP
|
||||
#define BOOST_SPIRIT_X3_CORE_PARSE_RESULT_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <iterator>
|
||||
#include <ranges>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se = It>
|
||||
struct parse_result
|
||||
{
|
||||
static_assert(
|
||||
BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE == 0,
|
||||
"Using this class requires `#define BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE 0`"
|
||||
);
|
||||
|
||||
using iterator_type = It;
|
||||
using sentinel_type = Se;
|
||||
|
||||
// Strictly equivalent to the logical conjunction of the return
|
||||
// values of the `.parse()` functions of all underlying parsers.
|
||||
bool ok = false;
|
||||
|
||||
// Represents the failure of `x3::expect[p]` and `a > b`.
|
||||
// Has value if and only if `ok` is `false` and any of
|
||||
// the underlying parsers have encountered expectation
|
||||
// failure.
|
||||
std::optional<expectation_failure<It>> expect_failure;
|
||||
|
||||
// Represents the remaining subrange of the input, after
|
||||
// applications of all (partially) successful attempts on
|
||||
// underlying parsers.
|
||||
std::ranges::subrange<It, Se> remainder;
|
||||
|
||||
// Convenient accessor, returns the string view of `remainder`.
|
||||
[[nodiscard]] constexpr std::basic_string_view<std::iter_value_t<It>>
|
||||
remainder_str() const
|
||||
requires requires {
|
||||
typename std::basic_string_view<std::iter_value_t<It>>;
|
||||
requires std::is_constructible_v<std::basic_string_view<std::iter_value_t<It>>, std::ranges::subrange<It, Se> const&>;
|
||||
}
|
||||
{
|
||||
return std::basic_string_view<std::iter_value_t<It>>{remainder};
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool completed() const noexcept
|
||||
{
|
||||
// Cases:
|
||||
// (1) The input was empty, and
|
||||
// (1-a) The grammar accepts empty input and succeeded => remainder.empty() && ok
|
||||
// (1-b) The grammar rejects empty input and failed => remainder.empty() && !ok
|
||||
// (2) The input was NOT empty, and
|
||||
// (2-a) The grammar comsumed all input and succeeded => remainder.empty() && ok
|
||||
// (2-b) The grammar consumed some input and (partially) succeeded => !remainder.empty() && ok
|
||||
// (2-c) The grammar consumed all input and failed (possibly via semantic action) => remainder.empty() && !ok
|
||||
// (2-d) The grammar consumed some input and failed => !remainder.empty() && !ok
|
||||
|
||||
// `completed()` is `true` if and only if the parse result is
|
||||
// either 1-a or 2-a; `false` otherwise. Note that 2-b is
|
||||
// intentionally considered out of scope.
|
||||
//
|
||||
// This definition eliminates the need to double-check both
|
||||
// the resulting `bool` and iterators on the user's part,
|
||||
// which had been the long-standing burden of Spirit since
|
||||
// the Qi era.
|
||||
return ok && remainder.empty();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr explicit operator bool() const noexcept
|
||||
{
|
||||
return this->completed();
|
||||
}
|
||||
};
|
||||
|
||||
template <std::ranges::forward_range R>
|
||||
using parse_result_for = parse_result<std::ranges::iterator_t<R>, std::ranges::sentinel_t<R>>;
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013 Agustin Berge
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -9,22 +8,24 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_PARSER_OCTOBER_16_2008_0254PM)
|
||||
#define BOOST_SPIRIT_X3_PARSER_OCTOBER_16_2008_0254PM
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/utility/declval.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
#include <utility>
|
||||
|
||||
#if !defined(BOOST_SPIRIT_X3_NO_RTTI)
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Subject, typename Action>
|
||||
struct action;
|
||||
@@ -32,74 +33,32 @@ namespace boost::spirit::x3
|
||||
template <typename Subject, typename Handler>
|
||||
struct guard;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct parser_base {};
|
||||
struct parser_id;
|
||||
} // detail
|
||||
struct parser_base {};
|
||||
struct parser_id;
|
||||
|
||||
template <typename Derived>
|
||||
struct parser : detail::parser_base
|
||||
struct parser : parser_base
|
||||
{
|
||||
static_assert(!std::is_reference_v<Derived>);
|
||||
using derived_type = Derived;
|
||||
typedef Derived derived_type;
|
||||
static bool const handles_container = false;
|
||||
static bool const is_pass_through_unary = false;
|
||||
static bool const has_action = false;
|
||||
|
||||
static constexpr bool handles_container = false;
|
||||
static constexpr bool is_pass_through_unary = false;
|
||||
static constexpr bool has_action = false;
|
||||
|
||||
[[nodiscard]] constexpr Derived& derived() & noexcept
|
||||
constexpr Derived const& derived() const
|
||||
{
|
||||
return static_cast<Derived&>(*this);
|
||||
return *static_cast<Derived const*>(this);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Derived const& derived() const& noexcept
|
||||
template <typename Action>
|
||||
constexpr action<Derived, Action> operator[](Action f) const
|
||||
{
|
||||
return static_cast<Derived const&>(*this);
|
||||
return { this->derived(), f };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Derived&& derived() && noexcept
|
||||
template <typename Handler>
|
||||
constexpr guard<Derived, Handler> on_error(Handler f) const
|
||||
{
|
||||
return static_cast<Derived&&>(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Derived const&& derived() const&& noexcept
|
||||
{
|
||||
return static_cast<Derived const&&>(*this);
|
||||
}
|
||||
|
||||
template <typename Self, typename Action>
|
||||
requires std::is_constructible_v<
|
||||
action<Derived, std::remove_cvref_t<Action>>,
|
||||
decltype(std::declval<Self>().derived()),
|
||||
Action
|
||||
>
|
||||
[[nodiscard]] constexpr action<Derived, std::remove_cvref_t<Action>>
|
||||
operator[](this Self&& self, Action&& f)
|
||||
noexcept(std::is_nothrow_constructible_v<
|
||||
action<Derived, std::remove_cvref_t<Action>>,
|
||||
decltype(std::forward<Self>(self).derived()),
|
||||
Action
|
||||
>)
|
||||
{
|
||||
return { std::forward<Self>(self).derived(), std::forward<Action>(f) };
|
||||
}
|
||||
|
||||
template <typename Self, typename Handler>
|
||||
requires std::is_constructible_v<
|
||||
guard<Derived, std::remove_cvref_t<Handler>>,
|
||||
decltype(std::declval<Self>().derived()),
|
||||
Handler
|
||||
>
|
||||
[[nodiscard]] constexpr guard<Derived, std::remove_cvref_t<Handler>>
|
||||
on_error(this Self&& self, Handler&& f)
|
||||
noexcept(std::is_nothrow_constructible_v<
|
||||
guard<Derived, std::remove_cvref_t<Handler>>,
|
||||
decltype(std::forward<Self>(self).derived()),
|
||||
Handler
|
||||
>)
|
||||
{
|
||||
return { std::forward<Self>(self).derived(), std::forward<Handler>(f) };
|
||||
return { this->derived(), f };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -109,20 +68,14 @@ namespace boost::spirit::x3
|
||||
template <typename Subject, typename Derived>
|
||||
struct unary_parser : parser<Derived>
|
||||
{
|
||||
using category = unary_category;
|
||||
using subject_type = Subject;
|
||||
static constexpr bool has_action = Subject::has_action;
|
||||
typedef unary_category category;
|
||||
typedef Subject subject_type;
|
||||
static bool const has_action = Subject::has_action;
|
||||
|
||||
template <typename SubjectT>
|
||||
requires
|
||||
(!std::is_same_v<std::remove_cvref_t<SubjectT>, unary_parser>) &&
|
||||
std::is_constructible_v<Subject, SubjectT>
|
||||
constexpr unary_parser(SubjectT&& subject)
|
||||
noexcept(std::is_nothrow_constructible_v<Subject, SubjectT>)
|
||||
: subject(std::forward<SubjectT>(subject))
|
||||
{}
|
||||
constexpr unary_parser(Subject const& subject)
|
||||
: subject(subject) {}
|
||||
|
||||
[[nodiscard]] constexpr unary_parser const& get_unary() const noexcept { return *this; }
|
||||
unary_parser const& get_unary() const { return *this; }
|
||||
|
||||
Subject subject;
|
||||
};
|
||||
@@ -130,375 +83,139 @@ namespace boost::spirit::x3
|
||||
template <typename Left, typename Right, typename Derived>
|
||||
struct binary_parser : parser<Derived>
|
||||
{
|
||||
using category = binary_category;
|
||||
using left_type = Left;
|
||||
using right_type = Right;
|
||||
static constexpr bool has_action = left_type::has_action || right_type::has_action;
|
||||
typedef binary_category category;
|
||||
typedef Left left_type;
|
||||
typedef Right right_type;
|
||||
static bool const has_action =
|
||||
left_type::has_action || right_type::has_action;
|
||||
|
||||
template <typename LeftT, typename RightT>
|
||||
requires std::is_constructible_v<Left, LeftT> && std::is_constructible_v<Right, RightT>
|
||||
constexpr binary_parser(LeftT&& left, RightT&& right)
|
||||
noexcept(std::is_nothrow_constructible_v<Left, LeftT> && std::is_nothrow_constructible_v<Right, RightT>)
|
||||
: left(std::forward<LeftT>(left))
|
||||
, right(std::forward<RightT>(right))
|
||||
{}
|
||||
constexpr binary_parser(Left const& left, Right const& right)
|
||||
: left(left), right(right) {}
|
||||
|
||||
[[nodiscard]] constexpr binary_parser const& get_binary() const noexcept { return *this; }
|
||||
binary_parser const& get_binary() const { return *this; }
|
||||
|
||||
Left left;
|
||||
Right right;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// as_parser: convert a type, T, into a parser.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace extension
|
||||
{
|
||||
// In short: if you want to customize the `as_parser(p)` behavior, just
|
||||
// specialize `x3::extension::as_parser` for your class.
|
||||
//
|
||||
// Older versions of X3 specified the signature `as_spirit_parser(p)` to be
|
||||
// used for the ADL adaptation of user-defined types. However, many parts in
|
||||
// X3 were instead using ADL of the form `as_parser(p)` to dispatch any types
|
||||
// in the first place. This makes it impossible for the control to reach the
|
||||
// `as_spirit_parser(p)` call if any user-defined `as_parser(p)` is *more
|
||||
// constrained* than `as_spirit_parser(p)`.
|
||||
//
|
||||
// In other words, the old signature `as_spirit_parser(p)` has never been
|
||||
// implemented correctly since its very first introduction to X3.
|
||||
//
|
||||
// Additionally, GitHub fulltext search shows that there exists zero usage of
|
||||
// `as_spirit_parser` except for the unmaintained blog post written by the
|
||||
// original inventor. Therefore, we simply removed the feature.
|
||||
//
|
||||
// Furthermore, the current maintainer of X3 believes there are no practical
|
||||
// use cases of ADL adaptation on user-defined types. As such, we make the
|
||||
// `x3::as_parser` (not to be confused with `x3::extension::as_parser`) to
|
||||
// model a C++20-ish CPO to inhibit undesired ADL in the first place.
|
||||
namespace detail
|
||||
{
|
||||
namespace as_parser_guard
|
||||
{
|
||||
void as_spirit_parser(...);
|
||||
|
||||
template <typename T>
|
||||
struct as_parser; // not defined
|
||||
template<typename T, typename R =
|
||||
decltype(as_spirit_parser(boost::declval<T const&>()))>
|
||||
struct deduce_as_parser
|
||||
{
|
||||
typedef R type;
|
||||
typedef typename
|
||||
boost::remove_cv<
|
||||
typename boost::remove_reference<R>::type
|
||||
>::type
|
||||
value_type;
|
||||
|
||||
static type call(T const& v)
|
||||
{
|
||||
return as_spirit_parser(v);
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct deduce_as_parser<T, void>
|
||||
{};
|
||||
}
|
||||
using as_parser_guard::deduce_as_parser;
|
||||
}
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct as_parser : detail::deduce_as_parser<T> {};
|
||||
|
||||
template <>
|
||||
struct as_parser<unused_type>
|
||||
{
|
||||
using value_type [[deprecated("Use x3::as_parser_plain_t")]] = unused_type;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] static constexpr auto&& call(T&& unused_) noexcept
|
||||
typedef unused_type type;
|
||||
typedef unused_type value_type;
|
||||
static constexpr type call(unused_type)
|
||||
{
|
||||
return std::forward<T>(unused_);
|
||||
return unused;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
requires std::is_base_of_v<detail::parser_base, std::remove_cvref_t<Derived>>
|
||||
struct as_parser<Derived>
|
||||
struct as_parser<Derived
|
||||
, typename enable_if<is_base_of<parser_base, Derived>>::type>
|
||||
{
|
||||
using value_type [[deprecated("Use x3::as_parser_plain_t")]] = std::remove_cvref_t<Derived>;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] static constexpr auto&& call(T&& p) noexcept
|
||||
typedef Derived const& type;
|
||||
typedef Derived value_type;
|
||||
static constexpr type call(Derived const& p)
|
||||
{
|
||||
return std::forward<T>(p);
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
struct as_parser<parser<Derived>>
|
||||
{
|
||||
using value_type [[deprecated("Use x3::as_parser_plain_t")]] = Derived;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] static constexpr auto&& call(T&& p) noexcept
|
||||
typedef Derived const& type;
|
||||
typedef Derived value_type;
|
||||
static constexpr type call(parser<Derived> const& p)
|
||||
{
|
||||
return std::forward<T>(p).derived();
|
||||
return p.derived();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
template <typename T>
|
||||
constexpr typename extension::as_parser<T>::type
|
||||
as_parser(T const& x)
|
||||
{
|
||||
struct as_parser_fn
|
||||
{
|
||||
template <typename T>
|
||||
static void operator()(T&&) = delete; // If you reach here, your specialization of `x3::extension::as_parser` has a wrong signature, or the type is simply incompatible.
|
||||
return extension::as_parser<T>::call(x);
|
||||
}
|
||||
|
||||
// catch-all default fallback
|
||||
template <typename T>
|
||||
requires std::is_base_of_v<
|
||||
parser_base,
|
||||
std::remove_cvref_t<decltype(extension::as_parser<std::remove_cvref_t<T>>::call(std::declval<T>()))>
|
||||
>
|
||||
[[nodiscard]] static constexpr decltype(auto)
|
||||
operator()(T&& x) noexcept(noexcept(extension::as_parser<std::remove_cvref_t<T>>::call(std::forward<T>(x))))
|
||||
{
|
||||
return extension::as_parser<std::remove_cvref_t<T>>::call(std::forward<T>(x));
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
[[nodiscard]] static constexpr auto&&
|
||||
operator()(parser<Derived>& p) noexcept
|
||||
{
|
||||
return p.derived();
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
[[nodiscard]] static constexpr auto&&
|
||||
operator()(parser<Derived> const& p) noexcept
|
||||
{
|
||||
return p.derived();
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
[[nodiscard]] static constexpr auto&&
|
||||
operator()(parser<Derived>&& p) noexcept
|
||||
{
|
||||
return std::move(p).derived();
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
[[nodiscard]] static constexpr auto&&
|
||||
operator()(parser<Derived> const&& p) noexcept
|
||||
{
|
||||
return std::move(p).derived();
|
||||
}
|
||||
}; // as_parser_fn
|
||||
} // detail
|
||||
|
||||
inline namespace cpos
|
||||
template <typename Derived>
|
||||
constexpr Derived const&
|
||||
as_parser(parser<Derived> const& p)
|
||||
{
|
||||
inline constexpr detail::as_parser_fn as_parser{};
|
||||
} // cpos
|
||||
return p.derived();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using as_parser_t = decltype(as_parser(std::declval<T>())); // no ADL
|
||||
|
||||
template <typename T>
|
||||
using as_parser_plain_t = std::remove_cvref_t<as_parser_t<T>>;
|
||||
|
||||
|
||||
// This is a very low level API provided for consistency with
|
||||
// `is_parser_nothrow_castable`. Most users should use `X3Subject`
|
||||
// instead.
|
||||
template <typename T>
|
||||
struct is_parser_castable : std::bool_constant<
|
||||
requires {
|
||||
{ x3::as_parser(std::declval<T>()) };
|
||||
}
|
||||
> {};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_parser_castable_v = is_parser_castable<T>::value;
|
||||
|
||||
// This trait can be used primarily for multi-parameter constructors.
|
||||
// For example, `a op b` normally requires the below condition to
|
||||
// become fully noexcept:
|
||||
// is_parser_nothrow_castable_v<A> &&
|
||||
// is_parser_nothrow_castable_v<B> &&
|
||||
// std::is_nothrow_constructible_v<op_parser, as_parser_t<A>, as_parser_t<B>>
|
||||
template <typename T>
|
||||
struct is_parser_nothrow_castable : std::bool_constant<
|
||||
requires {
|
||||
{ x3::as_parser(std::declval<T>()) } noexcept;
|
||||
}
|
||||
> {};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_parser_nothrow_castable_v = is_parser_nothrow_castable<T>::value;
|
||||
|
||||
// A type that models `X3Subject` can be used in generic directives
|
||||
// and operators. Note that this concept is iterator-agnostic.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The main what function
|
||||
//
|
||||
// For example, let `p` denote an object of `T`. Then, `!p` is a
|
||||
// well-formed NOT predicate in X3's domain (with "NOT predicate"
|
||||
// referring to that of the PEG semantics) if and only if `T`
|
||||
// models `X3Subject`.
|
||||
template <typename T>
|
||||
concept X3Subject =
|
||||
is_parser_castable_v<T> && // `as_parser(t)` is valid?
|
||||
std::is_base_of_v<detail::parser_base, as_parser_plain_t<T>>;
|
||||
|
||||
// Checks whether `Parser(as_parser(t))` is valid.
|
||||
//
|
||||
// This trait can be used for checking whether a "Parser" is constructible
|
||||
// with some arbitrary argument `T`. In our (X3 core) use cases, the `Parser`
|
||||
// is usually a concrete type (e.g. `some_parser<as_parser_plain_t<Subject>>`)
|
||||
// whereas the `T` is some user-provided arbitrary type (e.g. `X3Subject Subject`).
|
||||
//
|
||||
// This interface can only be used to check whether `Parser`'s single-parameter
|
||||
// constructor is available. For multi-parameter construction, manually combine
|
||||
// `is_parser_castable` with `std::is_constructible`.
|
||||
template <X3Subject Parser, X3Subject T>
|
||||
struct is_parser_constructible : std::false_type {};
|
||||
|
||||
template <X3Subject Parser, X3Subject T>
|
||||
requires std::is_constructible_v<Parser, as_parser_t<T>>
|
||||
struct is_parser_constructible<Parser, T> : std::true_type {};
|
||||
|
||||
template <X3Subject Parser, X3Subject T>
|
||||
constexpr bool is_parser_constructible_v = is_parser_constructible<Parser, T>::value;
|
||||
|
||||
// Checks whether `Parser(as_parser(t))` is noexcept.
|
||||
//
|
||||
// This interface can only be used to check whether `Parser`'s single-parameter
|
||||
// constructor is available. For multi-parameter construction, manually combine
|
||||
// `is_parser_nothrow_castable` with `std::is_nothrow_constructible`.
|
||||
template <X3Subject Parser, X3Subject T>
|
||||
struct is_parser_nothrow_constructible : std::false_type {};
|
||||
|
||||
template <X3Subject Parser, X3Subject T>
|
||||
requires
|
||||
is_parser_nothrow_castable_v<T> &&
|
||||
std::is_nothrow_constructible_v<Parser, as_parser_t<T>>
|
||||
struct is_parser_nothrow_constructible<Parser, T> : std::true_type {};
|
||||
|
||||
template <X3Subject Parser, X3Subject T>
|
||||
constexpr bool is_parser_nothrow_constructible_v = is_parser_nothrow_constructible<Parser, T>::value;
|
||||
|
||||
|
||||
template <
|
||||
typename Parser,
|
||||
typename It, // Don't constrain these; just let `static_assert` be engaged for friendly errors
|
||||
typename Se,
|
||||
typename Context,
|
||||
typename RContext,
|
||||
typename Attribute
|
||||
>
|
||||
struct is_parsable
|
||||
{
|
||||
static_assert(X3Subject<Parser>);
|
||||
static_assert(!std::is_reference_v<It>);
|
||||
static_assert(std::forward_iterator<It>);
|
||||
static_assert(std::sentinel_for<Se, It>);
|
||||
static_assert(!std::is_reference_v<Context>);
|
||||
static_assert(!std::is_reference_v<RContext>);
|
||||
static_assert(!std::is_reference_v<Attribute>);
|
||||
|
||||
static constexpr bool value = requires(Parser const& p) // mutable parser use case is currently unknown
|
||||
{
|
||||
{
|
||||
p.parse(
|
||||
std::declval<It&>(), // first
|
||||
std::declval<Se>(), // last
|
||||
std::declval<Context const&>(), // context
|
||||
std::declval<RContext&>(), // rcontext
|
||||
std::declval<Attribute&>() // attr
|
||||
)
|
||||
} -> std::convertible_to<bool>;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename Parser, typename It, typename Se, typename Context, typename RContext, typename Attribute>
|
||||
constexpr bool is_parsable_v = is_parsable<Parser, It, Se, Context, RContext, Attribute>::value;
|
||||
|
||||
// TODO: handle `parse_into_container` case
|
||||
template <typename Parser, typename It, typename Se, typename Context, typename RContext, typename Attribute>
|
||||
concept Parsable = is_parsable<Parser, It, Se, Context, RContext, Attribute>::value;
|
||||
// ^^^ this must be concept in order to provide better diagnostics (e.g. on MSVC)
|
||||
|
||||
template <
|
||||
typename Parser,
|
||||
typename It, // Don't constrain these; just let `static_assert` be engaged for friendly errors
|
||||
typename Se,
|
||||
typename Context,
|
||||
typename RContext,
|
||||
typename Attribute
|
||||
>
|
||||
struct is_nothrow_parsable
|
||||
{
|
||||
static_assert(X3Subject<Parser>);
|
||||
static_assert(!std::is_reference_v<It>);
|
||||
static_assert(std::forward_iterator<It>);
|
||||
static_assert(std::sentinel_for<Se, It>);
|
||||
static_assert(!std::is_reference_v<Context>);
|
||||
static_assert(!std::is_reference_v<RContext>);
|
||||
static_assert(!std::is_reference_v<Attribute>);
|
||||
|
||||
static constexpr bool value = requires(Parser const& p) // mutable parser use case is currently unknown
|
||||
{
|
||||
{
|
||||
p.parse(
|
||||
std::declval<It&>(), // first
|
||||
std::declval<Se>(), // last
|
||||
std::declval<Context const&>(), // context
|
||||
std::declval<RContext&>(), // rcontext
|
||||
std::declval<Attribute&>() // attr
|
||||
)
|
||||
} noexcept -> std::convertible_to<bool>;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename Parser, typename It, typename Se, typename Context, typename RContext, typename Attribute>
|
||||
constexpr bool is_nothrow_parsable_v = is_nothrow_parsable<Parser, It, Se, Context, RContext, Attribute>::value;
|
||||
|
||||
// The primary "parser" concept of X3, applicable in iterator-aware contexts.
|
||||
//
|
||||
// Let `it` denote an lvalue reference of `It`, and let `se` denote a prvalue of `Se`.
|
||||
// Let `p` denote an lvalue reference of `Parser`.
|
||||
//
|
||||
// For `Parser` to model `X3Parser`, the following conditions must be satisfied:
|
||||
// -- the expression `x3::as_parser(p)` is well-formed in unevaluated context, and
|
||||
// -- the expression `cp.parse(it, se, x3::unused, x3::unused, x3::unused)`
|
||||
// is well-formed and the return type is convertible to `bool`, where `cp` denotes a
|
||||
// const lvalue reference to the result of the expression `x3::as_parser(p)`.
|
||||
//
|
||||
// Although some exotic user-defined parser could be designed to operate on the very
|
||||
// specific context type and/or attribute type, we require the parser to at least
|
||||
// accept `unused_type` for `RContext`, `Context` and `Attribute`. This is because
|
||||
// core parsers of Spirit have historically been assuming natural use of `unused_type`
|
||||
// in many locations.
|
||||
template <typename Parser, class It, class Se>
|
||||
concept X3Parser =
|
||||
X3Subject<Parser> &&
|
||||
is_parsable_v<as_parser_plain_t<Parser>, It, Se, unused_type, unused_type, unused_type>;
|
||||
|
||||
|
||||
// The runtime type info that can be obtained via `x3::what(p)`.
|
||||
template <X3Subject Subject, typename Enabled = void>
|
||||
// Note: unlike Spirit2, spirit parsers are no longer required to have a
|
||||
// "what" member function. In X3, we specialize the get_info struct
|
||||
// below where needed. If a specialization is not provided, the default
|
||||
// below will be used. The default "what" result will be the typeid
|
||||
// name of the parser if BOOST_SPIRIT_X3_NO_RTTI is not defined, otherwise
|
||||
// "undefined"
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Parser, typename Enable = void>
|
||||
struct get_info
|
||||
{
|
||||
[[nodiscard]] static constexpr std::string operator()(Subject const& subject)
|
||||
typedef std::string result_type;
|
||||
std::string operator()(Parser const&) const
|
||||
{
|
||||
if constexpr (requires {
|
||||
{ subject.get_x3_info() } -> std::convertible_to<std::string>;
|
||||
})
|
||||
{
|
||||
return subject.get_x3_info();
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)subject;
|
||||
#ifndef BOOST_SPIRIT_X3_NO_RTTI
|
||||
return typeid(Subject).name();
|
||||
#else
|
||||
return "(get_info undefined)";
|
||||
#endif
|
||||
}
|
||||
#if !defined(BOOST_SPIRIT_X3_NO_RTTI)
|
||||
return typeid(Parser).name();
|
||||
#else
|
||||
return "undefined";
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
template <typename Parser>
|
||||
std::string what(Parser const& p)
|
||||
{
|
||||
// "what" is an extremely common identifier that can be defined in many user-specific
|
||||
// namespaces. We should avoid ADL usage for such generic names in the first place.
|
||||
// (Note: CPO inhibits ADL in general.)
|
||||
struct what_fn
|
||||
{
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] static constexpr std::string operator()(Subject const& p)
|
||||
{
|
||||
return get_info<Subject>{}(p);
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
return get_info<Parser>()(p);
|
||||
}
|
||||
}}}
|
||||
|
||||
inline namespace cpos
|
||||
{
|
||||
inline constexpr detail::what_fn what{}; // no ADL
|
||||
} // cpos
|
||||
|
||||
} // boost::spirit::x3
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename Subject, typename Derived, typename Context>
|
||||
struct has_attribute<x3::unary_parser<Subject, Derived>, Context>
|
||||
@@ -506,7 +223,8 @@ namespace boost::spirit::x3::traits
|
||||
|
||||
template <typename Left, typename Right, typename Derived, typename Context>
|
||||
struct has_attribute<x3::binary_parser<Left, Right, Derived>, Context>
|
||||
: std::disjunction<has_attribute<Left, Context>, has_attribute<Right, Context>> {};
|
||||
} // boost::spirit::x3::traits
|
||||
: mpl::bool_<has_attribute<Left, Context>::value ||
|
||||
has_attribute<Right, Context>::value> {};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
51
include/boost/spirit/home/x3/core/proxy.hpp
Normal file
51
include/boost/spirit/home/x3/core/proxy.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2017 wanghan02
|
||||
Copyright (c) 2024 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_X3_PROXY_FEBRUARY_1_2013_0211PM)
|
||||
#define BOOST_SPIRIT_X3_PROXY_FEBRUARY_1_2013_0211PM
|
||||
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Subject, typename Derived>
|
||||
struct proxy : unary_parser<Subject, Derived>
|
||||
{
|
||||
static bool const is_pass_through_unary = true;
|
||||
|
||||
constexpr proxy(Subject const& subject)
|
||||
: unary_parser<Subject, Derived>(subject) {}
|
||||
|
||||
// Overload this when appropriate. The proxy parser will pick up
|
||||
// the most derived overload.
|
||||
template <typename Iterator, typename Context
|
||||
, typename RuleContext, typename Attribute, typename Category>
|
||||
bool parse_subject(Iterator& first, Iterator const& last
|
||||
, Context const& context, RuleContext& rcontext, Attribute& attr, Category) const
|
||||
{
|
||||
this->subject.parse(first, last, context, rcontext, attr);
|
||||
return !has_expectation_failure(context);
|
||||
}
|
||||
|
||||
// Main entry point.
|
||||
template <typename Iterator, typename Context
|
||||
, typename RuleContext, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RuleContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
return this->derived().parse_subject(first, last, context, rcontext, attr
|
||||
, typename traits::attribute_category<Attribute>::type());
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2017 wanghan02
|
||||
Copyright (c) 2024-2025 Nana Sakisaka
|
||||
Copyright (c) 2024 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -13,86 +13,61 @@
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/utility/declval.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
// Tag used to find the skipper from the context
|
||||
struct skipper_tag;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Move the /first/ iterator to the first non-matching position
|
||||
// given a skip-parser. The function is a no-op if unused_type or
|
||||
// unused_skipper is passed as the skip-parser.
|
||||
template <X3Subject Skipper>
|
||||
struct [[nodiscard]] unused_skipper
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Skipper>
|
||||
struct unused_skipper : unused_type
|
||||
{
|
||||
constexpr unused_skipper(Skipper const& skipper) noexcept
|
||||
: skipper(skipper)
|
||||
{}
|
||||
|
||||
unused_skipper(Skipper const& skipper)
|
||||
: skipper(skipper) {}
|
||||
Skipper const& skipper;
|
||||
};
|
||||
|
||||
template <typename Context>
|
||||
using unused_skipper_t = unused_skipper<std::remove_cvref_t<decltype(x3::get<skipper_tag>(std::declval<Context>()))>>;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename Skipper>
|
||||
struct is_unused_skipper : std::false_type
|
||||
{
|
||||
static_assert(X3Subject<Skipper>);
|
||||
};
|
||||
struct is_unused_skipper
|
||||
: mpl::false_ {};
|
||||
|
||||
template <typename Skipper>
|
||||
struct is_unused_skipper<unused_skipper<Skipper>> : std::true_type {};
|
||||
struct is_unused_skipper<unused_skipper<Skipper>>
|
||||
: mpl::true_ {};
|
||||
|
||||
template <>
|
||||
struct is_unused_skipper<unused_type> : std::true_type {};
|
||||
struct is_unused_skipper<unused_type>
|
||||
: mpl::true_ {};
|
||||
|
||||
template <typename Skipper>
|
||||
[[nodiscard]] constexpr Skipper const&
|
||||
get_unused_skipper(Skipper const& skipper) noexcept
|
||||
inline Skipper const&
|
||||
get_unused_skipper(Skipper const& skipper)
|
||||
{
|
||||
static_assert(X3Subject<Skipper>);
|
||||
return skipper;
|
||||
}
|
||||
|
||||
template <typename Skipper>
|
||||
[[nodiscard]] constexpr Skipper const&
|
||||
get_unused_skipper(unused_skipper<Skipper> const& unused_skipper) noexcept
|
||||
inline Skipper const&
|
||||
get_unused_skipper(unused_skipper<Skipper> const& unused_skipper)
|
||||
{
|
||||
static_assert(X3Subject<Skipper>);
|
||||
return unused_skipper.skipper;
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
struct skip_over_context
|
||||
{
|
||||
using type = unused_type;
|
||||
};
|
||||
|
||||
template <typename Context>
|
||||
requires (!std::is_same_v<expectation_failure_t<Context>, unused_type>)
|
||||
struct skip_over_context<Context>
|
||||
{
|
||||
using type = std::remove_cvref_t<decltype(x3::make_context<expectation_failure_tag>(
|
||||
x3::get<expectation_failure_tag>(std::declval<Context const&>())
|
||||
))>;
|
||||
};
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, X3Subject Skipper>
|
||||
constexpr void skip_over(
|
||||
It& first, Se const& last, Context& context, Skipper const& skipper
|
||||
)
|
||||
noexcept(is_nothrow_parsable_v<Skipper, It, Se, typename skip_over_context<Context>::type, unused_type, unused_type>)
|
||||
template <typename Iterator, typename Context, typename Skipper>
|
||||
inline void skip_over(
|
||||
Iterator& first, Iterator const& last, Context& context, Skipper const& skipper)
|
||||
{
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
(void)context;
|
||||
boost::ignore_unused(context);
|
||||
while (skipper.parse(first, last, unused, unused, unused))
|
||||
/* loop */;
|
||||
#else
|
||||
@@ -142,7 +117,7 @@ namespace boost::spirit::x3
|
||||
// For this reason we're going to cherry-pick the reference
|
||||
// and repack it into a brand new context.
|
||||
|
||||
auto const local_ctx = x3::make_context<expectation_failure_tag>(
|
||||
auto const local_ctx = make_context<expectation_failure_tag>(
|
||||
x3::get<expectation_failure_tag>(context));
|
||||
|
||||
while (skipper.parse(first, last, local_ctx, unused, unused))
|
||||
@@ -151,33 +126,35 @@ namespace boost::spirit::x3
|
||||
#endif
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context>
|
||||
constexpr void skip_over(It&, Se const&, Context&, unused_type) noexcept
|
||||
template <typename Iterator, typename Context>
|
||||
inline void skip_over(Iterator&, Iterator const&, Context&, unused_type)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename Skipper>
|
||||
constexpr void skip_over(It&, Se const&, Context&, unused_skipper<Skipper> const&) noexcept
|
||||
template <typename Iterator, typename Context, typename Skipper>
|
||||
inline void skip_over(
|
||||
Iterator&, Iterator const&, Context&, unused_skipper<Skipper> const&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// this tag is used to find the skipper from the context
|
||||
struct skipper_tag;
|
||||
|
||||
template <typename Context>
|
||||
struct has_skipper
|
||||
: std::bool_constant<!detail::is_unused_skipper<
|
||||
std::remove_cvref_t<decltype(x3::get<skipper_tag>(std::declval<Context>()))>
|
||||
>::value>
|
||||
{};
|
||||
: mpl::not_<detail::is_unused_skipper<
|
||||
typename remove_cv<typename remove_reference<
|
||||
decltype(x3::get<skipper_tag>(boost::declval<Context>()))
|
||||
>::type>::type
|
||||
>> {};
|
||||
|
||||
template <typename Context>
|
||||
constexpr bool has_skipper_v = has_skipper<Context>::value;
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context>
|
||||
constexpr void skip_over(It& first, Se const& last, Context& context)
|
||||
noexcept(noexcept(detail::skip_over(first, last, context, x3::get<skipper_tag>(context))))
|
||||
template <typename Iterator, typename Context>
|
||||
inline void skip_over(
|
||||
Iterator& first, Iterator const& last, Context& context)
|
||||
{
|
||||
detail::skip_over(first, last, context, x3::get<skipper_tag>(context));
|
||||
}
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Copyright (c) 2009 Chris Hoeppler
|
||||
Copyright (c) 2014 Lee Clagett
|
||||
Copyright (c) 2017 wanghan02
|
||||
Copyright (c) 2024-2025 Nana Sakisaka
|
||||
Copyright (c) 2024 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -13,124 +13,82 @@
|
||||
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template<typename Prefix, typename Subject, typename Postfix>
|
||||
struct confix_directive :
|
||||
unary_parser<Subject, confix_directive<Prefix, Subject, Postfix>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, confix_directive<Prefix, Subject, Postfix>>;
|
||||
static constexpr bool is_pass_through_unary = true;
|
||||
static constexpr bool handles_container = Subject::handles_container;
|
||||
typedef unary_parser<
|
||||
Subject, confix_directive<Prefix, Subject, Postfix>> base_type;
|
||||
static bool const is_pass_through_unary = true;
|
||||
static bool const handles_container = Subject::handles_container;
|
||||
|
||||
template <typename PrefixT, typename SubjectT, typename PostfixT>
|
||||
requires
|
||||
std::is_constructible_v<Prefix, PrefixT> &&
|
||||
std::is_constructible_v<Subject, SubjectT> &&
|
||||
std::is_constructible_v<Postfix, PostfixT>
|
||||
constexpr confix_directive(PrefixT&& prefix, SubjectT&& subject, PostfixT&& postfix)
|
||||
noexcept(
|
||||
std::is_nothrow_constructible_v<Prefix, PrefixT> &&
|
||||
std::is_nothrow_constructible_v<Subject, SubjectT> &&
|
||||
std::is_nothrow_constructible_v<Postfix, PostfixT>
|
||||
)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
, prefix_(std::forward<PrefixT>(prefix))
|
||||
, postfix_(std::forward<PostfixT>(postfix))
|
||||
constexpr confix_directive(Prefix const& prefix
|
||||
, Subject const& subject
|
||||
, Postfix const& postfix) :
|
||||
base_type(subject),
|
||||
prefix(prefix),
|
||||
postfix(postfix)
|
||||
{
|
||||
}
|
||||
|
||||
template<std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr
|
||||
) const noexcept(
|
||||
std::is_nothrow_copy_assignable_v<It> &&
|
||||
is_nothrow_parsable_v<Prefix, It, Se, Context, RContext, unused_type> &&
|
||||
is_nothrow_parsable_v<Subject, It, Se, Context, RContext, Attribute> &&
|
||||
is_nothrow_parsable_v<Postfix, It, Se, Context, RContext, unused_type>
|
||||
)
|
||||
template<typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse(
|
||||
Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
It const saved_first = first;
|
||||
Iterator save = first;
|
||||
|
||||
if (!(prefix_.parse(first, last, context, rcontext, unused) &&
|
||||
if (!(prefix.parse(first, last, context, rcontext, unused) &&
|
||||
this->subject.parse(first, last, context, rcontext, attr) &&
|
||||
postfix_.parse(first, last, context, rcontext, unused))
|
||||
) {
|
||||
postfix.parse(first, last, context, rcontext, unused)))
|
||||
{
|
||||
#if !BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
if (x3::has_expectation_failure(context))
|
||||
if (has_expectation_failure(context))
|
||||
{
|
||||
// don't rollback iterator (mimicking exception-like behavior)
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
first = saved_first;
|
||||
first = save;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
Prefix prefix_;
|
||||
Postfix postfix_;
|
||||
Prefix prefix;
|
||||
Postfix postfix;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
template<typename Prefix, typename Postfix>
|
||||
struct confix_gen
|
||||
{
|
||||
template <X3Subject Prefix, X3Subject Postfix>
|
||||
struct [[nodiscard]] confix_gen
|
||||
template<typename Subject>
|
||||
constexpr confix_directive<
|
||||
Prefix, typename extension::as_parser<Subject>::value_type, Postfix>
|
||||
operator[](Subject const& subject) const
|
||||
{
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] constexpr confix_directive<Prefix, as_parser_plain_t<Subject>, Postfix>
|
||||
operator[](Subject&& subject) const
|
||||
noexcept(
|
||||
is_parser_nothrow_castable_v<Subject> &&
|
||||
std::is_nothrow_constructible_v<
|
||||
confix_directive<Prefix, as_parser_plain_t<Subject>, Postfix>,
|
||||
Prefix const&,
|
||||
as_parser_t<Subject>,
|
||||
Postfix const&
|
||||
>
|
||||
)
|
||||
{
|
||||
return { prefix, as_parser(std::forward<Subject>(subject)), postfix };
|
||||
}
|
||||
return { prefix, as_parser(subject), postfix };
|
||||
}
|
||||
|
||||
Prefix prefix;
|
||||
Postfix postfix;
|
||||
};
|
||||
Prefix prefix;
|
||||
Postfix postfix;
|
||||
};
|
||||
|
||||
struct confix_fn
|
||||
{
|
||||
template <X3Subject Prefix, X3Subject Postfix>
|
||||
static constexpr confix_gen<as_parser_plain_t<Prefix>, as_parser_plain_t<Postfix>>
|
||||
operator()(Prefix&& prefix, Postfix&& postfix)
|
||||
noexcept(
|
||||
is_parser_nothrow_castable_v<Prefix> &&
|
||||
is_parser_nothrow_castable_v<Postfix> &&
|
||||
std::is_nothrow_constructible_v<
|
||||
detail::confix_gen<as_parser_plain_t<Prefix>, as_parser_plain_t<Postfix>>,
|
||||
as_parser_t<Prefix>, as_parser_t<Postfix>
|
||||
>
|
||||
)
|
||||
{
|
||||
return { as_parser(std::forward<Prefix>(prefix)), as_parser(std::forward<Postfix>(postfix)) };
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
|
||||
inline namespace cpos
|
||||
template<typename Prefix, typename Postfix>
|
||||
constexpr confix_gen<typename extension::as_parser<Prefix>::value_type,
|
||||
typename extension::as_parser<Postfix>::value_type>
|
||||
confix(Prefix const& prefix, Postfix const& postfix)
|
||||
{
|
||||
inline constexpr detail::confix_fn confix{};
|
||||
} // cpos
|
||||
} // boost::spirit::x3
|
||||
return { as_parser(prefix), as_parser(postfix) };
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2017 wanghan02
|
||||
Copyright (c) 2024-2025 Nana Sakisaka
|
||||
Copyright (c) 2024 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -14,30 +14,21 @@
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Subject>
|
||||
struct expect_directive : unary_parser<Subject, expect_directive<Subject>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, expect_directive<Subject>>;
|
||||
static constexpr bool is_pass_through_unary = true;
|
||||
typedef unary_parser<Subject, expect_directive<Subject> > base_type;
|
||||
static bool const is_pass_through_unary = true;
|
||||
|
||||
template <typename SubjectT>
|
||||
requires std::is_constructible_v<Subject, SubjectT>
|
||||
constexpr expect_directive(SubjectT&& subject)
|
||||
noexcept(std::is_nothrow_constructible_v<Subject, SubjectT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
{}
|
||||
constexpr expect_directive(Subject const& subject)
|
||||
: base_type(subject) {}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr
|
||||
) const // never noexcept; expectation failure requires construction of debug information
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
bool const r = this->subject.parse(first, last, context, rcontext, attr);
|
||||
|
||||
@@ -45,12 +36,12 @@ namespace boost::spirit::x3
|
||||
{
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
boost::throw_exception(
|
||||
expectation_failure<It>(
|
||||
first, x3::what(this->subject)));
|
||||
expectation_failure<Iterator>(
|
||||
first, what(this->subject)));
|
||||
#else
|
||||
if (!x3::has_expectation_failure(context))
|
||||
if (!has_expectation_failure(context))
|
||||
{
|
||||
x3::set_expectation_failure(first, this->subject, context);
|
||||
set_expectation_failure(first, this->subject, context);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -58,59 +49,50 @@ namespace boost::spirit::x3
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
struct expect_gen
|
||||
{
|
||||
struct expect_gen
|
||||
template <typename Subject>
|
||||
constexpr expect_directive<typename extension::as_parser<Subject>::value_type>
|
||||
operator[](Subject const& subject) const
|
||||
{
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] constexpr expect_directive<as_parser_plain_t<Subject>>
|
||||
operator[](Subject&& subject) const
|
||||
noexcept(is_parser_nothrow_constructible_v<expect_directive<as_parser_plain_t<Subject>>, Subject>)
|
||||
{
|
||||
return { as_parser(std::forward<Subject>(subject)) };
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
return { as_parser(subject) };
|
||||
}
|
||||
};
|
||||
|
||||
inline namespace cpos
|
||||
{
|
||||
inline constexpr detail::expect_gen expect{};
|
||||
} // cpos
|
||||
constexpr auto expect = expect_gen{};
|
||||
}}}
|
||||
|
||||
} // boost::spirit::x3
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
// Special case handling for expect expressions.
|
||||
template <typename Subject, typename Context, typename RContext>
|
||||
struct parse_into_container_impl<expect_directive<Subject>, Context, RContext>
|
||||
{
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
expect_directive<Subject> const& parser,
|
||||
It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr
|
||||
) // never noexcept; expectation failure requires construction of debug information
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
expect_directive<Subject> const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr)
|
||||
{
|
||||
bool const r = detail::parse_into_container(
|
||||
bool const r = parse_into_container(
|
||||
parser.subject, first, last, context, rcontext, attr);
|
||||
|
||||
if (!r)
|
||||
{
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
boost::throw_exception(
|
||||
expectation_failure<It>(
|
||||
first, x3::what(parser.subject)));
|
||||
expectation_failure<Iterator>(
|
||||
first, what(parser.subject)));
|
||||
#else
|
||||
if (!x3::has_expectation_failure(context))
|
||||
if (!has_expectation_failure(context))
|
||||
{
|
||||
x3::set_expectation_failure(first, parser.subject, context);
|
||||
set_expectation_failure(first, parser.subject, context);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
} // boost::spirit::x3::detail
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -12,85 +11,68 @@
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/spirit/home/x3/core/skip_over.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Subject>
|
||||
struct lexeme_directive : unary_parser<Subject, lexeme_directive<Subject>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, lexeme_directive<Subject>>;
|
||||
static constexpr bool is_pass_through_unary = true;
|
||||
static constexpr bool handles_container = Subject::handles_container;
|
||||
typedef unary_parser<Subject, lexeme_directive<Subject> > base_type;
|
||||
static bool const is_pass_through_unary = true;
|
||||
static bool const handles_container = Subject::handles_container;
|
||||
|
||||
template <typename SubjectT>
|
||||
requires std::is_constructible_v<Subject, SubjectT>
|
||||
constexpr lexeme_directive(SubjectT&& subject)
|
||||
noexcept(std::is_nothrow_constructible_v<base_type, SubjectT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
{}
|
||||
constexpr lexeme_directive(Subject const& subject)
|
||||
: base_type(subject) {}
|
||||
|
||||
template <typename Context>
|
||||
using pre_skip_context_t = std::remove_cvref_t<decltype(
|
||||
x3::make_context<skipper_tag>(std::declval<unused_skipper_t<Context>&>(), std::declval<Context const&>())
|
||||
)>;
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires has_skipper_v<Context>
|
||||
[[nodiscard]] constexpr bool parse(
|
||||
It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr
|
||||
) const
|
||||
noexcept(
|
||||
noexcept(x3::skip_over(first, last, context)) &&
|
||||
is_nothrow_parsable_v<Subject, It, Se, pre_skip_context_t<Context>, RContext, Attribute>
|
||||
)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
typename enable_if<has_skipper<Context>, bool>::type
|
||||
parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
x3::skip_over(first, last, context);
|
||||
|
||||
auto const& skipper = x3::get<skipper_tag>(context);
|
||||
unused_skipper_t<Context> unused_skipper(skipper);
|
||||
|
||||
typedef unused_skipper<
|
||||
typename remove_reference<decltype(skipper)>::type>
|
||||
unused_skipper_type;
|
||||
unused_skipper_type unused_skipper(skipper);
|
||||
|
||||
return this->subject.parse(
|
||||
first, last,
|
||||
x3::make_context<skipper_tag>(unused_skipper, context),
|
||||
rcontext,
|
||||
attr
|
||||
);
|
||||
first, last
|
||||
, make_context<skipper_tag>(unused_skipper, context)
|
||||
, rcontext
|
||||
, attr);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires (!has_skipper_v<Context>)
|
||||
[[nodiscard]] constexpr bool parse(
|
||||
It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr
|
||||
) const
|
||||
noexcept(is_nothrow_parsable_v<Subject, It, Se, Context, RContext, Attribute>)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
typename disable_if<has_skipper<Context>, bool>::type
|
||||
parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
// no need to pre-skip if skipper is unused
|
||||
return this->subject.parse(first, last, context, rcontext, attr);
|
||||
return this->subject.parse(
|
||||
first, last
|
||||
, context
|
||||
, rcontext
|
||||
, attr);
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
struct lexeme_gen
|
||||
{
|
||||
struct lexeme_gen
|
||||
template <typename Subject>
|
||||
constexpr lexeme_directive<typename extension::as_parser<Subject>::value_type>
|
||||
operator[](Subject const& subject) const
|
||||
{
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] constexpr lexeme_directive<as_parser_plain_t<Subject>>
|
||||
operator[](Subject&& subject) const
|
||||
noexcept(is_parser_nothrow_constructible_v<lexeme_directive<as_parser_plain_t<Subject>>, Subject>)
|
||||
{
|
||||
return { as_parser(std::forward<Subject>(subject)) };
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
return { as_parser(subject) };
|
||||
}
|
||||
};
|
||||
|
||||
inline namespace cpos
|
||||
{
|
||||
inline constexpr detail::lexeme_gen lexeme{};
|
||||
}
|
||||
} // boost::spirit::x3
|
||||
constexpr auto lexeme = lexeme_gen{};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Copyright (c) 2015 Mario Lang
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2017 wanghan02
|
||||
Copyright (c) 2024-2025 Nana Sakisaka
|
||||
Copyright (c) 2024 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -15,64 +15,45 @@
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Subject>
|
||||
struct matches_directive : unary_parser<Subject, matches_directive<Subject>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, matches_directive<Subject>>;
|
||||
static constexpr bool has_attribute = true;
|
||||
static bool const has_attribute = true;
|
||||
using attribute_type = bool;
|
||||
|
||||
template <typename SubjectT>
|
||||
requires std::is_constructible_v<Subject, SubjectT>
|
||||
constexpr matches_directive(SubjectT&& subject)
|
||||
noexcept(std::is_nothrow_constructible_v<Subject, SubjectT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
{}
|
||||
constexpr matches_directive(Subject const& subject) : base_type(subject) {}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
noexcept(
|
||||
is_nothrow_parsable_v<Subject, It, Se, Context, RContext, unused_type> &&
|
||||
noexcept(traits::move_to(std::declval<bool const&>(), attr))
|
||||
)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
bool const matched = this->subject.parse(first, last, context, rcontext, unused);
|
||||
bool const result = this->subject.parse(
|
||||
first, last, context, rcontext, unused);
|
||||
|
||||
#if !BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
if (x3::has_expectation_failure(context)) return false;
|
||||
if (has_expectation_failure(context)) return false;
|
||||
#endif
|
||||
|
||||
traits::move_to(matched, attr);
|
||||
traits::move_to(result, attr);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
struct matches_gen
|
||||
{
|
||||
struct matches_gen
|
||||
template <typename Subject>
|
||||
constexpr matches_directive<typename extension::as_parser<Subject>::value_type>
|
||||
operator[](Subject const& subject) const
|
||||
{
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] constexpr matches_directive<as_parser_plain_t<Subject>>
|
||||
operator[](Subject&& subject) const
|
||||
noexcept(is_parser_nothrow_constructible_v<matches_directive<as_parser_plain_t<Subject>>, Subject>)
|
||||
{
|
||||
return { as_parser(std::forward<Subject>(subject)) };
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
return { as_parser(subject) };
|
||||
}
|
||||
};
|
||||
|
||||
inline namespace cpos
|
||||
{
|
||||
inline constexpr detail::matches_gen matches{};
|
||||
} // cpos
|
||||
|
||||
} // boost::spirit::x3
|
||||
constexpr auto matches = matches_gen{};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -11,58 +10,42 @@
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
// `omit_directive` forces the attribute of subject parser
|
||||
// to be `unused_type`
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// omit_directive forces the attribute of subject parser
|
||||
// to be unused_type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Subject>
|
||||
struct omit_directive : unary_parser<Subject, omit_directive<Subject>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, omit_directive<Subject>>;
|
||||
using attribute_type = unused_type;
|
||||
using subject_type = Subject;
|
||||
static constexpr bool has_attribute = false;
|
||||
typedef unary_parser<Subject, omit_directive<Subject> > base_type;
|
||||
typedef unused_type attribute_type;
|
||||
static bool const has_attribute = false;
|
||||
|
||||
template <typename SubjectT>
|
||||
requires std::is_constructible_v<Subject, SubjectT>
|
||||
constexpr omit_directive(SubjectT&& subject)
|
||||
noexcept(std::is_nothrow_constructible_v<Subject, SubjectT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
{}
|
||||
typedef Subject subject_type;
|
||||
constexpr omit_directive(Subject const& subject)
|
||||
: base_type(subject) {}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It& first, Se const& last, Context const& context, RContext& rcontext, unused_type
|
||||
) const noexcept(is_nothrow_parsable_v<Subject, It, Se, Context, RContext, unused_type>)
|
||||
template <typename Iterator, typename Context, typename RContext>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, unused_type) const
|
||||
{
|
||||
static_assert(Parsable<Subject, It, Se, Context, RContext, unused_type>);
|
||||
return this->subject.parse(first, last, context, rcontext, unused);
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
struct omit_gen
|
||||
{
|
||||
struct omit_gen
|
||||
template <typename Subject>
|
||||
constexpr omit_directive<typename extension::as_parser<Subject>::value_type>
|
||||
operator[](Subject const& subject) const
|
||||
{
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] constexpr omit_directive<as_parser_plain_t<Subject>>
|
||||
operator[](Subject&& subject) const
|
||||
noexcept(is_parser_nothrow_constructible_v<omit_directive<as_parser_plain_t<Subject>>, as_parser_t<Subject>>)
|
||||
{
|
||||
return { as_parser(std::forward<Subject>(subject)) };
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
return { as_parser(subject) };
|
||||
}
|
||||
};
|
||||
|
||||
inline namespace cpos
|
||||
{
|
||||
inline constexpr detail::omit_gen omit{};
|
||||
}
|
||||
} // boost::spirit::x3
|
||||
constexpr auto omit = omit_gen{};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -12,20 +11,11 @@
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/pseudo_attribute.hpp>
|
||||
#include <boost/range/iterator_range_core.hpp>
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
|
||||
# pragma message("Use of `boost::iterator_range` is deprecated in X3. #define BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE")
|
||||
# include <boost/range/iterator_range_core.hpp>
|
||||
#endif
|
||||
|
||||
#include <ranges>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
// Pseudo attribute type indicating that the parser wants the
|
||||
// this is a pseudo attribute type indicating that the parser wants the
|
||||
// iterator range pointing to the [first, last) matching characters from
|
||||
// the input iterators.
|
||||
struct raw_attribute_type {};
|
||||
@@ -33,83 +23,64 @@ namespace boost::spirit::x3
|
||||
template <typename Subject>
|
||||
struct raw_directive : unary_parser<Subject, raw_directive<Subject>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, raw_directive<Subject>>;
|
||||
using attribute_type = raw_attribute_type;
|
||||
using subject_type = Subject;
|
||||
typedef unary_parser<Subject, raw_directive<Subject> > base_type;
|
||||
typedef raw_attribute_type attribute_type;
|
||||
static bool const handles_container = true;
|
||||
typedef Subject subject_type;
|
||||
|
||||
static constexpr bool handles_container = true;
|
||||
constexpr raw_directive(Subject const& subject)
|
||||
: base_type(subject) {}
|
||||
|
||||
template <typename SubjectT>
|
||||
requires std::is_constructible_v<Subject, SubjectT>
|
||||
constexpr raw_directive(SubjectT&& subject)
|
||||
noexcept(std::is_nothrow_constructible_v<Subject, SubjectT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
{}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
// never noexcept; construction of `std::ranges::subrange` is never noexcept
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
static_assert(Parsable<Subject, It, Se, Context, RContext, unused_type>);
|
||||
|
||||
x3::skip_over(first, last, context);
|
||||
It local_it = first;
|
||||
if (this->subject.parse(local_it, last, context, rcontext, unused))
|
||||
Iterator i = first;
|
||||
if (this->subject.parse(i, last, context, rcontext, unused))
|
||||
{
|
||||
traits::move_to(first, local_it, attr);
|
||||
first = local_it;
|
||||
traits::move_to(first, i, attr);
|
||||
first = i;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, unused_type) const
|
||||
noexcept(is_nothrow_parsable_v<Subject, It, Se, Context, RContext, unused_type>)
|
||||
template <typename Iterator, typename Context, typename RContext>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, unused_type) const
|
||||
{
|
||||
return this->subject.parse(first, last, context, rcontext, unused);
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
struct raw_gen
|
||||
{
|
||||
struct raw_gen
|
||||
template <typename Subject>
|
||||
constexpr raw_directive<typename extension::as_parser<Subject>::value_type>
|
||||
operator[](Subject const& subject) const
|
||||
{
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] constexpr raw_directive<as_parser_plain_t<Subject>>
|
||||
operator[](Subject&& subject) const
|
||||
noexcept(is_parser_nothrow_constructible_v<raw_directive<as_parser_plain_t<Subject>>, as_parser_t<Subject>>)
|
||||
{
|
||||
return { as_parser(std::forward<Subject>(subject)) };
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
return { as_parser(subject) };
|
||||
}
|
||||
};
|
||||
|
||||
inline namespace cpos
|
||||
{
|
||||
inline constexpr detail::raw_gen raw{};
|
||||
}
|
||||
constexpr auto raw = raw_gen{};
|
||||
|
||||
namespace traits
|
||||
{
|
||||
template <typename Context, std::forward_iterator It>
|
||||
struct pseudo_attribute<Context, raw_attribute_type, It>
|
||||
template <typename Context, typename Iterator>
|
||||
struct pseudo_attribute<Context, raw_attribute_type, Iterator>
|
||||
{
|
||||
using attribute_type = raw_attribute_type;
|
||||
#ifdef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
|
||||
using type = std::ranges::subrange<It>;
|
||||
#else
|
||||
using type = boost::iterator_range<It>;
|
||||
#endif
|
||||
using type = boost::iterator_range<Iterator>;
|
||||
|
||||
[[nodiscard]] static constexpr type call(It& first, std::sentinel_for<It> auto const& last, raw_attribute_type)
|
||||
static type call(Iterator& first, Iterator const& last, attribute_type)
|
||||
{
|
||||
return { first, last };
|
||||
}
|
||||
};
|
||||
}
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2014 Thomas Bernard
|
||||
Copyright (c) 2017 wanghan02
|
||||
Copyright (c) 2024-2025 Nana Sakisaka
|
||||
Copyright (c) 2024 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -15,192 +15,144 @@
|
||||
#include <boost/spirit/home/x3/operator/kleene.hpp>
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
template <std::integral T>
|
||||
template <typename T>
|
||||
struct exact_count // handles repeat(exact)[p]
|
||||
{
|
||||
using value_type = T;
|
||||
[[nodiscard]] constexpr bool got_max(T i) const noexcept { return i >= exact_value; }
|
||||
[[nodiscard]] constexpr bool got_min(T i) const noexcept { return i >= exact_value; }
|
||||
typedef T type;
|
||||
bool got_max(T i) const { return i >= exact_value; }
|
||||
bool got_min(T i) const { return i >= exact_value; }
|
||||
|
||||
T exact_value;
|
||||
T const exact_value;
|
||||
};
|
||||
|
||||
template <std::integral T>
|
||||
template <typename T>
|
||||
struct finite_count // handles repeat(min, max)[p]
|
||||
{
|
||||
using value_type = T;
|
||||
[[nodiscard]] constexpr bool got_max(T i) const noexcept { return i >= max_value; }
|
||||
[[nodiscard]] constexpr bool got_min(T i) const noexcept { return i >= min_value; }
|
||||
typedef T type;
|
||||
bool got_max(T i) const { return i >= max_value; }
|
||||
bool got_min(T i) const { return i >= min_value; }
|
||||
|
||||
T min_value;
|
||||
T max_value;
|
||||
T const min_value;
|
||||
T const max_value;
|
||||
};
|
||||
|
||||
template <std::integral T>
|
||||
template <typename T>
|
||||
struct infinite_count // handles repeat(min, inf)[p]
|
||||
{
|
||||
using value_type = T;
|
||||
[[nodiscard]] constexpr bool got_max(T /*i*/) const noexcept { return false; }
|
||||
[[nodiscard]] constexpr bool got_min(T i) const noexcept { return i >= min_value; }
|
||||
typedef T type;
|
||||
bool got_max(T /*i*/) const { return false; }
|
||||
bool got_min(T i) const { return i >= min_value; }
|
||||
|
||||
T min_value;
|
||||
T const min_value;
|
||||
};
|
||||
} // boost::spirit::x3::detail
|
||||
}}}}
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
namespace detail
|
||||
template<typename Subject, typename RepeatCountLimit>
|
||||
struct repeat_directive : unary_parser<Subject, repeat_directive<Subject,RepeatCountLimit>>
|
||||
{
|
||||
template <typename Bounds>
|
||||
concept RepeatBounds = requires(std::remove_cvref_t<Bounds> const& bounds) {
|
||||
typename std::remove_cvref_t<Bounds>::value_type;
|
||||
{ bounds.got_max(std::declval<typename std::remove_cvref_t<Bounds>::value_type>()) } -> std::same_as<bool>;
|
||||
{ bounds.got_min(std::declval<typename std::remove_cvref_t<Bounds>::value_type>()) } -> std::same_as<bool>;
|
||||
};
|
||||
} // detail
|
||||
typedef unary_parser<Subject, repeat_directive<Subject,RepeatCountLimit>> base_type;
|
||||
static bool const is_pass_through_unary = true;
|
||||
static bool const handles_container = true;
|
||||
|
||||
template <typename Subject, detail::RepeatBounds Bounds>
|
||||
struct repeat_directive : unary_parser<Subject, repeat_directive<Subject, Bounds>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, repeat_directive<Subject, Bounds>>;
|
||||
static constexpr bool is_pass_through_unary = true;
|
||||
static constexpr bool handles_container = true;
|
||||
|
||||
template <typename SubjectT, detail::RepeatBounds BoundsT>
|
||||
requires std::is_constructible_v<base_type, SubjectT> && std::is_constructible_v<Bounds, BoundsT>
|
||||
constexpr repeat_directive(SubjectT&& subject, BoundsT&& bounds)
|
||||
noexcept(std::is_nothrow_constructible_v<base_type, SubjectT> && std::is_nothrow_constructible_v<Bounds, BoundsT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
, bounds_(std::forward<BoundsT>(bounds))
|
||||
constexpr repeat_directive(Subject const& subject, RepeatCountLimit const& repeat_limit_)
|
||||
: base_type(subject)
|
||||
, repeat_limit(repeat_limit_)
|
||||
{}
|
||||
|
||||
template<std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
// never noexcept (requires container insertion)
|
||||
template<typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse(
|
||||
Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
It local_it = first;
|
||||
typename Bounds::value_type i{};
|
||||
for (; !bounds_.got_min(i); ++i)
|
||||
Iterator local_iterator = first;
|
||||
typename RepeatCountLimit::type i{};
|
||||
for (/**/; !repeat_limit.got_min(i); ++i)
|
||||
{
|
||||
if (!detail::parse_into_container(this->subject, local_it, last, context, rcontext, attr))
|
||||
{
|
||||
if (!detail::parse_into_container(
|
||||
this->subject, local_iterator, last, context, rcontext, attr))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
first = local_it;
|
||||
first = local_iterator;
|
||||
// parse some more up to the maximum specified
|
||||
for (; !bounds_.got_max(i); ++i)
|
||||
for (/**/; !repeat_limit.got_max(i); ++i)
|
||||
{
|
||||
if (!detail::parse_into_container(this->subject, first, last, context, rcontext, attr))
|
||||
{
|
||||
if (!detail::parse_into_container(
|
||||
this->subject, first, last, context, rcontext, attr))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return !x3::has_expectation_failure(context);
|
||||
return !has_expectation_failure(context);
|
||||
}
|
||||
|
||||
private:
|
||||
Bounds bounds_;
|
||||
RepeatCountLimit repeat_limit;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
// Infinite loop tag type
|
||||
struct inf_type {};
|
||||
constexpr inf_type inf = inf_type();
|
||||
|
||||
struct repeat_gen
|
||||
{
|
||||
// Infinite loop tag type
|
||||
struct repeat_inf_type
|
||||
template<typename Subject>
|
||||
constexpr auto operator[](Subject const& subject) const
|
||||
{
|
||||
constexpr explicit repeat_inf_type() noexcept = default;
|
||||
};
|
||||
} // detail
|
||||
return *as_parser(subject);
|
||||
}
|
||||
|
||||
inline namespace cpos
|
||||
{
|
||||
// Infinite loop tag type
|
||||
[[deprecated("Use `x3::repeat_inf`")]]
|
||||
inline constexpr detail::repeat_inf_type inf{};
|
||||
|
||||
// Infinite loop tag type
|
||||
inline constexpr detail::repeat_inf_type repeat_inf{};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct repeat_gen
|
||||
template <typename T>
|
||||
struct repeat_gen_lvl1
|
||||
{
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard, deprecated("`repeat[p]` has the exact same meaning as `*p`. Use `*p` instead.")]]
|
||||
constexpr auto operator[](Subject&& subject) const
|
||||
noexcept(noexcept(*as_parser(std::forward<Subject>(subject))))
|
||||
constexpr repeat_gen_lvl1(T&& repeat_limit_)
|
||||
: repeat_limit(repeat_limit_)
|
||||
{}
|
||||
|
||||
template<typename Subject>
|
||||
constexpr repeat_directive< typename extension::as_parser<Subject>::value_type, T>
|
||||
operator[](Subject const& subject) const
|
||||
{
|
||||
return *as_parser(std::forward<Subject>(subject));
|
||||
return { as_parser(subject),repeat_limit };
|
||||
}
|
||||
|
||||
template <RepeatBounds Bounds>
|
||||
struct [[nodiscard]] repeat_gen_impl
|
||||
{
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] constexpr repeat_directive<as_parser_plain_t<Subject>, Bounds>
|
||||
operator[](Subject&& subject) const
|
||||
noexcept(
|
||||
is_parser_nothrow_castable_v<Subject> &&
|
||||
std::is_nothrow_constructible_v<
|
||||
repeat_directive<as_parser_plain_t<Subject>, Bounds>,
|
||||
as_parser_t<Subject>,
|
||||
Bounds const&
|
||||
>
|
||||
)
|
||||
{
|
||||
return { as_parser(std::forward<Subject>(subject)), bounds };
|
||||
}
|
||||
|
||||
Bounds bounds;
|
||||
};
|
||||
|
||||
template <std::integral T>
|
||||
static constexpr repeat_gen_impl<exact_count<T>>
|
||||
operator()(T const exact) noexcept
|
||||
{
|
||||
return { exact_count<T>{exact} };
|
||||
}
|
||||
|
||||
template <std::integral T>
|
||||
static constexpr repeat_gen_impl<finite_count<T>>
|
||||
operator()(T const min_val, T const max_val) noexcept
|
||||
{
|
||||
return { finite_count<T>{min_val, max_val} };
|
||||
}
|
||||
|
||||
template <std::integral T>
|
||||
static constexpr repeat_gen_impl<infinite_count<T>>
|
||||
operator()(T const min_val, repeat_inf_type const&) noexcept
|
||||
{
|
||||
return { infinite_count<T>{min_val} };
|
||||
}
|
||||
T repeat_limit;
|
||||
};
|
||||
} // detail
|
||||
|
||||
inline namespace cpos
|
||||
{
|
||||
inline constexpr detail::repeat_gen repeat{};
|
||||
}
|
||||
template <typename T>
|
||||
constexpr repeat_gen_lvl1<detail::exact_count<T>>
|
||||
operator()(T const exact) const
|
||||
{
|
||||
return { detail::exact_count<T>{exact} };
|
||||
}
|
||||
|
||||
} // boost::spirit::x3
|
||||
template <typename T>
|
||||
constexpr repeat_gen_lvl1<detail::finite_count<T>>
|
||||
operator()(T const min_val, T const max_val) const
|
||||
{
|
||||
return { detail::finite_count<T>{min_val,max_val} };
|
||||
}
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
template <typename T>
|
||||
constexpr repeat_gen_lvl1<detail::infinite_count<T>>
|
||||
operator()(T const min_val, inf_type const &) const
|
||||
{
|
||||
return { detail::infinite_count<T>{min_val} };
|
||||
}
|
||||
};
|
||||
|
||||
constexpr auto repeat = repeat_gen{};
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename Subject, typename Bounds, typename Context>
|
||||
struct attribute_of<x3::repeat_directive<Subject, Bounds>, Context>
|
||||
: build_container<attribute_of_t<Subject, Context>>
|
||||
{};
|
||||
} // boost::spirit::x3::traits
|
||||
template <typename Subject, typename RepeatCountLimit, typename Context>
|
||||
struct attribute_of<x3::repeat_directive<Subject,RepeatCountLimit>, Context>
|
||||
: build_container<typename attribute_of<Subject, Context>::type> {};
|
||||
}}}}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013 Agustin Berge
|
||||
Copyright (c) 2024-2025 Nana Sakisaka
|
||||
Copyright (c) 2024 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -14,94 +14,67 @@
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
#include <boost/spirit/home/x3/core/skip_over.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Subject>
|
||||
struct reskip_directive : unary_parser<Subject, reskip_directive<Subject>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, reskip_directive<Subject>>;
|
||||
static constexpr bool is_pass_through_unary = true;
|
||||
static constexpr bool handles_container = Subject::handles_container;
|
||||
typedef unary_parser<Subject, reskip_directive<Subject>> base_type;
|
||||
static bool const is_pass_through_unary = true;
|
||||
static bool const handles_container = Subject::handles_container;
|
||||
|
||||
template <typename SubjectT>
|
||||
requires
|
||||
(!std::is_same_v<std::remove_cvref_t<SubjectT>, reskip_directive>) &&
|
||||
std::is_constructible_v<Subject, SubjectT>
|
||||
constexpr reskip_directive(SubjectT&& subject)
|
||||
noexcept(std::is_nothrow_constructible_v<Subject, SubjectT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
{}
|
||||
constexpr reskip_directive(Subject const& subject)
|
||||
: base_type(subject) {}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires has_skipper_v<Context>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
noexcept(is_nothrow_parsable_v<Subject, It, Se, Context, RContext, Attribute>)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
typename disable_if<has_skipper<Context>, bool>::type
|
||||
parse(Iterator& first, Iterator const& last
|
||||
, Context& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
static_assert(Parsable<Subject, It, Se, Context, RContext, Attribute>);
|
||||
return this->subject.parse(first, last, context, rcontext, attr);
|
||||
}
|
||||
auto const& skipper =
|
||||
detail::get_unused_skipper(x3::get<skipper_tag>(context));
|
||||
|
||||
private:
|
||||
template <typename Context>
|
||||
using context_t = x3::context<
|
||||
skipper_tag,
|
||||
decltype(detail::get_unused_skipper(x3::get<skipper_tag>(std::declval<Context const&>()))),
|
||||
Context
|
||||
>;
|
||||
|
||||
public:
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires (!has_skipper_v<Context>)
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
// never noexcept (requires expectation failure modification)
|
||||
{
|
||||
static_assert(Parsable<Subject, It, Se, context_t<Context>, RContext, Attribute>);
|
||||
|
||||
auto const& skipper = detail::get_unused_skipper(x3::get<skipper_tag>(context));
|
||||
|
||||
auto const local_ctx = x3::make_context<skipper_tag>(skipper, context);
|
||||
auto const local_ctx = make_context<skipper_tag>(skipper, context);
|
||||
bool const r = this->subject.parse(first, last, local_ctx, rcontext, attr);
|
||||
|
||||
#if !BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
if (x3::has_expectation_failure(local_ctx))
|
||||
if (has_expectation_failure(local_ctx))
|
||||
{
|
||||
x3::set_expectation_failure(x3::get_expectation_failure(local_ctx), context);
|
||||
set_expectation_failure(get_expectation_failure(local_ctx), context);
|
||||
}
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
typename enable_if<has_skipper<Context>, bool>::type
|
||||
parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
return this->subject.parse(first, last, context, rcontext, attr);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Subject, typename Skipper>
|
||||
struct skip_directive : unary_parser<Subject, skip_directive<Subject, Skipper>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, skip_directive<Subject, Skipper>>;
|
||||
static constexpr bool is_pass_through_unary = true;
|
||||
static constexpr bool handles_container = Subject::handles_container;
|
||||
typedef unary_parser<Subject, skip_directive<Subject, Skipper>> base_type;
|
||||
static bool const is_pass_through_unary = true;
|
||||
static bool const handles_container = Subject::handles_container;
|
||||
|
||||
template <typename SubjectT, typename SkipperT>
|
||||
requires std::is_constructible_v<Subject, SubjectT> && std::is_constructible_v<Skipper, SkipperT>
|
||||
constexpr skip_directive(SubjectT&& subject, SkipperT&& skipper)
|
||||
noexcept(std::is_nothrow_constructible_v<Subject, SubjectT> && std::is_nothrow_constructible_v<Skipper, SkipperT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
, skipper_(skipper)
|
||||
constexpr skip_directive(Subject const& subject, Skipper const& skipper)
|
||||
: base_type(subject)
|
||||
, skipper(skipper)
|
||||
{}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, unused_type const&, RContext& rcontext, Attribute& attr) const
|
||||
noexcept(is_nothrow_parsable_v<Subject, It, Se, x3::context<skipper_tag, Skipper>, RContext, Attribute>)
|
||||
template <typename Iterator, typename RContext, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, unused_type const&, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
static_assert(Parsable<Subject, It, Se, x3::context<skipper_tag, Skipper>, RContext, Attribute>);
|
||||
|
||||
// It is perfectly fine to omit the expectation_failure context
|
||||
// even in non-throwing mode if and only if the skipper itself
|
||||
// is expectation-less.
|
||||
@@ -121,126 +94,73 @@ namespace boost::spirit::x3
|
||||
// Anyways, we don't need to repack the expectation context
|
||||
// into our brand new skipper context, in contrast to the
|
||||
// repacking process done in `x3::skip_over`.
|
||||
return this->subject.parse(
|
||||
first, last, x3::make_context<skipper_tag>(skipper_), rcontext, attr
|
||||
);
|
||||
return this->subject.parse(first, last,
|
||||
make_context<skipper_tag>(skipper), rcontext, attr);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
// never noexcept (requires expectation failure modification)
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
static_assert(Parsable<Subject, It, Se, x3::context<skipper_tag, Context>, RContext, Attribute>);
|
||||
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
return this->subject.parse(first, last, x3::make_context<skipper_tag>(skipper_, context), rcontext, attr);
|
||||
return this->subject.parse(first, last, make_context<skipper_tag>(skipper, context), rcontext, attr);
|
||||
|
||||
#else
|
||||
static_assert(
|
||||
!std::is_same_v<expectation_failure_t<Context>, unused_type>,
|
||||
"Context type was not specified for x3::expectation_failure_tag. "
|
||||
"You probably forgot: `x3::with<x3::expectation_failure_tag>(failure)[p]`. "
|
||||
"Note that you must also bind the context to your skipper."
|
||||
);
|
||||
"Note that you must also bind the context to your skipper.");
|
||||
|
||||
// This logic is heavily related to the instantiation chain;
|
||||
// see `x3::skip_over` for details.
|
||||
auto const local_ctx = x3::make_context<skipper_tag>(skipper_, context);
|
||||
auto const local_ctx = make_context<skipper_tag>(skipper, context);
|
||||
bool const r = this->subject.parse(first, last, local_ctx, rcontext, attr);
|
||||
|
||||
if (x3::has_expectation_failure(local_ctx))
|
||||
if (has_expectation_failure(local_ctx))
|
||||
{
|
||||
x3::set_expectation_failure(x3::get_expectation_failure(local_ctx), context);
|
||||
set_expectation_failure(get_expectation_failure(local_ctx), context);
|
||||
}
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
Skipper skipper_;
|
||||
Skipper const skipper;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
struct reskip_gen
|
||||
{
|
||||
template <X3Subject Skipper>
|
||||
struct skip_gen_impl
|
||||
{
|
||||
// Unreference rvalue reference, but hold lvalue reference as-is
|
||||
using skipper_type = std::conditional_t<
|
||||
std::is_rvalue_reference_v<Skipper>,
|
||||
std::remove_reference_t<Skipper>,
|
||||
Skipper
|
||||
>;
|
||||
|
||||
template <typename SkipperT>
|
||||
requires std::is_same_v<std::remove_cvref_t<SkipperT>, std::remove_cvref_t<Skipper>>
|
||||
constexpr skip_gen_impl(SkipperT&& skipper)
|
||||
noexcept(std::is_nothrow_constructible_v<skipper_type, SkipperT>)
|
||||
: skipper_(std::forward<SkipperT>(skipper))
|
||||
{}
|
||||
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] constexpr skip_directive<as_parser_plain_t<Subject>, std::remove_cvref_t<Skipper>>
|
||||
operator[](Subject&& subject) const
|
||||
noexcept(
|
||||
is_parser_nothrow_castable_v<Subject> &&
|
||||
std::is_nothrow_constructible_v<
|
||||
skip_directive<as_parser_plain_t<Subject>, std::remove_cvref_t<Skipper>>,
|
||||
as_parser_t<Subject>,
|
||||
skipper_type const&
|
||||
>
|
||||
)
|
||||
{
|
||||
return { as_parser(std::forward<Subject>(subject)), skipper_ };
|
||||
}
|
||||
|
||||
private:
|
||||
skipper_type skipper_;
|
||||
};
|
||||
|
||||
template <typename Skipper>
|
||||
struct skip_gen
|
||||
{
|
||||
template <X3Subject Skipper>
|
||||
[[nodiscard]]
|
||||
static constexpr skip_gen_impl<as_parser_t<Skipper>>
|
||||
operator()(Skipper&& skipper)
|
||||
noexcept(
|
||||
is_parser_nothrow_castable_v<Skipper> &&
|
||||
std::is_nothrow_constructible_v<skip_gen_impl<as_parser_t<Skipper>>, as_parser_t<Skipper>>
|
||||
)
|
||||
{
|
||||
return { as_parser(std::forward<Skipper>(skipper)) };
|
||||
}
|
||||
constexpr skip_gen(Skipper const& skipper)
|
||||
: skipper_(skipper) {}
|
||||
|
||||
template <typename Subject>
|
||||
[[nodiscard, deprecated("Use `x3::reskip[p]`.")]]
|
||||
/* static */ constexpr reskip_directive<as_parser_plain_t<Subject>>
|
||||
operator[](Subject&& subject) const // MSVC 2022 bug: cannot define `static operator[]` even in C++26 mode
|
||||
noexcept(is_parser_nothrow_constructible_v<reskip_directive<as_parser_plain_t<Subject>>, Subject>)
|
||||
constexpr skip_directive<typename extension::as_parser<Subject>::value_type, Skipper>
|
||||
operator[](Subject const& subject) const
|
||||
{
|
||||
return { as_parser(std::forward<Subject>(subject)) };
|
||||
return { as_parser(subject), skipper_ };
|
||||
}
|
||||
|
||||
Skipper skipper_;
|
||||
};
|
||||
|
||||
struct reskip_gen
|
||||
template <typename Skipper>
|
||||
constexpr skip_gen<Skipper> const operator()(Skipper const& skipper) const
|
||||
{
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]]
|
||||
/* static */ constexpr reskip_directive<as_parser_plain_t<Subject>>
|
||||
operator[](Subject&& subject) const // MSVC 2022 bug: cannot define `static operator[]` even in C++26 mode
|
||||
noexcept(is_parser_nothrow_constructible_v<reskip_directive<as_parser_plain_t<Subject>>, Subject>)
|
||||
{
|
||||
return { as_parser(std::forward<Subject>(subject)) };
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
return { skipper };
|
||||
}
|
||||
|
||||
inline namespace cpos
|
||||
{
|
||||
inline constexpr detail::skip_gen skip{};
|
||||
inline constexpr detail::reskip_gen reskip{};
|
||||
}
|
||||
} // boost::spirit::x3
|
||||
template <typename Subject>
|
||||
constexpr reskip_directive<typename extension::as_parser<Subject>::value_type>
|
||||
operator[](Subject const& subject) const
|
||||
{
|
||||
return { as_parser(subject) };
|
||||
}
|
||||
};
|
||||
|
||||
constexpr auto skip = reskip_gen{};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -11,201 +10,77 @@
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Subject, typename ID, typename T>
|
||||
struct with_directive;
|
||||
|
||||
namespace detail
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// with directive injects a value into the context prior to parsing.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Subject, typename Derived, typename T>
|
||||
struct with_value_holder
|
||||
: unary_parser<Subject, Derived>
|
||||
{
|
||||
template <typename Subject, typename ID, typename T>
|
||||
struct with_directive_impl
|
||||
: unary_parser<Subject, with_directive<Subject, ID, T>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, with_directive<Subject, ID, T>>;
|
||||
mutable T val_;
|
||||
|
||||
template <typename SubjectT, typename U>
|
||||
requires
|
||||
std::is_constructible_v<Subject, SubjectT> &&
|
||||
std::is_constructible_v<T, U>
|
||||
constexpr with_directive_impl(SubjectT&& subject, U&& val)
|
||||
noexcept(
|
||||
std::is_nothrow_constructible_v<Subject, SubjectT> &&
|
||||
std::is_nothrow_constructible_v<T, U>
|
||||
)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
, val_(std::forward<U>(val))
|
||||
{}
|
||||
};
|
||||
|
||||
template <typename Subject, typename ID, typename T>
|
||||
struct with_directive_impl<Subject, ID, T const>
|
||||
: unary_parser<Subject, with_directive<Subject, ID, T const>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, with_directive<Subject, ID, T const>>;
|
||||
/* not mutable */ T const val_;
|
||||
|
||||
template <typename SubjectT, typename U>
|
||||
requires
|
||||
std::is_constructible_v<Subject, SubjectT> &&
|
||||
std::is_constructible_v<T const, U>
|
||||
constexpr with_directive_impl(SubjectT&& subject, U&& val)
|
||||
noexcept(
|
||||
std::is_nothrow_constructible_v<Subject, SubjectT> &&
|
||||
std::is_nothrow_constructible_v<T const, U>
|
||||
)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
, val_(std::forward<U>(val))
|
||||
{}
|
||||
};
|
||||
|
||||
template <typename Subject, typename ID, typename T>
|
||||
struct with_directive_impl<Subject, ID, T&>
|
||||
: unary_parser<Subject, with_directive<Subject, ID, T&>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, with_directive<Subject, ID, T&>>;
|
||||
T& val_;
|
||||
|
||||
template <typename SubjectT, typename U>
|
||||
requires
|
||||
std::is_constructible_v<Subject, SubjectT> &&
|
||||
std::is_constructible_v<T&, U&>
|
||||
constexpr with_directive_impl(SubjectT&& subject, U& val)
|
||||
noexcept(std::is_nothrow_constructible_v<Subject, SubjectT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
, val_(val)
|
||||
{}
|
||||
};
|
||||
} // detail
|
||||
|
||||
// `with` directive injects a value into the context prior to parsing.
|
||||
// Holds lvalue references by reference, holds rvalue reference by value.
|
||||
template <typename Subject, typename ID, typename T>
|
||||
struct with_directive : detail::with_directive_impl<Subject, ID, T>
|
||||
typedef unary_parser<Subject, Derived> base_type;
|
||||
mutable T val;
|
||||
constexpr with_value_holder(Subject const& subject, T&& val)
|
||||
: base_type(subject)
|
||||
, val(std::forward<T>(val)) {}
|
||||
};
|
||||
|
||||
template <typename Subject, typename Derived, typename T>
|
||||
struct with_value_holder<Subject, Derived, T&>
|
||||
: unary_parser<Subject, Derived>
|
||||
{
|
||||
static_assert(
|
||||
!std::is_rvalue_reference_v<T>,
|
||||
"`x3::with`: rvalue reference is prohibited to prevent dangling reference"
|
||||
);
|
||||
|
||||
static_assert(
|
||||
std::is_lvalue_reference_v<T> || std::is_move_constructible_v<T>,
|
||||
"Passing an rvalue to `x3::with` requires the type to be move-constructible "
|
||||
"so it can be stored by value."
|
||||
);
|
||||
|
||||
using subject_type = Subject;
|
||||
using id_type = ID;
|
||||
using value_type = T;
|
||||
using base_type = detail::with_directive_impl<Subject, ID, T>;
|
||||
|
||||
static constexpr bool is_pass_through_unary = true;
|
||||
static constexpr bool handles_container = Subject::handles_container;
|
||||
|
||||
template <typename SubjectT, typename U>
|
||||
requires std::is_constructible_v<base_type, SubjectT, U>
|
||||
constexpr with_directive(SubjectT&& subject, U&& val)
|
||||
noexcept(std::is_nothrow_constructible_v<base_type, SubjectT, U>)
|
||||
: base_type(std::forward<SubjectT>(subject), std::forward<U>(val))
|
||||
{}
|
||||
|
||||
// The internal context type. This can be used to determine the composed
|
||||
// context type used in `x3::parse`/`x3::phrase_parse`. It is required for
|
||||
// the argument of `BOOST_SPIRIT_X3_INSTANTIATE`.
|
||||
template <typename Context>
|
||||
using context_t = context<ID, std::remove_reference_t<T>, Context>;
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
noexcept(is_nothrow_parsable_v<Subject, It, Se, context_t<Context>, RContext, Attribute>)
|
||||
{
|
||||
static_assert(Parsable<Subject, It, Se, context_t<Context>, RContext, Attribute>);
|
||||
return this->subject.parse(
|
||||
first, last,
|
||||
x3::make_context<ID>(this->val_, context),
|
||||
rcontext, attr
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
using base_type::val_;
|
||||
typedef unary_parser<Subject, Derived> base_type;
|
||||
T& val;
|
||||
constexpr with_value_holder(Subject const& subject, T& val)
|
||||
: base_type(subject)
|
||||
, val(val) {}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
template <typename Subject, typename ID, typename T>
|
||||
struct with_directive
|
||||
: with_value_holder<Subject, with_directive<Subject, ID, T>, T>
|
||||
{
|
||||
template <typename ID, typename T>
|
||||
struct [[nodiscard]] with_gen
|
||||
typedef with_value_holder<Subject, with_directive<Subject, ID, T>, T> base_type;
|
||||
static bool const is_pass_through_unary = true;
|
||||
static bool const handles_container = Subject::handles_container;
|
||||
|
||||
typedef Subject subject_type;
|
||||
|
||||
constexpr with_directive(Subject const& subject, T&& val)
|
||||
: base_type(subject, std::forward<T>(val)) {}
|
||||
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
static_assert(!std::is_rvalue_reference_v<T>);
|
||||
T val;
|
||||
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] constexpr with_directive<as_parser_plain_t<Subject>, ID, T>
|
||||
operator[](Subject&& subject) &&
|
||||
noexcept(
|
||||
is_parser_nothrow_castable_v<Subject> &&
|
||||
std::is_nothrow_constructible_v<
|
||||
with_directive<as_parser_plain_t<Subject>, ID, T>,
|
||||
as_parser_t<Subject>,
|
||||
T&& // lvalue or rvalue, forwarded
|
||||
>
|
||||
)
|
||||
{
|
||||
// with rvalue `with_gen`, the held value can always be forwarded
|
||||
return { as_parser(std::forward<Subject>(subject)), std::forward<T>(val) };
|
||||
}
|
||||
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] constexpr with_directive<as_parser_plain_t<Subject>, ID, T>
|
||||
operator[](Subject&& subject) const&
|
||||
noexcept(
|
||||
is_parser_nothrow_castable_v<Subject> &&
|
||||
std::is_nothrow_constructible_v<
|
||||
with_directive<as_parser_plain_t<Subject>, ID, T>,
|
||||
as_parser_t<Subject>,
|
||||
T& // lvalue
|
||||
>
|
||||
)
|
||||
{
|
||||
static_assert(
|
||||
std::is_lvalue_reference_v<T> || std::is_copy_constructible_v<T>,
|
||||
"When you have passed an rvalue to `x3::with` and saved the functor "
|
||||
"as a local variable, it requires the held type to be copy-constructible. "
|
||||
"If your type is move only, then apply `std::move` to your `x3::with<ID>(val)` "
|
||||
"instance."
|
||||
);
|
||||
return { as_parser(std::forward<Subject>(subject)), val };
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ID>
|
||||
struct with_fn
|
||||
{
|
||||
template <typename T>
|
||||
static constexpr with_gen<ID, T> operator()(T&& val)
|
||||
noexcept(
|
||||
std::is_lvalue_reference_v<T> ||
|
||||
std::is_nothrow_move_constructible_v<T>
|
||||
)
|
||||
{
|
||||
return { std::forward<T>(val) };
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
|
||||
inline namespace cpos
|
||||
return this->subject.parse(
|
||||
first, last
|
||||
, make_context<ID>(this->val, context)
|
||||
, rcontext
|
||||
, attr);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ID, typename T>
|
||||
struct with_gen
|
||||
{
|
||||
// `with` directive injects a value into the context prior to parsing.
|
||||
// Holds lvalue references by reference, holds rvalue reference by value.
|
||||
template <typename ID>
|
||||
inline constexpr detail::with_fn<ID> with{};
|
||||
} // cpos
|
||||
} // boost::spirit::x3
|
||||
T&& val;
|
||||
|
||||
template <typename Subject>
|
||||
constexpr with_directive<typename extension::as_parser<Subject>::value_type, ID, T>
|
||||
operator[](Subject const& subject) const
|
||||
{
|
||||
return { as_parser(subject), std::forward<T>(val) };
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ID, typename T>
|
||||
constexpr with_gen<ID, T> with(T&& val)
|
||||
{
|
||||
return { std::forward<T>(val) };
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
370
include/boost/spirit/home/x3/nonterminal/detail/rule.hpp
Normal file
370
include/boost/spirit/home/x3/nonterminal/detail/rule.hpp
Normal file
@@ -0,0 +1,370 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2017 wanghan02
|
||||
Copyright (c) 2024 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_X3_DETAIL_RULE_JAN_08_2012_0326PM)
|
||||
#define BOOST_SPIRIT_X3_DETAIL_RULE_JAN_08_2012_0326PM
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/spirit/home/x3/auxiliary/guard.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/skip_over.hpp>
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
#include <boost/spirit/home/x3/directive/expect.hpp>
|
||||
#include <boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
|
||||
#if defined(BOOST_SPIRIT_X3_DEBUG)
|
||||
#include <boost/spirit/home/x3/nonterminal/simple_trace.hpp>
|
||||
#endif
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename ID>
|
||||
struct identity;
|
||||
|
||||
template <typename ID, typename Attribute = unused_type, bool force_attribute = false>
|
||||
struct rule;
|
||||
|
||||
struct parse_pass_context_tag;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename ID>
|
||||
struct rule_id {};
|
||||
|
||||
// we use this so we can detect if the default parse_rule
|
||||
// is the being called.
|
||||
struct default_parse_rule_result
|
||||
{
|
||||
default_parse_rule_result(bool r)
|
||||
: r(r) {}
|
||||
operator bool() const { return r; }
|
||||
bool r;
|
||||
};
|
||||
}
|
||||
|
||||
// default parse_rule implementation
|
||||
template <typename ID, typename Iterator
|
||||
, typename Context, typename ActualAttribute>
|
||||
inline detail::default_parse_rule_result
|
||||
parse_rule(
|
||||
detail::rule_id<ID>
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, ActualAttribute& attr);
|
||||
}}}
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
#if defined(BOOST_SPIRIT_X3_DEBUG)
|
||||
template <typename Iterator, typename Attribute>
|
||||
struct context_debug
|
||||
{
|
||||
context_debug(
|
||||
char const* rule_name
|
||||
, Iterator const& first, Iterator const& last
|
||||
, Attribute const& attr
|
||||
, bool const& ok_parse //was parse successful?
|
||||
)
|
||||
: ok_parse(ok_parse), rule_name(rule_name)
|
||||
, first(first), last(last)
|
||||
, attr(attr)
|
||||
, f(detail::get_simple_trace())
|
||||
{
|
||||
f(first, last, attr, pre_parse, rule_name);
|
||||
}
|
||||
|
||||
~context_debug()
|
||||
{
|
||||
auto status = ok_parse ? successful_parse : failed_parse ;
|
||||
f(first, last, attr, status, rule_name);
|
||||
}
|
||||
|
||||
bool const& ok_parse;
|
||||
char const* rule_name;
|
||||
Iterator const& first;
|
||||
Iterator const& last;
|
||||
Attribute const& attr;
|
||||
detail::simple_trace_type& f;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename ID, typename Iterator, typename Context, typename Enable = void>
|
||||
struct has_on_error : mpl::false_ {};
|
||||
|
||||
template <typename ID, typename Iterator, typename Context>
|
||||
struct has_on_error<ID, Iterator, Context,
|
||||
decltype(void(
|
||||
std::declval<ID>().on_error(
|
||||
std::declval<Iterator&>()
|
||||
, std::declval<Iterator>()
|
||||
, std::declval<expectation_failure<Iterator>>()
|
||||
, std::declval<Context>()
|
||||
)
|
||||
))
|
||||
>
|
||||
: mpl::true_
|
||||
{};
|
||||
|
||||
template <typename ID, typename Iterator, typename Attribute, typename Context, typename Enable = void>
|
||||
struct has_on_success : mpl::false_ {};
|
||||
|
||||
template <typename ID, typename Iterator, typename Attribute, typename Context>
|
||||
struct has_on_success<ID, Iterator, Context, Attribute,
|
||||
decltype(void(
|
||||
std::declval<ID>().on_success(
|
||||
std::declval<Iterator&>()
|
||||
, std::declval<Iterator&>()
|
||||
, std::declval<Attribute&>()
|
||||
, std::declval<Context>()
|
||||
)
|
||||
))
|
||||
>
|
||||
: mpl::true_
|
||||
{};
|
||||
|
||||
template <typename ID>
|
||||
struct make_id
|
||||
{
|
||||
typedef identity<ID> type;
|
||||
};
|
||||
|
||||
template <typename ID>
|
||||
struct make_id<identity<ID>>
|
||||
{
|
||||
typedef identity<ID> type;
|
||||
};
|
||||
|
||||
template <typename ID, typename RHS, typename Context>
|
||||
Context const&
|
||||
make_rule_context(RHS const& /* rhs */, Context const& context
|
||||
, mpl::false_ /* is_default_parse_rule */)
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
template <typename ID, typename RHS, typename Context>
|
||||
auto make_rule_context(RHS const& rhs, Context const& context
|
||||
, mpl::true_ /* is_default_parse_rule */ )
|
||||
{
|
||||
return make_unique_context<ID>(rhs, context);
|
||||
}
|
||||
|
||||
template <typename Attribute, typename ID, bool skip_definition_injection = false>
|
||||
struct rule_parser
|
||||
{
|
||||
template <typename Iterator, typename Context, typename ActualAttribute>
|
||||
static bool call_on_success(
|
||||
Iterator& /* before */, Iterator& /* after */
|
||||
, Context const& /* context */, ActualAttribute& /* attr */
|
||||
, mpl::false_ /* No on_success handler */ )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Context, typename ActualAttribute>
|
||||
static bool call_on_success(
|
||||
Iterator& before, Iterator& after
|
||||
, Context const& context, ActualAttribute& attr
|
||||
, mpl::true_ /* Has on_success handler */)
|
||||
{
|
||||
x3::skip_over(before, after, context);
|
||||
bool pass = true;
|
||||
ID().on_success(
|
||||
before
|
||||
, after
|
||||
, attr
|
||||
, make_context<parse_pass_context_tag>(pass, context)
|
||||
);
|
||||
return pass;
|
||||
}
|
||||
|
||||
template <typename RHS, typename Iterator, typename Context
|
||||
, typename RContext, typename ActualAttribute>
|
||||
static bool parse_rhs_main(
|
||||
RHS const& rhs
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, ActualAttribute& attr
|
||||
, mpl::false_)
|
||||
{
|
||||
// see if the user has a BOOST_SPIRIT_DEFINE for this rule
|
||||
typedef
|
||||
decltype(parse_rule(
|
||||
detail::rule_id<ID>{}, first, last
|
||||
, make_unique_context<ID>(rhs, context), std::declval<Attribute&>()))
|
||||
parse_rule_result;
|
||||
|
||||
// If there is no BOOST_SPIRIT_DEFINE for this rule,
|
||||
// we'll make a context for this rule tagged by its ID
|
||||
// so we can extract the rule later on in the default
|
||||
// (generic) parse_rule function.
|
||||
typedef
|
||||
is_same<parse_rule_result, default_parse_rule_result>
|
||||
is_default_parse_rule;
|
||||
|
||||
Iterator start = first;
|
||||
bool r = rhs.parse(
|
||||
first
|
||||
, last
|
||||
, make_rule_context<ID>(rhs, context, std::conditional_t<skip_definition_injection, mpl::false_, is_default_parse_rule>())
|
||||
, rcontext
|
||||
, attr
|
||||
);
|
||||
|
||||
if (r)
|
||||
{
|
||||
r = call_on_success(start, first, context, attr
|
||||
, has_on_success<ID, Iterator, Context, ActualAttribute>());
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
template <typename RHS, typename Iterator, typename Context
|
||||
, typename RContext, typename ActualAttribute>
|
||||
static bool parse_rhs_main(
|
||||
RHS const& rhs
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, ActualAttribute& attr
|
||||
, mpl::true_ /* on_error is found */)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
try
|
||||
#endif
|
||||
{
|
||||
if (parse_rhs_main(
|
||||
rhs, first, last, context, rcontext, attr, mpl::false_()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
catch (expectation_failure<Iterator> const& x) {
|
||||
#else
|
||||
if (has_expectation_failure(context)) {
|
||||
auto& x = get_expectation_failure(context);
|
||||
#endif
|
||||
// X3 developer note: don't forget to sync this implementation with x3::guard
|
||||
switch (ID().on_error(first, last, x, context))
|
||||
{
|
||||
case error_handler_result::fail:
|
||||
clear_expectation_failure(context);
|
||||
return false;
|
||||
|
||||
case error_handler_result::retry:
|
||||
continue;
|
||||
|
||||
case error_handler_result::accept:
|
||||
return true;
|
||||
|
||||
case error_handler_result::rethrow:
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
throw;
|
||||
#else
|
||||
return false; // TODO: design decision required
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RHS, typename Iterator
|
||||
, typename Context, typename RContext, typename ActualAttribute>
|
||||
static bool parse_rhs_main(
|
||||
RHS const& rhs
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, ActualAttribute& attr)
|
||||
{
|
||||
return parse_rhs_main(
|
||||
rhs, first, last, context, rcontext, attr
|
||||
, has_on_error<ID, Iterator, Context>()
|
||||
);
|
||||
}
|
||||
|
||||
template <typename RHS, typename Iterator
|
||||
, typename Context, typename RContext, typename ActualAttribute>
|
||||
static bool parse_rhs(
|
||||
RHS const& rhs
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, ActualAttribute& attr
|
||||
, mpl::false_)
|
||||
{
|
||||
return parse_rhs_main(rhs, first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
template <typename RHS, typename Iterator
|
||||
, typename Context, typename RContext, typename ActualAttribute>
|
||||
static bool parse_rhs(
|
||||
RHS const& rhs
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, ActualAttribute& /* attr */
|
||||
, mpl::true_)
|
||||
{
|
||||
return parse_rhs_main(rhs, first, last, context, rcontext, unused);
|
||||
}
|
||||
|
||||
template <typename RHS, typename Iterator, typename Context
|
||||
, typename ActualAttribute, typename ExplicitAttrPropagation>
|
||||
static bool call_rule_definition(
|
||||
RHS const& rhs
|
||||
, char const* rule_name
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, ActualAttribute& attr
|
||||
, ExplicitAttrPropagation)
|
||||
{
|
||||
boost::ignore_unused(rule_name);
|
||||
|
||||
// do down-stream transformation, provides attribute for
|
||||
// rhs parser
|
||||
typedef traits::transform_attribute<
|
||||
ActualAttribute, Attribute, parser_id>
|
||||
transform;
|
||||
|
||||
typedef typename transform::type transform_attr;
|
||||
transform_attr attr_ = transform::pre(attr);
|
||||
|
||||
bool ok_parse
|
||||
//Creates a place to hold the result of parse_rhs
|
||||
//called inside the following scope.
|
||||
;
|
||||
{
|
||||
// Create a scope to cause the dbg variable below (within
|
||||
// the #if...#endif) to call it's DTOR before any
|
||||
// modifications are made to the attribute, attr_ passed
|
||||
// to parse_rhs (such as might be done in
|
||||
// transform::post when, for example,
|
||||
// ActualAttribute is a recursive variant).
|
||||
#if defined(BOOST_SPIRIT_X3_DEBUG)
|
||||
context_debug<Iterator, transform_attr>
|
||||
dbg(rule_name, first, last, attr_, ok_parse);
|
||||
#endif
|
||||
ok_parse = parse_rhs(rhs, first, last, context, attr_, attr_
|
||||
, mpl::bool_
|
||||
< ( RHS::has_action
|
||||
&& !ExplicitAttrPropagation::value
|
||||
)
|
||||
>()
|
||||
);
|
||||
}
|
||||
if (ok_parse)
|
||||
{
|
||||
// do up-stream transformation, this integrates the results
|
||||
// back into the original attribute value, if appropriate
|
||||
transform::post(attr, std::forward<transform_attr>(attr_));
|
||||
}
|
||||
return ok_parse;
|
||||
}
|
||||
};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
@@ -1,454 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2017 wanghan02
|
||||
Copyright (c) 2024-2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_X3_DETAIL_RULE_JAN_08_2012_0326PM)
|
||||
#define BOOST_SPIRIT_X3_DETAIL_RULE_JAN_08_2012_0326PM
|
||||
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/skip_over.hpp>
|
||||
#include <boost/spirit/home/x3/core/error_handler_types.hpp>
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
#include <boost/spirit/home/x3/directive/expect.hpp>
|
||||
#include <boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp>
|
||||
|
||||
#if defined(BOOST_SPIRIT_X3_DEBUG)
|
||||
#include <boost/spirit/home/x3/nonterminal/simple_trace.hpp>
|
||||
#endif
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
template <typename ID, typename Attribute = unused_type, bool force_attribute = false>
|
||||
struct rule;
|
||||
|
||||
struct parse_pass_context_tag;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename ID>
|
||||
struct rule_id {};
|
||||
|
||||
// Placeholder type to detect whether the default `parse_rule(...)` is called
|
||||
enum struct default_parse_rule_result : bool {};
|
||||
|
||||
template <typename ID, typename Context>
|
||||
constexpr bool context_has_rule_id = !std::is_same_v<
|
||||
std::remove_cvref_t<decltype(x3::get<ID>(std::declval<Context const&>()))>,
|
||||
unused_type
|
||||
>;
|
||||
} // detail
|
||||
|
||||
// The default `parse_rule` definition.
|
||||
//
|
||||
// This overload will only be selected when there exists no user-defined
|
||||
// definition for `parse_rule`.
|
||||
//
|
||||
// When a user invokes `BOOST_SPIRIT_X3_DEFINE_`, an unconstrained overload
|
||||
// is generated at the user's namespace scope. It will never conflict with
|
||||
// this (vvvvv) overload, as the generated one is never directly called with
|
||||
// a context containing `ID`.
|
||||
template <typename ID, std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename Attribute>
|
||||
requires detail::context_has_rule_id<ID, Context>
|
||||
[[nodiscard]] constexpr detail::default_parse_rule_result
|
||||
parse_rule(
|
||||
detail::rule_id<ID>,
|
||||
It& first, Se const& last,
|
||||
Context const& context, Attribute& attr
|
||||
)
|
||||
{
|
||||
auto&& rule_ = x3::get<ID>(context);
|
||||
return static_cast<detail::default_parse_rule_result>(
|
||||
rule_.parse(first, last, context, unused, attr)
|
||||
);
|
||||
}
|
||||
|
||||
// This overload is selected only when the user *declares* their `parse_rule`
|
||||
// in the user's namespace scope AND the function definition is not found.
|
||||
template <typename ID, std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename Attribute>
|
||||
requires (!detail::context_has_rule_id<ID, Context>)
|
||||
constexpr void
|
||||
parse_rule(
|
||||
detail::rule_id<ID>,
|
||||
It&, Se const&,
|
||||
Context const&, Attribute&
|
||||
) = delete; // BOOST_SPIRIT_X3_DEFINE undefined for this rule
|
||||
|
||||
} // boost::spirit::x3
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
{
|
||||
#if defined(BOOST_SPIRIT_X3_DEBUG)
|
||||
// TODO: This should be customizable by users
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
struct scoped_debug
|
||||
{
|
||||
scoped_debug(
|
||||
char const* rule_name,
|
||||
It const& first, Se const& last,
|
||||
Attribute const& attr,
|
||||
bool const& parse_ok
|
||||
)
|
||||
: parse_ok(parse_ok)
|
||||
, rule_name(rule_name)
|
||||
, first(first)
|
||||
, last(last)
|
||||
, attr(attr)
|
||||
, f(detail::get_simple_trace())
|
||||
{
|
||||
f(first, last, attr, pre_parse, rule_name);
|
||||
}
|
||||
|
||||
~scoped_debug()
|
||||
{
|
||||
f(first, last, attr, parse_ok ? successful_parse : failed_parse, rule_name);
|
||||
}
|
||||
|
||||
bool const& parse_ok;
|
||||
char const* rule_name = nullptr;
|
||||
It const& first;
|
||||
Se const& last;
|
||||
Attribute const& attr;
|
||||
detail::simple_trace_type& f;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename ID, typename It, typename Se, typename Context>
|
||||
concept HasImmutableOnErrorOverload =
|
||||
std::forward_iterator<It> &&
|
||||
std::sentinel_for<Se, It> &&
|
||||
requires(ID& id) { // Note: `ID` should be non-const
|
||||
id.on_error(
|
||||
std::declval<It const&>(),
|
||||
std::declval<Se const&>(),
|
||||
std::declval<expectation_failure<It> const&>(),
|
||||
std::declval<Context const&>()
|
||||
);
|
||||
};
|
||||
|
||||
template <typename ID, typename It, typename Se, typename Context>
|
||||
concept HasMutableOnErrorOverload =
|
||||
std::forward_iterator<It> &&
|
||||
std::sentinel_for<Se, It> &&
|
||||
requires(ID& id) { // Note: `ID` should be non-const
|
||||
id.on_error(
|
||||
std::declval<It&>(),
|
||||
std::declval<Se&>(),
|
||||
std::declval<expectation_failure<It> const&>(),
|
||||
std::declval<Context const&>()
|
||||
);
|
||||
};
|
||||
|
||||
template <typename ID, std::forward_iterator It, std::sentinel_for<It> Se, typename Context>
|
||||
struct has_on_error : std::false_type {};
|
||||
|
||||
template <typename ID, std::forward_iterator It, std::sentinel_for<It> Se, typename Context>
|
||||
requires HasImmutableOnErrorOverload<ID, It, Se, Context>
|
||||
struct has_on_error<ID, It, Se, Context> : std::true_type
|
||||
{
|
||||
// We intentionally make this hard error to prevent error-prone definition
|
||||
static_assert(
|
||||
std::convertible_to<
|
||||
decltype(std::declval<ID&>().on_error(
|
||||
std::declval<It const&>(),
|
||||
std::declval<Se const&>(),
|
||||
std::declval<expectation_failure<It> const&>(),
|
||||
std::declval<Context const&>()
|
||||
)),
|
||||
x3::error_handler_result
|
||||
>,
|
||||
"The return type of `on_error` should be convertible to `x3::error_handler_result`."
|
||||
);
|
||||
};
|
||||
|
||||
template <typename ID, std::forward_iterator It, std::sentinel_for<It> Se, typename Context>
|
||||
requires
|
||||
(!HasImmutableOnErrorOverload<ID, It, Se, Context>) &&
|
||||
HasMutableOnErrorOverload<ID, It, Se, Context>
|
||||
struct has_on_error<ID, It, Se, Context> : std::false_type
|
||||
{
|
||||
// Historically, Spirit has passed mutable lvalue references of the iterators *as-is*
|
||||
// to the `on_success`/`on_error` handlers. This behavior was simply a mistake, because:
|
||||
// (1) `on_success`/`on_error` mechanism was designed to be grammar-agnostic, and
|
||||
// (2) it does not make sense to modify the grammar-specific iterator on the
|
||||
// grammar-agnostic callback.
|
||||
//
|
||||
// Furthermore, any modification to X3's internal iterator variables may invoke
|
||||
// undefined behavior, since we never provide any kind of guarantee on how the
|
||||
// intermediate iterator variables are processed in X3's implementation details.
|
||||
static_assert(
|
||||
false,
|
||||
"The `on_error` callback should only accept const reference or passed-by-value iterators."
|
||||
);
|
||||
};
|
||||
|
||||
template <typename ID, typename It, typename Se, typename Attribute, typename Context>
|
||||
concept HasImmutableOnSuccessOverload =
|
||||
std::forward_iterator<It> &&
|
||||
std::sentinel_for<Se, It> &&
|
||||
requires(ID& id) { // Note: `ID` should be non-const
|
||||
id.on_success(
|
||||
std::declval<It const&>(),
|
||||
std::declval<Se const&>(),
|
||||
std::declval<Attribute&>(),
|
||||
std::declval<Context const&>()
|
||||
);
|
||||
};
|
||||
|
||||
template <typename ID, typename It, typename Se, typename Attribute, typename Context>
|
||||
concept HasMutableOnSuccessOverload =
|
||||
std::forward_iterator<It> &&
|
||||
std::sentinel_for<Se, It> &&
|
||||
requires(ID& id) { // Note: `ID` should be non-const
|
||||
id.on_success(
|
||||
std::declval<It&>(),
|
||||
std::declval<Se&>(),
|
||||
std::declval<Attribute&>(),
|
||||
std::declval<Context const&>()
|
||||
);
|
||||
};
|
||||
|
||||
template <typename ID, std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute, typename Context>
|
||||
struct has_on_success : std::false_type {};
|
||||
|
||||
template <typename ID, std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute, typename Context>
|
||||
requires HasImmutableOnSuccessOverload<ID, It, Se, Attribute, Context>
|
||||
struct has_on_success<ID, It, Se, Attribute, Context> : std::true_type
|
||||
{
|
||||
// We intentionally make this hard error to prevent error-prone definition
|
||||
static_assert(
|
||||
std::is_void_v<
|
||||
decltype(std::declval<ID&>().on_success(
|
||||
std::declval<It const&>(),
|
||||
std::declval<Se const&>(),
|
||||
std::declval<Attribute&>(),
|
||||
std::declval<Context const&>()
|
||||
))
|
||||
>,
|
||||
"The return type of `on_success` should be `void`."
|
||||
);
|
||||
};
|
||||
|
||||
template <typename ID, std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute, typename Context>
|
||||
requires
|
||||
(!HasImmutableOnSuccessOverload<ID, It, Se, Attribute, Context>) &&
|
||||
HasMutableOnSuccessOverload<ID, It, Se, Attribute, Context>
|
||||
struct has_on_success<ID, It, Se, Attribute, Context> : std::false_type
|
||||
{
|
||||
// For details, see the comments on `has_on_error`.
|
||||
static_assert(
|
||||
false,
|
||||
"The `on_success` callback should only accept const reference or passed-by-value iterators."
|
||||
);
|
||||
};
|
||||
|
||||
template <typename Attribute, typename ID, bool SkipDefinitionInjection = false>
|
||||
struct rule_parser
|
||||
{
|
||||
template <
|
||||
typename RHS, std::forward_iterator It, std::sentinel_for<It> Se,
|
||||
typename Context, typename RContext, typename ActualAttribute
|
||||
>
|
||||
[[nodiscard]] static constexpr bool
|
||||
parse_rhs(
|
||||
RHS const& rhs, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, ActualAttribute& attr
|
||||
) // never noexcept; requires complex handling
|
||||
{
|
||||
It start = first;
|
||||
|
||||
// See if the user has a BOOST_SPIRIT_DEFINE for this rule
|
||||
using parse_rule_result_type = decltype(
|
||||
parse_rule( // ADL
|
||||
std::declval<detail::rule_id<ID>>(), first, last,
|
||||
std::declval<decltype(x3::make_unique_context<ID>(rhs, context))>(),
|
||||
std::declval<Attribute&>()
|
||||
)
|
||||
);
|
||||
constexpr bool is_default_parse_rule = std::is_same_v<
|
||||
parse_rule_result_type, default_parse_rule_result
|
||||
>;
|
||||
|
||||
bool ok;
|
||||
if constexpr (SkipDefinitionInjection || !is_default_parse_rule)
|
||||
{
|
||||
ok = rhs.parse(first, last, context, rcontext, attr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is no BOOST_SPIRIT_DEFINE for this rule,
|
||||
// we'll make a context for this rule tagged by its ID
|
||||
// so we can extract the rule later on in the default
|
||||
// parse_rule function.
|
||||
auto rule_id_context = x3::make_unique_context<ID>(rhs, context);
|
||||
ok = rhs.parse(first, last, rule_id_context, rcontext, attr);
|
||||
}
|
||||
|
||||
// Note: this check uses `It, It` because the value is actually iterator-iterator pair
|
||||
if constexpr (has_on_success<ID, It, It, ActualAttribute, Context>::value)
|
||||
{
|
||||
if (!ok) return false;
|
||||
|
||||
x3::skip_over(start, first, context);
|
||||
bool pass = true;
|
||||
ID().on_success(
|
||||
std::as_const(start), std::as_const(first), attr,
|
||||
x3::make_context<parse_pass_context_tag>(pass, context)
|
||||
);
|
||||
return pass;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
template <
|
||||
typename RHS, std::forward_iterator It, std::sentinel_for<It> Se,
|
||||
typename Context, typename RContext, typename ActualAttribute
|
||||
>
|
||||
[[nodiscard]] static constexpr bool
|
||||
parse_rhs_with_on_error(
|
||||
RHS const& rhs, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, ActualAttribute& attr
|
||||
) // never noexcept; requires complex handling
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
try
|
||||
#endif
|
||||
{
|
||||
if (rule_parser::parse_rhs(rhs, first, last, context, rcontext, attr))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
catch (expectation_failure<It> const& x) {
|
||||
#else
|
||||
if (x3::has_expectation_failure(context)) {
|
||||
auto const& x = x3::get_expectation_failure(context);
|
||||
#endif
|
||||
// X3 developer note: don't forget to sync this implementation with x3::guard
|
||||
switch (ID{}.on_error(std::as_const(first), std::as_const(last), x, context))
|
||||
{
|
||||
case error_handler_result::fail:
|
||||
x3::clear_expectation_failure(context);
|
||||
return false;
|
||||
|
||||
case error_handler_result::retry:
|
||||
continue;
|
||||
|
||||
case error_handler_result::accept:
|
||||
return true;
|
||||
|
||||
case error_handler_result::rethrow:
|
||||
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
|
||||
throw;
|
||||
#else
|
||||
return false; // TODO: design decision required
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <
|
||||
bool ForceAttribute,
|
||||
typename RHS, std::forward_iterator It, std::sentinel_for<It> Se,
|
||||
typename Context, typename ActualAttribute
|
||||
>
|
||||
[[nodiscard]] static constexpr bool
|
||||
call_rule_definition(
|
||||
RHS const& rhs, char const* rule_name,
|
||||
It& first, Se const& last,
|
||||
Context const& context, ActualAttribute& attr
|
||||
)
|
||||
{
|
||||
// Do down-stream transformation, provides attribute for rhs parser
|
||||
using transform = traits::transform_attribute<ActualAttribute, Attribute, parser_id>;
|
||||
using transform_attr = typename transform::type;
|
||||
transform_attr attr_ = transform::pre(attr);
|
||||
|
||||
// Creates a place to hold the result of parse_rhs
|
||||
// called inside the following scope.
|
||||
bool parse_ok;
|
||||
{
|
||||
#ifdef BOOST_SPIRIT_X3_DEBUG
|
||||
// Create a scope to cause the dbg variable below (within
|
||||
// the #if...#endif) to call it's DTOR before any
|
||||
// modifications are made to the attribute, attr_ passed
|
||||
// to parse_rhs (such as might be done in
|
||||
// transform::post when, for example,
|
||||
// ActualAttribute is a recursive variant).
|
||||
scoped_debug<It, Se, transform_attr>
|
||||
dbg(rule_name, first, last, attr_, parse_ok);
|
||||
#else
|
||||
(void)rule_name;
|
||||
#endif
|
||||
|
||||
// In theory, these calls can be overloaded using tag dispatches.
|
||||
// However we should get over those legacy technique already, as they
|
||||
// lead to enormous amount of call stack, generating unreadable
|
||||
// compilation errors. Even when we have a single layer of tag dispatch,
|
||||
// we should generally avoid it because the "true_type/false_type"
|
||||
// argument placed at the very last param of the overload is virtually
|
||||
// indistinguishable in messages and has serious QoL issue in debuggers.
|
||||
constexpr bool rhs_has_on_error = has_on_error<ID, It, Se, Context>::value;
|
||||
|
||||
// The existence of semantic action inhibits attribute materialization
|
||||
// _unless_ it is explicitly required by the user (primarily via `%=`).
|
||||
if constexpr (RHS::has_action && !ForceAttribute)
|
||||
{
|
||||
if constexpr (rhs_has_on_error)
|
||||
{
|
||||
parse_ok = rule_parser::parse_rhs_with_on_error(
|
||||
rhs, first, last, context, attr_ /* rcontext */, unused
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
parse_ok = rule_parser::parse_rhs(
|
||||
rhs, first, last, context, attr_ /* rcontext */, unused
|
||||
);
|
||||
}
|
||||
}
|
||||
else // attribute is required
|
||||
{
|
||||
if constexpr (rhs_has_on_error)
|
||||
{
|
||||
parse_ok = rule_parser::parse_rhs_with_on_error(
|
||||
rhs, first, last, context, attr_ /* rcontext */, attr_
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
parse_ok = rule_parser::parse_rhs(
|
||||
rhs, first, last, context, attr_ /* rcontext */, attr_
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parse_ok)
|
||||
{
|
||||
// do up-stream transformation, this integrates the results
|
||||
// back into the original attribute value, if appropriate
|
||||
transform::post(attr, std::forward<transform_attr>(attr_));
|
||||
}
|
||||
return parse_ok;
|
||||
}
|
||||
};
|
||||
} // boost::spirit::x3::detail
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -11,34 +10,24 @@
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/transform_attribute.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct parser_id;
|
||||
} // detail
|
||||
struct parser_id;
|
||||
|
||||
template <typename Exposed, typename Transformed>
|
||||
requires std::is_assignable_v<Exposed&, Transformed&&>
|
||||
struct default_transform_attribute
|
||||
{
|
||||
using type = Transformed;
|
||||
typedef Transformed type;
|
||||
|
||||
static constexpr Transformed pre(Exposed&)
|
||||
noexcept(std::is_nothrow_default_constructible_v<Transformed>)
|
||||
{
|
||||
return Transformed{};
|
||||
}
|
||||
static Transformed pre(Exposed&) { return Transformed(); }
|
||||
|
||||
template <typename TransformedT>
|
||||
static constexpr void post(Exposed& val, TransformedT&& attribute)
|
||||
noexcept(noexcept(traits::move_to(std::forward<TransformedT>(attribute), val)))
|
||||
static void post(Exposed& val, Transformed&& attribute)
|
||||
{
|
||||
traits::move_to(std::forward<TransformedT>(attribute), val);
|
||||
traits::move_to(std::forward<Transformed>(attribute), val);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -46,59 +35,58 @@ namespace boost::spirit::x3
|
||||
template <typename Attribute>
|
||||
struct default_transform_attribute<Attribute, Attribute>
|
||||
{
|
||||
using type = Attribute&;
|
||||
static constexpr Attribute& pre(Attribute& val) noexcept { return val; }
|
||||
static constexpr void post(Attribute&, Attribute const&) noexcept {}
|
||||
typedef Attribute& type;
|
||||
static Attribute& pre(Attribute& val) { return val; }
|
||||
static void post(Attribute&, Attribute const&) {}
|
||||
};
|
||||
|
||||
// main specialization for x3
|
||||
template <typename Exposed, typename Transformed, typename Enable = void>
|
||||
requires std::is_assignable_v<Exposed&, Transformed&&>
|
||||
struct transform_attribute
|
||||
: default_transform_attribute<Exposed, Transformed> {};
|
||||
: default_transform_attribute<Exposed, Transformed> {};
|
||||
|
||||
// unused_type needs some special handling as well
|
||||
template <>
|
||||
struct transform_attribute<unused_type, unused_type>
|
||||
{
|
||||
using type = unused_type;
|
||||
static constexpr unused_type pre(unused_type) noexcept { return unused; }
|
||||
static constexpr void post(unused_type, unused_type) noexcept {}
|
||||
typedef unused_type type;
|
||||
static unused_type pre(unused_type) { return unused; }
|
||||
static void post(unused_type, unused_type) {}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct transform_attribute<unused_type const, unused_type>
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
|
||||
template <typename Attribute>
|
||||
struct transform_attribute<unused_type, Attribute>
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
|
||||
template <typename Attribute>
|
||||
struct transform_attribute<unused_type const, Attribute>
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
|
||||
template <typename Attribute>
|
||||
struct transform_attribute<Attribute, unused_type>
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
|
||||
template <typename Attribute>
|
||||
struct transform_attribute<Attribute const, unused_type>
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
|
||||
} // boost::spirit::x3
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
}}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename Exposed, typename Transformed>
|
||||
requires std::is_assignable_v<Exposed&, Transformed&&>
|
||||
struct transform_attribute<Exposed, Transformed, x3::detail::parser_id>
|
||||
: x3::transform_attribute<Exposed, Transformed>
|
||||
struct transform_attribute<Exposed, Transformed, x3::parser_id>
|
||||
: x3::transform_attribute<Exposed, Transformed>
|
||||
{
|
||||
static_assert(!std::is_reference_v<Exposed>, "Exposed cannot be a reference type");
|
||||
static_assert(!std::is_reference_v<Transformed>, "Transformed cannot be a reference type");
|
||||
static_assert(!std::is_reference<Exposed>::value,
|
||||
"Exposed cannot be a reference type");
|
||||
static_assert(!std::is_reference<Transformed>::value,
|
||||
"Transformed cannot be a reference type");
|
||||
};
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -8,330 +7,254 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_RULE_JAN_08_2012_0326PM)
|
||||
#define BOOST_SPIRIT_X3_RULE_JAN_08_2012_0326PM
|
||||
|
||||
#include <boost/spirit/home/x3/nonterminal/detail/rule_parser.hpp>
|
||||
#include <boost/spirit/home/x3/nonterminal/detail/rule.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/preprocessor/variadic/to_seq.hpp>
|
||||
#include <boost/preprocessor/variadic/elem.hpp>
|
||||
#include <boost/preprocessor/seq/for_each.hpp>
|
||||
#include <boost/config/helper_macros.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#if !defined(BOOST_SPIRIT_X3_NO_RTTI)
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename ID, X3Subject RHS, typename Attribute, bool ForceAttribute, bool SkipDefinitionInjection = false>
|
||||
struct rule_definition : parser<rule_definition<ID, RHS, Attribute, ForceAttribute, SkipDefinitionInjection>>
|
||||
// default parse_rule implementation
|
||||
template <typename ID, typename Iterator
|
||||
, typename Context, typename ActualAttribute>
|
||||
inline detail::default_parse_rule_result
|
||||
parse_rule(
|
||||
detail::rule_id<ID>
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, ActualAttribute& attr)
|
||||
{
|
||||
using this_type = rule_definition<ID, RHS, Attribute, ForceAttribute, SkipDefinitionInjection>;
|
||||
using id = ID;
|
||||
using rhs_type = RHS;
|
||||
using lhs_type = rule<ID, Attribute, ForceAttribute>;
|
||||
using attribute_type = Attribute;
|
||||
static_assert(!is_same<decltype(x3::get<ID>(context)), unused_type>::value,
|
||||
"BOOST_SPIRIT_DEFINE undefined for this rule.");
|
||||
return x3::get<ID>(context).parse(first, last, context, unused, attr);
|
||||
}
|
||||
|
||||
static constexpr bool has_attribute = !std::is_same_v<Attribute, unused_type>;
|
||||
static constexpr bool handles_container = traits::is_container<Attribute>::value;
|
||||
static constexpr bool force_attribute = ForceAttribute;
|
||||
template <typename ID, typename RHS, typename Attribute, bool force_attribute_, bool skip_definition_injection = false>
|
||||
struct rule_definition : parser<rule_definition<ID, RHS, Attribute, force_attribute_, skip_definition_injection>>
|
||||
{
|
||||
typedef rule_definition<ID, RHS, Attribute, force_attribute_, skip_definition_injection> this_type;
|
||||
typedef ID id;
|
||||
typedef RHS rhs_type;
|
||||
typedef rule<ID, Attribute, force_attribute_> lhs_type;
|
||||
typedef Attribute attribute_type;
|
||||
|
||||
template <typename RHS_T>
|
||||
requires std::is_constructible_v<RHS, RHS_T>
|
||||
constexpr rule_definition(RHS_T&& rhs, char const* name)
|
||||
noexcept(std::is_nothrow_constructible_v<RHS, RHS_T>)
|
||||
: rhs(std::forward<RHS_T>(rhs))
|
||||
, name(name)
|
||||
{}
|
||||
static bool const has_attribute =
|
||||
!is_same<Attribute, unused_type>::value;
|
||||
static bool const handles_container =
|
||||
traits::is_container<Attribute>::value;
|
||||
static bool const force_attribute =
|
||||
force_attribute_;
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename Attribute_>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, unused_type, Attribute_& attr) const
|
||||
// never noexcept; requires very complex implementation details
|
||||
constexpr rule_definition(RHS const& rhs, char const* name)
|
||||
: rhs(rhs), name(name) {}
|
||||
|
||||
template <typename Iterator, typename Context, typename Attribute_>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, unused_type, Attribute_& attr) const
|
||||
{
|
||||
return detail::rule_parser<attribute_type, ID, SkipDefinitionInjection>
|
||||
::template call_rule_definition<ForceAttribute>(
|
||||
rhs, name, first, last, context, attr
|
||||
);
|
||||
return detail::rule_parser<attribute_type, ID, skip_definition_injection>
|
||||
::call_rule_definition(
|
||||
rhs, name, first, last
|
||||
, context
|
||||
, attr
|
||||
, mpl::bool_<force_attribute>());
|
||||
}
|
||||
|
||||
RHS rhs;
|
||||
char const* name = "unnamed";
|
||||
char const* name;
|
||||
};
|
||||
|
||||
template <typename ID, typename Attribute, bool ForceAttribute>
|
||||
struct rule : parser<rule<ID, Attribute, ForceAttribute>>
|
||||
template <typename ID, typename Attribute, bool force_attribute_>
|
||||
struct rule : parser<rule<ID, Attribute, force_attribute_>>
|
||||
{
|
||||
static_assert(!std::is_reference_v<Attribute>, "Reference qualifier on rule attribute type is meaningless");
|
||||
static_assert(!std::is_reference<Attribute>::value,
|
||||
"Reference qualifier on rule attribute type is meaningless");
|
||||
|
||||
using id = ID;
|
||||
using attribute_type = Attribute;
|
||||
static constexpr bool has_attribute = !std::is_same_v<std::remove_const_t<Attribute>, unused_type>;
|
||||
static constexpr bool handles_container = traits::is_container<Attribute>::value;
|
||||
static constexpr bool force_attribute = ForceAttribute;
|
||||
typedef ID id;
|
||||
typedef Attribute attribute_type;
|
||||
static bool const has_attribute =
|
||||
!std::is_same<std::remove_const_t<Attribute>, unused_type>::value;
|
||||
static bool const handles_container =
|
||||
traits::is_container<Attribute>::value;
|
||||
static bool const force_attribute = force_attribute_;
|
||||
|
||||
#if !defined(BOOST_SPIRIT_X3_NO_RTTI)
|
||||
rule() : name(typeid(rule).name()) {}
|
||||
#else
|
||||
constexpr rule() noexcept : name("unnamed") {}
|
||||
constexpr rule() : name("unnamed") {}
|
||||
#endif
|
||||
|
||||
constexpr rule(char const* name) noexcept
|
||||
: name(name)
|
||||
{}
|
||||
constexpr rule(char const* name)
|
||||
: name(name) {}
|
||||
|
||||
constexpr rule(rule const& r) noexcept
|
||||
: name(r.name)
|
||||
constexpr rule(rule const& r)
|
||||
: name(r.name)
|
||||
{
|
||||
// Assert that we are not copying an unitialized static rule. If
|
||||
// the static is in another TU, it may be initialized after we copy
|
||||
// it. If so, its name member will be nullptr.
|
||||
BOOST_ASSERT_MSG(r.name != nullptr, "uninitialized rule"); // static initialization order fiasco
|
||||
BOOST_ASSERT_MSG(r.name, "uninitialized rule"); // static initialization order fiasco
|
||||
}
|
||||
|
||||
template <X3Subject RHS>
|
||||
[[nodiscard]] constexpr rule_definition<ID, as_parser_plain_t<RHS>, Attribute, ForceAttribute>
|
||||
operator=(RHS&& rhs) const&
|
||||
noexcept(
|
||||
is_parser_nothrow_castable_v<RHS> &&
|
||||
std::is_nothrow_constructible_v<
|
||||
rule_definition<ID, as_parser_plain_t<RHS>, Attribute, ForceAttribute>,
|
||||
as_parser_t<RHS>, char const*
|
||||
>
|
||||
)
|
||||
template <typename RHS>
|
||||
constexpr rule_definition<
|
||||
ID, typename extension::as_parser<RHS>::value_type, Attribute, force_attribute_>
|
||||
operator=(RHS const& rhs) const&
|
||||
{
|
||||
return { as_parser(std::forward<RHS>(rhs)), name };
|
||||
return { as_parser(rhs), name };
|
||||
}
|
||||
|
||||
template <X3Subject RHS>
|
||||
[[nodiscard]] constexpr rule_definition<ID, as_parser_plain_t<RHS>, Attribute, true>
|
||||
operator%=(RHS&& rhs) const&
|
||||
noexcept(
|
||||
is_parser_nothrow_castable_v<RHS> &&
|
||||
std::is_nothrow_constructible_v<
|
||||
rule_definition<ID, as_parser_plain_t<RHS>, Attribute, true>,
|
||||
as_parser_t<RHS>, char const*
|
||||
>
|
||||
)
|
||||
template <typename RHS>
|
||||
constexpr rule_definition<
|
||||
ID, typename extension::as_parser<RHS>::value_type, Attribute, true>
|
||||
operator%=(RHS const& rhs) const&
|
||||
{
|
||||
return { as_parser(std::forward<RHS>(rhs)), name };
|
||||
return { as_parser(rhs), name };
|
||||
}
|
||||
|
||||
// When a rule placeholder constructed and immediately consumed it cannot be used recursively,
|
||||
// that's why the rule definition injection into a parser context can be skipped.
|
||||
// This optimization has a huge impact on compile times because immediate rules are commonly
|
||||
// used to cast an attribute like `as`/`attr_cast` does in Qi.
|
||||
template <X3Subject RHS>
|
||||
[[nodiscard]] constexpr rule_definition<ID, as_parser_plain_t<RHS>, Attribute, ForceAttribute, true>
|
||||
operator=(RHS&& rhs) const&&
|
||||
noexcept(
|
||||
is_parser_nothrow_castable_v<RHS> &&
|
||||
std::is_nothrow_constructible_v<
|
||||
rule_definition<ID, as_parser_plain_t<RHS>, Attribute, ForceAttribute, true>,
|
||||
as_parser_t<RHS>, char const*
|
||||
>
|
||||
)
|
||||
template <typename RHS>
|
||||
constexpr rule_definition<
|
||||
ID, typename extension::as_parser<RHS>::value_type, Attribute, force_attribute_, true>
|
||||
operator=(RHS const& rhs) const&&
|
||||
{
|
||||
return { as_parser(std::forward<RHS>(rhs)), name };
|
||||
return { as_parser(rhs), name };
|
||||
}
|
||||
|
||||
template <X3Subject RHS>
|
||||
[[nodiscard]] constexpr rule_definition<ID, as_parser_plain_t<RHS>, Attribute, true, true>
|
||||
operator%=(RHS&& rhs) const&&
|
||||
noexcept(
|
||||
is_parser_nothrow_castable_v<RHS> &&
|
||||
std::is_nothrow_constructible_v<
|
||||
rule_definition<ID, as_parser_plain_t<RHS>, Attribute, true, true>,
|
||||
as_parser_t<RHS>, char const*
|
||||
>
|
||||
)
|
||||
template <typename RHS>
|
||||
constexpr rule_definition<
|
||||
ID, typename extension::as_parser<RHS>::value_type, Attribute, true, true>
|
||||
operator%=(RHS const& rhs) const&&
|
||||
{
|
||||
return { as_parser(std::forward<RHS>(rhs)), name };
|
||||
return { as_parser(rhs), name };
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename Exposed>
|
||||
requires (!std::is_same_v<std::remove_const_t<Exposed>, unused_type>)
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, unused_type, Exposed& exposed_attr) const
|
||||
// never noexcept; requires very complex implementation details
|
||||
|
||||
template <typename Iterator, typename Context, typename Attribute_>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, unused_type, Attribute_& attr) const
|
||||
{
|
||||
static_assert(has_attribute, "A rule must have an attribute. Check your rule definition.");
|
||||
static_assert(has_attribute,
|
||||
"The rule does not have an attribute. Check your parser.");
|
||||
|
||||
static_assert(
|
||||
traits::Transformable<Exposed, Attribute, detail::parser_id>,
|
||||
"Attribute type mismatch; the rule's attribute is not assignable to "
|
||||
"the exposed attribute, and no eligible specialization of "
|
||||
"`x3::traits::transform_attribute` was found."
|
||||
);
|
||||
using transform = traits::transform_attribute<
|
||||
Attribute_, attribute_type, parser_id>;
|
||||
|
||||
using transform = traits::transform_attribute<Exposed, Attribute, detail::parser_id>;
|
||||
using transformed_type = typename transform::type;
|
||||
transformed_type transformed_attr = transform::pre(exposed_attr);
|
||||
using transform_attr = typename transform::type;
|
||||
transform_attr attr_ = transform::pre(attr);
|
||||
|
||||
// ADL
|
||||
if (static_cast<bool>(parse_rule(detail::rule_id<ID>{}, first, last, context, transformed_attr))) {
|
||||
transform::post(exposed_attr, std::forward<transformed_type>(transformed_attr));
|
||||
if (parse_rule(detail::rule_id<ID>{}, first, last, context, attr_)) {
|
||||
transform::post(attr, std::forward<transform_attr>(attr_));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, unused_type, unused_type) const
|
||||
// never noexcept; requires very complex implementation details
|
||||
template <typename Iterator, typename Context>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, unused_type, unused_type) const
|
||||
{
|
||||
// make sure we pass exactly the rule attribute type
|
||||
attribute_type no_attr; // default-initialize
|
||||
|
||||
// ADL
|
||||
return static_cast<bool>(parse_rule(detail::rule_id<ID>{}, first, last, context, no_attr));
|
||||
attribute_type no_attr{};
|
||||
return parse_rule(detail::rule_id<ID>{}, first, last, context, no_attr);
|
||||
}
|
||||
|
||||
char const* name = "unnamed";
|
||||
char const* name;
|
||||
};
|
||||
|
||||
namespace traits
|
||||
{
|
||||
template <typename T, typename Enable = void>
|
||||
struct is_rule : std::false_type {};
|
||||
struct is_rule : mpl::false_ {};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_rule_v = is_rule<T>::value;
|
||||
template <typename ID, typename Attribute, bool force_attribute>
|
||||
struct is_rule<rule<ID, Attribute, force_attribute>> : mpl::true_ {};
|
||||
|
||||
template <typename ID, typename Attribute, bool ForceAttribute>
|
||||
struct is_rule<rule<ID, Attribute, ForceAttribute>> : std::true_type {};
|
||||
|
||||
template <typename ID, typename Attribute, typename RHS, bool ForceAttribute, bool SkipDefinitionInjection>
|
||||
struct is_rule<rule_definition<ID, RHS, Attribute, ForceAttribute, SkipDefinitionInjection>> : std::true_type {};
|
||||
template <typename ID, typename Attribute, typename RHS, bool force_attribute, bool skip_definition_injection>
|
||||
struct is_rule<rule_definition<ID, RHS, Attribute, force_attribute, skip_definition_injection>> : mpl::true_ {};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires traits::is_rule_v<T>
|
||||
struct get_info<T>
|
||||
struct get_info<T, typename enable_if<traits::is_rule<T>>::type>
|
||||
{
|
||||
using result_type = std::string;
|
||||
[[nodiscard]] std::string operator()(T const& r) const
|
||||
typedef std::string result_type;
|
||||
std::string operator()(T const& r) const
|
||||
{
|
||||
BOOST_ASSERT_MSG(r.name, "uninitialized rule"); // static initialization order fiasco
|
||||
return r.name? r.name : "uninitialized";
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------
|
||||
#define BOOST_SPIRIT_DECLARE_(r, data, rule_type) \
|
||||
template <typename Iterator, typename Context> \
|
||||
bool parse_rule( \
|
||||
::boost::spirit::x3::detail::rule_id<rule_type::id> \
|
||||
, Iterator& first, Iterator const& last \
|
||||
, Context const& context, rule_type::attribute_type& attr); \
|
||||
/***/
|
||||
|
||||
#define BOOST_SPIRIT_X3_DEPRECATED_MACRO_WARN_I(x) _Pragma(#x)
|
||||
#define BOOST_SPIRIT_X3_DEPRECATED_MACRO_WARN(msg) BOOST_SPIRIT_X3_DEPRECATED_MACRO_WARN_I(message(msg))
|
||||
#define BOOST_SPIRIT_DECLARE(...) BOOST_PP_SEQ_FOR_EACH( \
|
||||
BOOST_SPIRIT_DECLARE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
|
||||
/***/
|
||||
|
||||
#define BOOST_SPIRIT_X3_DECLARE_(r, constexpr_, rule_type) \
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context> \
|
||||
[[nodiscard]] constexpr_ bool \
|
||||
parse_rule( \
|
||||
::boost::spirit::x3::detail::rule_id<typename std::remove_cvref_t<rule_type>::id>, \
|
||||
It& first, Se const& last, \
|
||||
Context const& context, typename std::remove_cvref_t<rule_type>::attribute_type& attr \
|
||||
);
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
|
||||
#define BOOST_SPIRIT_DEFINE_(r, data, rule_name) \
|
||||
using BOOST_PP_CAT(rule_name, _synonym) = decltype(rule_name); \
|
||||
template <typename Iterator, typename Context> \
|
||||
inline bool parse_rule( \
|
||||
::boost::spirit::x3::detail::rule_id<BOOST_PP_CAT(rule_name, _synonym)::id> \
|
||||
, Iterator& first, Iterator const& last \
|
||||
, Context const& context, BOOST_PP_CAT(rule_name, _synonym)::attribute_type& attr) \
|
||||
{ \
|
||||
using rule_t = BOOST_JOIN(rule_name, _synonym); \
|
||||
return ::boost::spirit::x3::detail \
|
||||
::rule_parser<typename rule_t::attribute_type, rule_t::id, true> \
|
||||
::call_rule_definition( \
|
||||
BOOST_JOIN(rule_name, _def), rule_name.name \
|
||||
, first, last, context, attr \
|
||||
, ::boost::mpl::bool_<rule_t::force_attribute>()); \
|
||||
} \
|
||||
/***/
|
||||
#else
|
||||
#define BOOST_SPIRIT_DEFINE_(r, data, rule_name) \
|
||||
template <typename Iterator, typename Context> \
|
||||
inline bool parse_rule( \
|
||||
::boost::spirit::x3::detail::rule_id<decltype(rule_name)::id> \
|
||||
, Iterator& first, Iterator const& last \
|
||||
, Context const& context, decltype(rule_name)::attribute_type& attr) \
|
||||
{ \
|
||||
using rule_t = decltype(rule_name); \
|
||||
return ::boost::spirit::x3::detail \
|
||||
::rule_parser<typename rule_t::attribute_type, rule_t::id, true> \
|
||||
::call_rule_definition( \
|
||||
BOOST_JOIN(rule_name, _def), rule_name.name \
|
||||
, first, last, context, attr \
|
||||
, ::boost::mpl::bool_<rule_t::force_attribute>()); \
|
||||
} \
|
||||
/***/
|
||||
#endif
|
||||
|
||||
#define BOOST_SPIRIT_X3_DECLARE(rule_type) BOOST_SPIRIT_X3_DECLARE_(,, rule_type)
|
||||
#define BOOST_SPIRIT_X3_DECLARE_CONSTEXPR(rule_type) BOOST_SPIRIT_X3_DECLARE_(, constexpr, rule_type)
|
||||
#define BOOST_SPIRIT_DEFINE(...) BOOST_PP_SEQ_FOR_EACH( \
|
||||
BOOST_SPIRIT_DEFINE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
|
||||
/***/
|
||||
|
||||
// NB: This can't be `constexpr`, because a constexpr declaration
|
||||
// cannot be used with explicit template instantiation. We simply
|
||||
// can't drop (legit) use cases of `BOOST_SPIRIT_INSTANTIATE`, so
|
||||
// this is a pure technical limitation. If you need `constexpr`
|
||||
// support in your rule, use `BOOST_SPIRIT_X3_DECLARE_CONSTEXPR`.
|
||||
#define BOOST_SPIRIT_DECLARE(...) \
|
||||
BOOST_SPIRIT_X3_DEPRECATED_MACRO_WARN( \
|
||||
"Use of variadic arguments with `BOOST_SPIRIT_DECLARE` is deprecated due to the heavy compile-time cost of " \
|
||||
"`BOOST_PP_SEQ_*`. Just apply `BOOST_SPIRIT_X3_DECLARE` for each of your rules." \
|
||||
) \
|
||||
BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_X3_DECLARE_,, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
|
||||
#define BOOST_SPIRIT_INSTANTIATE(rule_type, Iterator, Context) \
|
||||
template bool parse_rule<Iterator, Context>( \
|
||||
::boost::spirit::x3::detail::rule_id<rule_type::id> \
|
||||
, Iterator& first, Iterator const& last \
|
||||
, Context const& context, rule_type::attribute_type&); \
|
||||
/***/
|
||||
|
||||
|
||||
#define BOOST_SPIRIT_X3_DEFINE_(r, constexpr_, rule_name) \
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context> \
|
||||
[[nodiscard]] constexpr_ bool \
|
||||
parse_rule( \
|
||||
::boost::spirit::x3::detail::rule_id<std::remove_cvref_t<decltype(rule_name)>::id>, \
|
||||
It& first, Se const& last, \
|
||||
Context const& context, \
|
||||
std::remove_cvref_t<decltype(rule_name)>::attribute_type& attr \
|
||||
) { \
|
||||
using rule_t = std::remove_cvref_t<decltype(rule_name)>; \
|
||||
return ::boost::spirit::x3::detail::rule_parser< \
|
||||
typename rule_t::attribute_type, typename rule_t::id, true \
|
||||
>::call_rule_definition<rule_t::force_attribute>( \
|
||||
BOOST_JOIN(rule_name, _def), rule_name.name, \
|
||||
first, last, context, attr \
|
||||
); \
|
||||
}
|
||||
|
||||
#define BOOST_SPIRIT_X3_DEFINE(rule_type) BOOST_SPIRIT_X3_DEFINE_(,, rule_type)
|
||||
#define BOOST_SPIRIT_X3_DEFINE_CONSTEXPR(rule_type) BOOST_SPIRIT_X3_DEFINE_(, constexpr, rule_type)
|
||||
|
||||
// NB: This can't be `constexpr`, because a constexpr declaration
|
||||
// cannot be used with explicit template instantiation. We simply
|
||||
// can't drop (legit) use cases of `BOOST_SPIRIT_INSTANTIATE`, so
|
||||
// this is a pure technical limitation. If you need `constexpr`
|
||||
// support in your rule, use `BOOST_SPIRIT_X3_DEFINE_CONSTEXPR`.
|
||||
#define BOOST_SPIRIT_DEFINE(...) \
|
||||
BOOST_SPIRIT_X3_DEPRECATED_MACRO_WARN( \
|
||||
"Use of variadic arguments with `BOOST_SPIRIT_DEFINE` is deprecated due to the heavy compile-time cost of " \
|
||||
"`BOOST_PP_SEQ_*`. Just apply `BOOST_SPIRIT_X3_DEFINE` for each of your rules." \
|
||||
) \
|
||||
BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_X3_DEFINE_,, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename RuleT, std::forward_iterator It, typename A, typename B = void>
|
||||
struct instantiate_macro_helper
|
||||
{
|
||||
using rule_type = RuleT;
|
||||
using iterator_type = It;
|
||||
|
||||
// Old API:
|
||||
// A => Context
|
||||
// B => void
|
||||
|
||||
// New API:
|
||||
// A => Se
|
||||
// B => Context
|
||||
|
||||
using sentinel_type = std::conditional_t<std::is_void_v<B>, It, A>;
|
||||
static_assert(std::sentinel_for<sentinel_type, It>);
|
||||
|
||||
using context_type = std::conditional_t<std::is_void_v<B>, A, B>;
|
||||
};
|
||||
} // detail
|
||||
|
||||
#define BOOST_SPIRIT_X3_INSTANTIATE_(rule_type, It, Se, Context) \
|
||||
template bool parse_rule<It, Se, Context>( \
|
||||
::boost::spirit::x3::detail::rule_id<typename std::remove_cvref_t<rule_type>::id>, \
|
||||
It&, Se const&, Context const&, \
|
||||
typename std::remove_cvref_t<rule_type>::attribute_type& \
|
||||
);
|
||||
|
||||
#define BOOST_SPIRIT_X3_INSTANTIATE_WRAP(...) __VA_ARGS__
|
||||
|
||||
// NB: This can't be `constexpr`, because a constexpr declaration
|
||||
// cannot be used with explicit template instantiation.
|
||||
#define BOOST_SPIRIT_X3_INSTANTIATE(...) \
|
||||
BOOST_SPIRIT_X3_INSTANTIATE_( \
|
||||
BOOST_SPIRIT_X3_INSTANTIATE_WRAP(typename ::boost::spirit::x3::detail::instantiate_macro_helper<__VA_ARGS__>::rule_type), \
|
||||
BOOST_SPIRIT_X3_INSTANTIATE_WRAP(typename ::boost::spirit::x3::detail::instantiate_macro_helper<__VA_ARGS__>::iterator_type), \
|
||||
BOOST_SPIRIT_X3_INSTANTIATE_WRAP(typename ::boost::spirit::x3::detail::instantiate_macro_helper<__VA_ARGS__>::sentinel_type), \
|
||||
BOOST_SPIRIT_X3_INSTANTIATE_WRAP(typename ::boost::spirit::x3::detail::instantiate_macro_helper<__VA_ARGS__>::context_type) \
|
||||
)
|
||||
|
||||
#define BOOST_SPIRIT_INSTANTIATE(...) \
|
||||
BOOST_SPIRIT_X3_DEPRECATED_MACRO_WARN( \
|
||||
"Use `BOOST_SPIRIT_X3_INSTANTIATE`. `BOOST_SPIRIT_INSTANTIATE` is deprecated because " \
|
||||
"the name was not correctly prefixed with `X3`." \
|
||||
) \
|
||||
BOOST_SPIRIT_X3_INSTANTIATE(__VA_ARGS__)
|
||||
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2009 Hartmut Kaiser
|
||||
Copyright (c) 2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
Copyright (c) 2009 Hartmut Kaiser
|
||||
Copyright (c) 2014 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -55,7 +54,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
};
|
||||
|
||||
template <typename T, typename Encoding, typename BoolPolicies = bool_policies<T>>
|
||||
struct literal_bool_parser : parser<literal_bool_parser<T, Encoding, BoolPolicies>>
|
||||
struct literal_bool_parser : parser<bool_parser<T, Encoding, BoolPolicies>>
|
||||
{
|
||||
typedef Encoding encoding;
|
||||
typedef T attribute_type;
|
||||
@@ -115,7 +114,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
constexpr false_type false_ = { false };
|
||||
}
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
namespace standard_wide
|
||||
{
|
||||
typedef bool_parser<bool, char_encoding::standard_wide> bool_type;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2009 Hartmut Kaiser
|
||||
Copyright (c) 2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
Copyright (c) 2009 Hartmut Kaiser
|
||||
Copyright (c) 2014 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -12,22 +11,19 @@
|
||||
#include <boost/spirit/home/x3/string/detail/string_parse.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
|
||||
#include <string_view>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Default boolean policies
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T = bool>
|
||||
struct bool_policies
|
||||
{
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute, typename CaseCompare>
|
||||
[[nodiscard]] static constexpr bool
|
||||
parse_true(It& first, Se const& last, Attribute& attr_, CaseCompare const& case_compare)
|
||||
noexcept(std::is_nothrow_constructible_v<Attribute, T>)
|
||||
template <typename Iterator, typename Attribute, typename CaseCompare>
|
||||
static bool
|
||||
parse_true(Iterator& first, Iterator const& last, Attribute& attr_, CaseCompare const& case_compare)
|
||||
{
|
||||
using namespace std::string_view_literals;
|
||||
if (detail::string_parse("true"sv, first, last, unused, case_compare))
|
||||
if (detail::string_parse("true", first, last, unused, case_compare))
|
||||
{
|
||||
traits::move_to(T(true), attr_); // result is true
|
||||
return true;
|
||||
@@ -35,13 +31,11 @@ namespace boost::spirit::x3
|
||||
return false;
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute, typename CaseCompare>
|
||||
[[nodiscard]] static constexpr bool
|
||||
parse_false(It& first, Se const& last, Attribute& attr_, CaseCompare const& case_compare)
|
||||
noexcept(std::is_nothrow_constructible_v<Attribute, T>)
|
||||
template <typename Iterator, typename Attribute, typename CaseCompare>
|
||||
static bool
|
||||
parse_false(Iterator& first, Iterator const& last, Attribute& attr_, CaseCompare const& case_compare)
|
||||
{
|
||||
using namespace std::string_view_literals;
|
||||
if (detail::string_parse("false"sv, first, last, unused, case_compare))
|
||||
if (detail::string_parse("false", first, last, unused, case_compare))
|
||||
{
|
||||
traits::move_to(T(false), attr_); // result is false
|
||||
return true;
|
||||
@@ -49,6 +43,6 @@ namespace boost::spirit::x3
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -12,11 +11,11 @@
|
||||
#include <boost/spirit/home/x3/string/detail/string_parse.hpp>
|
||||
#include <boost/spirit/home/x3/support/numeric_utils/extract_int.hpp>
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
// Default (unsigned) real number policies
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Default (unsigned) real number policies
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct ureal_policies
|
||||
{
|
||||
@@ -73,24 +72,24 @@ namespace boost::spirit::x3
|
||||
return extract_int<int, 10, 1, -1>::call(first, last, attr_);
|
||||
}
|
||||
|
||||
// The parse_nan() and parse_inf() functions get called whenever
|
||||
// a number to parse does not start with a digit (after having
|
||||
// successfully parsed an optional sign).
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The parse_nan() and parse_inf() functions get called whenever
|
||||
// a number to parse does not start with a digit (after having
|
||||
// successfully parsed an optional sign).
|
||||
//
|
||||
// The functions should return true if a Nan or Inf has been found. In
|
||||
// this case the attr should be set to the matched value (NaN or
|
||||
// Inf). The optional sign will be automatically applied afterwards.
|
||||
// The functions should return true if a Nan or Inf has been found. In
|
||||
// this case the attr should be set to the matched value (NaN or
|
||||
// Inf). The optional sign will be automatically applied afterwards.
|
||||
//
|
||||
// The default implementation below recognizes representations of NaN
|
||||
// and Inf as mandated by the C99 Standard and as proposed for
|
||||
// inclusion into the C++0x Standard: nan, nan(...), inf and infinity
|
||||
// (the matching is performed case-insensitively).
|
||||
// The default implementation below recognizes representations of NaN
|
||||
// and Inf as mandated by the C99 Standard and as proposed for
|
||||
// inclusion into the C++0x Standard: nan, nan(...), inf and infinity
|
||||
// (the matching is performed case-insensitively).
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool
|
||||
parse_nan(Iterator& first, Iterator const& last, Attribute& attr_)
|
||||
{
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
if (first == last)
|
||||
return false; // end of input reached
|
||||
|
||||
@@ -98,7 +97,7 @@ namespace boost::spirit::x3
|
||||
return false; // not "nan"
|
||||
|
||||
// nan[(...)] ?
|
||||
if (detail::string_parse("nan"sv, "NAN"sv, first, last, unused))
|
||||
if (detail::string_parse("nan", "NAN", first, last, unused))
|
||||
{
|
||||
if (first != last && *first == '(')
|
||||
{
|
||||
@@ -122,8 +121,6 @@ namespace boost::spirit::x3
|
||||
static bool
|
||||
parse_inf(Iterator& first, Iterator const& last, Attribute& attr_)
|
||||
{
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
if (first == last)
|
||||
return false; // end of input reached
|
||||
|
||||
@@ -131,10 +128,10 @@ namespace boost::spirit::x3
|
||||
return false; // not "inf"
|
||||
|
||||
// inf or infinity ?
|
||||
if (detail::string_parse("inf"sv, "INF"sv, first, last, unused))
|
||||
if (detail::string_parse("inf", "INF", first, last, unused))
|
||||
{
|
||||
// skip allowed 'inity' part of infinity
|
||||
(void)detail::string_parse("inity"sv, "INITY"sv, first, last, unused);
|
||||
detail::string_parse("inity", "INITY", first, last, unused);
|
||||
attr_ = std::numeric_limits<T>::infinity();
|
||||
return true;
|
||||
}
|
||||
@@ -142,7 +139,9 @@ namespace boost::spirit::x3
|
||||
}
|
||||
};
|
||||
|
||||
// Default (signed) real number policies
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Default (signed) real number policies
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct real_policies : ureal_policies<T>
|
||||
{
|
||||
@@ -165,6 +164,6 @@ namespace boost::spirit::x3
|
||||
{
|
||||
static bool const expect_dot = true;
|
||||
};
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -15,42 +14,42 @@
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/variant_has_substitute.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/variant_find_substitute.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
#include <boost/fusion/include/front.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Left, typename Right>
|
||||
struct alternative;
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
struct pass_variant_unused
|
||||
{
|
||||
using type = unused_type;
|
||||
typedef unused_type type;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] static constexpr unused_type
|
||||
call(T&) noexcept
|
||||
static unused_type
|
||||
call(T&)
|
||||
{
|
||||
return unused_type{};
|
||||
return unused_type();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Attribute>
|
||||
struct pass_variant_used
|
||||
{
|
||||
using type = Attribute&;
|
||||
typedef Attribute& type;
|
||||
|
||||
[[nodiscard]] static constexpr Attribute&
|
||||
call(Attribute& v) noexcept
|
||||
static Attribute&
|
||||
call(Attribute& v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
@@ -59,44 +58,56 @@ namespace boost::spirit::x3::detail
|
||||
template <>
|
||||
struct pass_variant_used<unused_type> : pass_variant_unused {};
|
||||
|
||||
template <typename Parser, typename Attribute, typename Context, typename Enable = void>
|
||||
template <typename Parser, typename Attribute, typename Context
|
||||
, typename Enable = void>
|
||||
struct pass_parser_attribute
|
||||
{
|
||||
using attribute_type = traits::attribute_of_t<Parser, Context>;
|
||||
using substitute_type = traits::variant_find_substitute_t<Attribute, attribute_type>;
|
||||
typedef typename
|
||||
traits::attribute_of<Parser, Context>::type
|
||||
attribute_type;
|
||||
typedef typename
|
||||
traits::variant_find_substitute<Attribute, attribute_type>::type
|
||||
substitute_type;
|
||||
|
||||
using type = std::conditional_t<
|
||||
std::is_same_v<Attribute, substitute_type>,
|
||||
Attribute&,
|
||||
substitute_type
|
||||
>;
|
||||
typedef typename
|
||||
mpl::if_<
|
||||
is_same<Attribute, substitute_type>
|
||||
, Attribute&
|
||||
, substitute_type
|
||||
>::type
|
||||
type;
|
||||
|
||||
template <typename Attribute_>
|
||||
requires std::is_same_v<Attribute_, std::remove_reference_t<type>>
|
||||
[[nodiscard]] static constexpr Attribute_&
|
||||
call(Attribute_& attribute) noexcept
|
||||
static Attribute_&
|
||||
call(Attribute_& attribute, mpl::true_)
|
||||
{
|
||||
return attribute;
|
||||
}
|
||||
|
||||
template <typename Attribute_>
|
||||
requires (!std::is_same_v<Attribute_, std::remove_reference_t<type>>)
|
||||
[[nodiscard]] static type
|
||||
call(Attribute_&)
|
||||
noexcept(std::is_nothrow_default_constructible_v<type>)
|
||||
static type
|
||||
call(Attribute_&, mpl::false_)
|
||||
{
|
||||
return type{};
|
||||
return type();
|
||||
}
|
||||
|
||||
template <typename Attribute_>
|
||||
static type
|
||||
call(Attribute_& attribute)
|
||||
{
|
||||
return call(attribute, is_same<Attribute_, typename remove_reference<type>::type>());
|
||||
}
|
||||
};
|
||||
|
||||
// Pass non-variant attributes as-is
|
||||
template <typename Parser, typename Attribute, typename Context, typename Enable = void>
|
||||
template <typename Parser, typename Attribute, typename Context
|
||||
, typename Enable = void>
|
||||
struct pass_non_variant_attribute
|
||||
{
|
||||
using type = Attribute&;
|
||||
typedef Attribute& type;
|
||||
|
||||
[[nodiscard]] constexpr static Attribute&
|
||||
call(Attribute& attribute) noexcept
|
||||
static Attribute&
|
||||
call(Attribute& attribute)
|
||||
{
|
||||
return attribute;
|
||||
}
|
||||
@@ -104,110 +115,80 @@ namespace boost::spirit::x3::detail
|
||||
|
||||
// Unwrap single element sequences
|
||||
template <typename Parser, typename Attribute, typename Context>
|
||||
requires traits::is_size_one_sequence_v<Attribute>
|
||||
struct pass_non_variant_attribute<Parser, Attribute, Context>
|
||||
struct pass_non_variant_attribute<Parser, Attribute, Context,
|
||||
typename enable_if<traits::is_size_one_sequence<Attribute>>::type>
|
||||
{
|
||||
using attr_type = typename std::remove_reference_t<
|
||||
typename fusion::result_of::front<Attribute>::type
|
||||
>;
|
||||
using pass = pass_parser_attribute<Parser, attr_type, Context>;
|
||||
using type = typename pass::type;
|
||||
typedef typename remove_reference<
|
||||
typename fusion::result_of::front<Attribute>::type>::type
|
||||
attr_type;
|
||||
|
||||
typedef pass_parser_attribute<Parser, attr_type, Context> pass;
|
||||
typedef typename pass::type type;
|
||||
|
||||
template <typename Attribute_>
|
||||
[[nodiscard]] static constexpr type
|
||||
static type
|
||||
call(Attribute_& attr)
|
||||
noexcept(noexcept(pass::call(fusion::front(attr))))
|
||||
{
|
||||
return pass::call(fusion::front(attr));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Parser, typename Attribute, typename Context>
|
||||
requires (!traits::is_variant_v<Attribute>)
|
||||
struct pass_parser_attribute<Parser, Attribute, Context>
|
||||
struct pass_parser_attribute<Parser, Attribute, Context,
|
||||
typename enable_if_c<(!traits::is_variant<Attribute>::value)>::type>
|
||||
: pass_non_variant_attribute<Parser, Attribute, Context>
|
||||
{};
|
||||
|
||||
template <typename Parser, typename Context>
|
||||
struct pass_parser_attribute<Parser, unused_type, Context>
|
||||
: pass_variant_unused
|
||||
{};
|
||||
: pass_variant_unused {};
|
||||
|
||||
template <typename Parser, typename Attribute, typename Context>
|
||||
struct pass_variant_attribute
|
||||
: std::conditional_t<
|
||||
traits::has_attribute_v<Parser, Context>,
|
||||
pass_parser_attribute<Parser, Attribute, Context>,
|
||||
pass_variant_unused
|
||||
>
|
||||
{};
|
||||
struct pass_variant_attribute :
|
||||
mpl::if_c<traits::has_attribute<Parser, Context>::value
|
||||
, pass_parser_attribute<Parser, Attribute, Context>
|
||||
, pass_variant_unused>::type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename L, typename R, typename Attribute, typename Context>
|
||||
struct pass_variant_attribute<alternative<L, R>, Attribute, Context>
|
||||
: std::conditional_t<
|
||||
traits::has_attribute_v<alternative<L, R>, Context>,
|
||||
pass_variant_used<Attribute>,
|
||||
pass_variant_unused
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Parser, std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename Attribute>
|
||||
using parse_alternative_pseudo_t = traits::pseudo_attribute<
|
||||
Context, typename pass_variant_attribute<Parser, Attribute, Context>::type, It, Se
|
||||
>;
|
||||
|
||||
template <typename Parser, std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename Attribute>
|
||||
constexpr bool is_reference_pseudo_type = std::is_reference_v<typename parse_alternative_pseudo_t<Parser, It, Se, Context, Attribute>::type>;
|
||||
|
||||
template <typename Parser, std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires is_reference_pseudo_type<Parser, It, Se, Context, Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse_alternative(
|
||||
Parser const& p, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attribute
|
||||
) noexcept(
|
||||
noexcept(parse_alternative_pseudo_t<Parser, It, Se, Context, Attribute>::call(
|
||||
first, last, pass_variant_attribute<Parser, Attribute, Context>::call(attribute)
|
||||
)) &&
|
||||
is_nothrow_parsable_v<
|
||||
Parser, It, Se, Context, RContext,
|
||||
std::remove_reference_t<typename parse_alternative_pseudo_t<Parser, It, Se, Context, Attribute>::type>
|
||||
>
|
||||
)
|
||||
struct pass_variant_attribute<alternative<L, R>, Attribute, Context> :
|
||||
mpl::if_c<traits::has_attribute<alternative<L, R>, Context>::value
|
||||
, pass_variant_used<Attribute>
|
||||
, pass_variant_unused>::type
|
||||
{
|
||||
using pass = pass_variant_attribute<Parser, Attribute, Context>;
|
||||
using pseudo = traits::pseudo_attribute<Context, typename pass::type, It, Se>;
|
||||
typename pseudo::type attr_ = pseudo::call(first, last, pass::call(attribute));
|
||||
return p.parse(first, last, context, rcontext, attr_);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Parser, std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires (!is_reference_pseudo_type<Parser, It, Se, Context, Attribute>)
|
||||
[[nodiscard]] constexpr bool
|
||||
parse_alternative(
|
||||
Parser const& p, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attribute
|
||||
) noexcept(
|
||||
noexcept(parse_alternative_pseudo_t<Parser, It, Se, Context, Attribute>::call(
|
||||
first, last, pass_variant_attribute<Parser, Attribute, Context>::call(attribute)
|
||||
)) &&
|
||||
is_nothrow_parsable_v<
|
||||
Parser, It, Se, Context, RContext,
|
||||
std::remove_reference_t<typename parse_alternative_pseudo_t<Parser, It, Se, Context, Attribute>::type>
|
||||
> &&
|
||||
noexcept(traits::move_to(
|
||||
std::declval<typename parse_alternative_pseudo_t<Parser, It, Se, Context, Attribute>::type&&>(),
|
||||
attribute
|
||||
))
|
||||
)
|
||||
template <bool Condition>
|
||||
struct move_if
|
||||
{
|
||||
using pass = pass_variant_attribute<Parser, Attribute, Context>;
|
||||
using pseudo = traits::pseudo_attribute<Context, typename pass::type, It, Se>;
|
||||
template<typename T1, typename T2>
|
||||
static void call(T1& /* attr_ */, T2& /* attr */) {}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct move_if<true>
|
||||
{
|
||||
template<typename T1, typename T2>
|
||||
static void call(T1& attr_, T2& attribute)
|
||||
{
|
||||
traits::move_to(attr_, attribute);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Parser, typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse_alternative(Parser const& p, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attribute)
|
||||
{
|
||||
using pass = detail::pass_variant_attribute<Parser, Attribute, Context>;
|
||||
using pseudo = traits::pseudo_attribute<Context, typename pass::type, Iterator>;
|
||||
|
||||
typename pseudo::type attr_ = pseudo::call(first, last, pass::call(attribute));
|
||||
|
||||
if (p.parse(first, last, context, rcontext, attr_))
|
||||
{
|
||||
traits::move_to(std::move(attr_), attribute);
|
||||
move_if<!std::is_reference<decltype(attr_)>::value>::call(attr_, attribute);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -216,14 +197,14 @@ namespace boost::spirit::x3::detail
|
||||
template <typename Subject>
|
||||
struct alternative_helper : unary_parser<Subject, alternative_helper<Subject>>
|
||||
{
|
||||
static constexpr bool is_pass_through_unary = true;
|
||||
static bool const is_pass_through_unary = true;
|
||||
|
||||
using unary_parser<Subject, alternative_helper<Subject>>::unary_parser;
|
||||
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool parse(
|
||||
Iterator& first, Iterator const& last, Context const& context, RContext& rcontext, Attribute& attr
|
||||
) const noexcept(noexcept(detail::parse_alternative(this->subject, first, last, context, rcontext, attr)))
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
return detail::parse_alternative(this->subject, first, last, context, rcontext, attr);
|
||||
}
|
||||
@@ -232,34 +213,39 @@ namespace boost::spirit::x3::detail
|
||||
template <typename Left, typename Right, typename Context, typename RContext>
|
||||
struct parse_into_container_impl<alternative<Left, Right>, Context, RContext>
|
||||
{
|
||||
using parser_type = alternative<Left, Right>;
|
||||
typedef alternative<Left, Right> parser_type;
|
||||
|
||||
template <typename Iterator, typename Attribute>
|
||||
requires traits::is_variant_v<traits::container_value_t<Attribute>>
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
parser_type const& parser,
|
||||
Iterator& first, Iterator const& last, Context const& context, RContext& rcontext, Attribute& attribute
|
||||
)
|
||||
static bool call(
|
||||
parser_type const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attribute, mpl::false_)
|
||||
{
|
||||
return detail::parse_into_container(parser.left, first, last, context, rcontext, attribute)
|
||||
|| detail::parse_into_container(parser.right, first, last, context, rcontext, attribute);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
parser_type const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attribute, mpl::true_)
|
||||
{
|
||||
return detail::parse_into_container(alternative_helper<Left>{parser.left}, first, last, context, rcontext, attribute)
|
||||
|| detail::parse_into_container(alternative_helper<Right>{parser.right}, first, last, context, rcontext, attribute);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Attribute>
|
||||
requires (!traits::is_variant_v<traits::container_value_t<Attribute>>)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
parser_type const& parser,
|
||||
Iterator& first, Iterator const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attribute
|
||||
)
|
||||
static bool call(
|
||||
parser_type const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attribute)
|
||||
{
|
||||
return detail::parse_into_container(parser.left, first, last, context, rcontext, attribute)
|
||||
|| detail::parse_into_container(parser.right, first, last, context, rcontext, attribute);
|
||||
return call(parser, first, last, context, rcontext, attribute,
|
||||
typename traits::is_variant<typename traits::container_value<Attribute>::type>::type{});
|
||||
}
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::detail
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -26,15 +25,18 @@
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
#include <iterator> // for std::make_move_iterator
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Left, typename Right>
|
||||
struct sequence;
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
template <typename Parser, typename Context, typename Enable = void>
|
||||
struct sequence_size
|
||||
@@ -356,62 +358,62 @@ namespace boost::spirit::x3::detail
|
||||
template <typename Left, typename Right, typename Context, typename RContext>
|
||||
struct parse_into_container_impl<sequence<Left, Right>, Context, RContext>
|
||||
{
|
||||
using parser_type = sequence<Left, Right>;
|
||||
typedef sequence<Left, Right> parser_type;
|
||||
|
||||
template <typename Attribute>
|
||||
static constexpr bool is_container_substitute = traits::is_substitute_v<
|
||||
traits::attribute_of_t<parser_type, Context>,
|
||||
traits::container_value_t<Attribute>
|
||||
>;
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
requires is_container_substitute<Attribute>
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
parser_type const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) noexcept(noexcept(parse_into_container_base_impl<parser_type>::call(
|
||||
parser, first, last, context, rcontext, attr
|
||||
)))
|
||||
{
|
||||
return parse_into_container_base_impl<parser_type>::call(
|
||||
parser, first, last, context, rcontext, attr
|
||||
);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
requires (!is_container_substitute<Attribute>)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
parser_type const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) // never noexcept (requires container insertion)
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
parser_type const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
|
||||
{
|
||||
// inform user what went wrong if we jumped here in attempt to
|
||||
// parse incompatible sequence into fusion::map
|
||||
static_assert(
|
||||
!std::is_same_v<traits::attribute_category_t<Attribute>, traits::associative_attribute>,
|
||||
"To parse directly into fusion::map sequence must produce tuple attribute "
|
||||
"where type of first element is existing key in fusion::map and second element "
|
||||
"is value to be stored under that key"
|
||||
);
|
||||
static_assert(!is_same< typename traits::attribute_category<Attribute>::type,
|
||||
traits::associative_attribute>::value,
|
||||
"To parse directly into fusion::map sequence must produce tuple attribute "
|
||||
"where type of first element is existing key in fusion::map and second element "
|
||||
"is value to be stored under that key");
|
||||
|
||||
Attribute attr_{};
|
||||
if (!detail::parse_sequence(
|
||||
parser, first, last, context, rcontext, attr_, traits::container_attribute()
|
||||
))
|
||||
if (!parse_sequence(parser
|
||||
, first, last, context, rcontext, attr_, traits::container_attribute()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
traits::append(
|
||||
attr,
|
||||
std::make_move_iterator(traits::begin(attr_)),
|
||||
std::make_move_iterator(traits::end(attr_))
|
||||
);
|
||||
traits::append(attr, std::make_move_iterator(traits::begin(attr_)),
|
||||
std::make_move_iterator(traits::end(attr_)));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
parser_type const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
|
||||
{
|
||||
return parse_into_container_base_impl<parser_type>::call(
|
||||
parser, first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
parser_type const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr)
|
||||
{
|
||||
typedef typename
|
||||
traits::attribute_of<parser_type, Context>::type
|
||||
attribute_type;
|
||||
|
||||
typedef typename
|
||||
traits::container_value<Attribute>::type
|
||||
value_type;
|
||||
|
||||
return call(parser, first, last, context, rcontext, attr
|
||||
, typename traits::is_substitute<attribute_type, value_type>::type());
|
||||
}
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::detail
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2017 wanghan02
|
||||
Copyright (c) 2024-2025 Nana Sakisaka
|
||||
Copyright (c) 2024 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -10,7 +10,7 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_OPTIONAL_MARCH_23_2007_1117PM)
|
||||
#define BOOST_SPIRIT_X3_OPTIONAL_MARCH_23_2007_1117PM
|
||||
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/proxy.hpp>
|
||||
#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
|
||||
@@ -18,101 +18,72 @@
|
||||
#include <boost/spirit/home/x3/support/traits/optional_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Subject>
|
||||
struct optional : unary_parser<Subject, optional<Subject>>
|
||||
struct optional : proxy<Subject, optional<Subject>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, optional<Subject>>;
|
||||
static constexpr bool is_pass_through_unary = false;
|
||||
static constexpr bool handles_container = true;
|
||||
typedef proxy<Subject, optional<Subject>> base_type;
|
||||
static bool const is_pass_through_unary = false;
|
||||
static bool const handles_container = true;
|
||||
|
||||
template <typename SubjectT>
|
||||
requires std::is_constructible_v<Subject, SubjectT>
|
||||
constexpr optional(SubjectT&& subject)
|
||||
noexcept(std::is_nothrow_constructible_v<Subject, SubjectT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
{}
|
||||
constexpr optional(Subject const& subject)
|
||||
: base_type(subject) {}
|
||||
|
||||
// catch-all overload
|
||||
template <
|
||||
std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext,
|
||||
typename Attribute // unconstrained
|
||||
>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr
|
||||
) const
|
||||
noexcept(is_nothrow_parsable_v<Subject, It, Se, Context, RContext, Attribute>)
|
||||
using base_type::parse_subject;
|
||||
|
||||
// Attribute is a container
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse_subject(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr
|
||||
, traits::container_attribute) const
|
||||
{
|
||||
static_assert(Parsable<Subject, It, Se, Context, RContext, Attribute>);
|
||||
|
||||
// discard [[nodiscard]]
|
||||
(void)this->subject.parse(first, last, context, rcontext, attr);
|
||||
return !x3::has_expectation_failure(context);
|
||||
detail::parse_into_container(
|
||||
this->subject, first, last, context, rcontext, attr);
|
||||
return !has_expectation_failure(context);
|
||||
}
|
||||
|
||||
// container attribute
|
||||
template <
|
||||
std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext,
|
||||
traits::CategorizedAttr<traits::container_attribute> Attribute
|
||||
>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
noexcept(noexcept(detail::parse_into_container(this->subject, first, last, context, rcontext, attr)))
|
||||
// Attribute is an optional
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse_subject(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr
|
||||
, traits::optional_attribute) const
|
||||
{
|
||||
// discard [[nodiscard]]
|
||||
(void)detail::parse_into_container(this->subject, first, last, context, rcontext, attr);
|
||||
return !x3::has_expectation_failure(context);
|
||||
}
|
||||
typedef typename
|
||||
x3::traits::optional_value<Attribute>::type
|
||||
value_type;
|
||||
|
||||
// optional attribute
|
||||
template <
|
||||
std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext,
|
||||
traits::CategorizedAttr<traits::optional_attribute> Attribute
|
||||
>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
noexcept(
|
||||
std::is_nothrow_default_constructible_v<x3::traits::optional_value_t<Attribute>> &&
|
||||
is_nothrow_parsable_v<Subject, It, Se, Context, RContext, x3::traits::optional_value_t<Attribute>> &&
|
||||
noexcept(x3::traits::move_to(std::declval<x3::traits::optional_value_t<Attribute>&&>(), attr))
|
||||
)
|
||||
{
|
||||
using value_type = x3::traits::optional_value_t<Attribute>;
|
||||
value_type val; // default-initialize
|
||||
// create a local value
|
||||
value_type val{};
|
||||
|
||||
static_assert(Parsable<Subject, It, Se, Context, RContext, value_type>);
|
||||
if (this->subject.parse(first, last, context, rcontext, val))
|
||||
{
|
||||
// assign the parsed value into our attribute
|
||||
x3::traits::move_to(std::move(val), attr);
|
||||
return true;
|
||||
}
|
||||
x3::traits::move_to(val, attr);
|
||||
|
||||
return !x3::has_expectation_failure(context);
|
||||
} else {
|
||||
return !has_expectation_failure(context);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] constexpr optional<as_parser_plain_t<Subject>>
|
||||
operator-(Subject&& subject)
|
||||
noexcept(is_parser_nothrow_constructible_v<optional<as_parser_plain_t<Subject>>, Subject>)
|
||||
template <typename Subject>
|
||||
constexpr optional<typename extension::as_parser<Subject>::value_type>
|
||||
operator-(Subject const& subject)
|
||||
{
|
||||
return { as_parser(std::forward<Subject>(subject)) };
|
||||
return { as_parser(subject) };
|
||||
}
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename Subject, typename Context>
|
||||
struct attribute_of<x3::optional<Subject>, Context>
|
||||
: build_optional<attribute_of_t<Subject, Context>>
|
||||
{};
|
||||
} // boost::spirit::x3::traits
|
||||
: build_optional<
|
||||
typename attribute_of<Subject, Context>::type> {};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -9,7 +8,6 @@
|
||||
#define BOOST_SPIRIT_X3_STRING_FEBRUARY_03_2007_0355PM
|
||||
|
||||
#include <boost/spirit/home/x3/string/literal_string.hpp>
|
||||
#include <boost/spirit/home/x3/string/string.hpp>
|
||||
#include <boost/spirit/home/x3/string/symbols.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -10,22 +9,36 @@
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
|
||||
#include <string_view>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
template <typename CharT, typename CharTraitsT, std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute, typename CaseCompareFunc>
|
||||
[[nodiscard]] constexpr bool
|
||||
string_parse(
|
||||
std::basic_string_view<CharT, CharTraitsT> const str,
|
||||
It& first, Se const& last,
|
||||
Attribute& attr, CaseCompareFunc const& compare
|
||||
) noexcept(std::is_same_v<std::remove_const_t<Attribute>, unused_type>)
|
||||
template <typename Char, typename Iterator, typename Attribute, typename CaseCompareFunc>
|
||||
inline bool string_parse(
|
||||
Char const* str
|
||||
, Iterator& first, Iterator const& last, Attribute& attr, CaseCompareFunc const& compare)
|
||||
{
|
||||
It i = first;
|
||||
auto stri = str.begin();
|
||||
auto str_last = str.end();
|
||||
Iterator i = first;
|
||||
Char ch = *str;
|
||||
|
||||
for (; !!ch; ++i)
|
||||
{
|
||||
if (i == last || (compare(ch, *i) != 0))
|
||||
return false;
|
||||
ch = *++str;
|
||||
}
|
||||
|
||||
x3::traits::move_to(first, i, attr);
|
||||
first = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename String, typename Iterator, typename Attribute, typename CaseCompareFunc>
|
||||
inline bool string_parse(
|
||||
String const& str
|
||||
, Iterator& first, Iterator const& last, Attribute& attr, CaseCompareFunc const& compare)
|
||||
{
|
||||
Iterator i = first;
|
||||
typename String::const_iterator stri = str.begin();
|
||||
typename String::const_iterator str_last = str.end();
|
||||
|
||||
for (; stri != str_last; ++stri, ++i)
|
||||
if (i == last || (compare(*stri, *i) != 0))
|
||||
@@ -35,29 +48,30 @@ namespace boost::spirit::x3::detail
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CharT, typename CharTraitsT, std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute, typename CaseCompareFunc>
|
||||
[[nodiscard]] constexpr bool
|
||||
string_parse(
|
||||
std::basic_string<CharT, CharTraitsT> const& str,
|
||||
It& first, Se const& last,
|
||||
Attribute& attr, CaseCompareFunc const& compare
|
||||
) noexcept(std::is_same_v<std::remove_const_t<Attribute>, unused_type>)
|
||||
template <typename Char, typename Iterator, typename Attribute>
|
||||
inline bool string_parse(
|
||||
Char const* uc_i, Char const* lc_i
|
||||
, Iterator& first, Iterator const& last, Attribute& attr)
|
||||
{
|
||||
return detail::string_parse(std::basic_string_view{str}, first, last, attr, compare);
|
||||
Iterator i = first;
|
||||
|
||||
for (; *uc_i && *lc_i; ++uc_i, ++lc_i, ++i)
|
||||
if (i == last || ((*uc_i != *i) && (*lc_i != *i)))
|
||||
return false;
|
||||
x3::traits::move_to(first, i, attr);
|
||||
first = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CharT, typename CharTraitsT, std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
string_parse(
|
||||
std::basic_string_view<CharT, CharTraitsT> const ucstr,
|
||||
std::basic_string_view<CharT, CharTraitsT> const lcstr,
|
||||
It& first, Se const& last, Attribute& attr
|
||||
) noexcept(std::is_same_v<std::remove_const_t<Attribute>, unused_type>)
|
||||
template <typename String, typename Iterator, typename Attribute>
|
||||
inline bool string_parse(
|
||||
String const& ucstr, String const& lcstr
|
||||
, Iterator& first, Iterator const& last, Attribute& attr)
|
||||
{
|
||||
auto uc_i = ucstr.begin();
|
||||
auto uc_last = ucstr.end();
|
||||
auto lc_i = lcstr.begin();
|
||||
It i = first;
|
||||
typename String::const_iterator uc_i = ucstr.begin();
|
||||
typename String::const_iterator uc_last = ucstr.end();
|
||||
typename String::const_iterator lc_i = lcstr.begin();
|
||||
Iterator i = first;
|
||||
|
||||
for (; uc_i != uc_last; ++uc_i, ++lc_i, ++i)
|
||||
if (i == last || ((*uc_i != *i) && (*lc_i != *i)))
|
||||
@@ -66,17 +80,6 @@ namespace boost::spirit::x3::detail
|
||||
first = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CharT, typename CharTraitsT, std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
string_parse(
|
||||
std::basic_string<CharT, CharTraitsT> const& ucstr,
|
||||
std::basic_string<CharT, CharTraitsT> const& lcstr,
|
||||
It& first, Se const& last, Attribute& attr
|
||||
) noexcept(std::is_same_v<std::remove_const_t<Attribute>, unused_type>)
|
||||
{
|
||||
return detail::string_parse(std::basic_string_view{ucstr}, std::basic_string_view{lcstr}, first, last, attr);
|
||||
}
|
||||
} // boost::spirit::x3::detail
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
202
include/boost/spirit/home/x3/string/detail/tst.hpp
Normal file
202
include/boost/spirit/home/x3/string/detail/tst.hpp
Normal file
@@ -0,0 +1,202 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_X3_TST_MARCH_09_2007_0905AM)
|
||||
#define BOOST_SPIRIT_X3_TST_MARCH_09_2007_0905AM
|
||||
|
||||
#include <boost/call_traits.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
// This file contains low level TST routines, not for
|
||||
// public consumption.
|
||||
|
||||
template <typename Char, typename T>
|
||||
struct tst_node
|
||||
{
|
||||
tst_node(Char id)
|
||||
: id(id), data(0), lt(0), eq(0), gt(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Alloc>
|
||||
static void
|
||||
destruct_node(tst_node* p, Alloc* alloc)
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
if (p->data)
|
||||
alloc->delete_data(p->data);
|
||||
destruct_node(p->lt, alloc);
|
||||
destruct_node(p->eq, alloc);
|
||||
destruct_node(p->gt, alloc);
|
||||
alloc->delete_node(p);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Alloc>
|
||||
static tst_node*
|
||||
clone_node(tst_node* p, Alloc* alloc)
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
tst_node* clone = alloc->new_node(p->id);
|
||||
if (p->data)
|
||||
clone->data = alloc->new_data(*p->data);
|
||||
clone->lt = clone_node(p->lt, alloc);
|
||||
clone->eq = clone_node(p->eq, alloc);
|
||||
clone->gt = clone_node(p->gt, alloc);
|
||||
return clone;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename CaseCompare>
|
||||
static T*
|
||||
find(tst_node* start, Iterator& first, Iterator last, CaseCompare comp)
|
||||
{
|
||||
if (first == last)
|
||||
return 0;
|
||||
|
||||
Iterator i = first;
|
||||
Iterator latest = first;
|
||||
tst_node* p = start;
|
||||
T* found = 0;
|
||||
|
||||
while (p && i != last)
|
||||
{
|
||||
int32_t c = comp(*i,p->id);
|
||||
if (c == 0)
|
||||
{
|
||||
if (p->data)
|
||||
{
|
||||
found = p->data;
|
||||
latest = i;
|
||||
}
|
||||
p = p->eq;
|
||||
i++;
|
||||
}
|
||||
else if (c < 0)
|
||||
{
|
||||
p = p->lt;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = p->gt;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
first = ++latest; // one past the last matching char
|
||||
return found;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Alloc>
|
||||
static T*
|
||||
add(
|
||||
tst_node*& start
|
||||
, Iterator first
|
||||
, Iterator last
|
||||
, typename boost::call_traits<T>::param_type val
|
||||
, Alloc* alloc)
|
||||
{
|
||||
if (first == last)
|
||||
return 0;
|
||||
|
||||
tst_node** pp = &start;
|
||||
for (;;)
|
||||
{
|
||||
auto c = *first;
|
||||
|
||||
if (*pp == 0)
|
||||
*pp = alloc->new_node(c);
|
||||
tst_node* p = *pp;
|
||||
|
||||
if (c == p->id)
|
||||
{
|
||||
if (++first == last)
|
||||
{
|
||||
if (p->data == 0)
|
||||
p->data = alloc->new_data(val);
|
||||
return p->data;
|
||||
}
|
||||
pp = &p->eq;
|
||||
}
|
||||
else if (c < p->id)
|
||||
{
|
||||
pp = &p->lt;
|
||||
}
|
||||
else
|
||||
{
|
||||
pp = &p->gt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Alloc>
|
||||
static void
|
||||
remove(tst_node*& p, Iterator first, Iterator last, Alloc* alloc)
|
||||
{
|
||||
if (p == 0 || first == last)
|
||||
return;
|
||||
|
||||
auto c = *first;
|
||||
|
||||
if (c == p->id)
|
||||
{
|
||||
if (++first == last)
|
||||
{
|
||||
if (p->data)
|
||||
{
|
||||
alloc->delete_data(p->data);
|
||||
p->data = 0;
|
||||
}
|
||||
}
|
||||
remove(p->eq, first, last, alloc);
|
||||
}
|
||||
else if (c < p->id)
|
||||
{
|
||||
remove(p->lt, first, last, alloc);
|
||||
}
|
||||
else
|
||||
{
|
||||
remove(p->gt, first, last, alloc);
|
||||
}
|
||||
|
||||
if (p->data == 0 && p->lt == 0 && p->eq == 0 && p->gt == 0)
|
||||
{
|
||||
alloc->delete_node(p);
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static void
|
||||
for_each(tst_node* p, std::basic_string<Char> prefix, F f)
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
for_each(p->lt, prefix, f);
|
||||
std::basic_string<Char> s = prefix + p->id;
|
||||
for_each(p->eq, s, f);
|
||||
if (p->data)
|
||||
f(s, *p->data);
|
||||
for_each(p->gt, prefix, f);
|
||||
}
|
||||
}
|
||||
|
||||
Char id; // the node's identity character
|
||||
T* data; // optional data
|
||||
tst_node* lt; // left pointer
|
||||
tst_node* eq; // middle pointer
|
||||
tst_node* gt; // right pointer
|
||||
};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
@@ -1,175 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_X3_TST_MARCH_09_2007_0905AM)
|
||||
#define BOOST_SPIRIT_X3_TST_MARCH_09_2007_0905AM
|
||||
|
||||
#include <boost/spirit/home/x3/core/config.hpp>
|
||||
#include <boost/spirit/home/x3/support/allocator.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
{
|
||||
// This file contains low level TST routines, not for
|
||||
// public consumption.
|
||||
|
||||
template <typename Char, typename T, typename Alloc = std::allocator<T>>
|
||||
struct tst_node
|
||||
{
|
||||
using allocator_type = Alloc;
|
||||
using node_allocator_type = std::allocator_traits<Alloc>::template rebind_alloc<tst_node>;
|
||||
|
||||
constexpr explicit tst_node(Char id, Alloc const& alloc = {}) noexcept
|
||||
: alloc(alloc)
|
||||
, node_alloc(this->alloc)
|
||||
, id(id)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr tst_node(tst_node const& rhs)
|
||||
: alloc(std::allocator_traits<Alloc>::select_on_container_copy_construction(rhs.alloc))
|
||||
, node_alloc(std::allocator_traits<node_allocator_type>::select_on_container_copy_construction(rhs.node_alloc))
|
||||
, id(rhs.id)
|
||||
, data(allocator_ops<tst_node>::template copy_construct<&tst_node::alloc, &tst_node::data>(*this, rhs))
|
||||
, lt(allocator_ops<tst_node>::template copy_construct<&tst_node::node_alloc, &tst_node::lt>(*this, rhs))
|
||||
, eq(allocator_ops<tst_node>::template copy_construct<&tst_node::node_alloc, &tst_node::eq>(*this, rhs))
|
||||
, gt(allocator_ops<tst_node>::template copy_construct<&tst_node::node_alloc, &tst_node::gt>(*this, rhs))
|
||||
{
|
||||
}
|
||||
|
||||
constexpr tst_node(tst_node&& rhs) noexcept
|
||||
: alloc(std::move(rhs.alloc))
|
||||
, node_alloc(std::move(rhs.node_alloc))
|
||||
, id(std::move(rhs.id))
|
||||
, data(std::exchange(rhs.data, nullptr))
|
||||
, lt(std::exchange(rhs.lt, nullptr))
|
||||
, eq(std::exchange(rhs.eq, nullptr))
|
||||
, gt(std::exchange(rhs.gt, nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
constexpr ~tst_node() noexcept
|
||||
{
|
||||
allocator_ops<tst_node>::template destroy_deallocate<
|
||||
&tst_node::alloc, &tst_node::data
|
||||
>(*this);
|
||||
|
||||
allocator_ops<tst_node>::template destroy_deallocate<
|
||||
&tst_node::node_alloc,
|
||||
&tst_node::lt, &tst_node::eq, &tst_node::gt
|
||||
>(*this);
|
||||
}
|
||||
|
||||
constexpr tst_node& operator=(tst_node const& rhs)
|
||||
{
|
||||
if (std::addressof(rhs) == this) return *this;
|
||||
|
||||
id = rhs.id;
|
||||
|
||||
allocator_ops<tst_node>::template copy_assign<
|
||||
&tst_node::alloc, &tst_node::data
|
||||
>(*this, rhs);
|
||||
|
||||
allocator_ops<tst_node>::template copy_assign<
|
||||
&tst_node::node_alloc,
|
||||
&tst_node::lt, &tst_node::eq, &tst_node::gt
|
||||
>(*this, rhs);
|
||||
}
|
||||
|
||||
constexpr tst_node& operator=(tst_node&& rhs)
|
||||
noexcept(allocator_ops<tst_node>::template move_assign_noexcept<allocator_type, node_allocator_type>)
|
||||
{
|
||||
if (std::addressof(rhs) == this) return *this;
|
||||
|
||||
id = std::move(rhs.id);
|
||||
|
||||
allocator_ops<tst_node>::template move_assign<
|
||||
&tst_node::alloc, &tst_node::data
|
||||
>(*this, std::move(rhs));
|
||||
|
||||
allocator_ops<tst_node>::template move_assign<
|
||||
&tst_node::node_alloc,
|
||||
&tst_node::lt, &tst_node::eq, &tst_node::gt
|
||||
>(*this, std::move(rhs));
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator, typename CaseCompare>
|
||||
[[nodiscard]] static constexpr T*
|
||||
find(tst_node* start, Iterator& first, Iterator last, CaseCompare const& comp) noexcept
|
||||
{
|
||||
if (first == last) return nullptr;
|
||||
|
||||
Iterator i = first;
|
||||
Iterator latest = first;
|
||||
tst_node* p = start;
|
||||
T* found = nullptr;
|
||||
|
||||
while (p && i != last)
|
||||
{
|
||||
auto c = comp(*i,p->id);
|
||||
if (c == 0) {
|
||||
if (p->data)
|
||||
{
|
||||
found = p->data;
|
||||
latest = i;
|
||||
}
|
||||
p = p->eq;
|
||||
++i;
|
||||
}
|
||||
else if (c < 0)
|
||||
{
|
||||
p = p->lt;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = p->gt;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
first = ++latest; // one past the last matching char
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static void
|
||||
for_each(tst_node* const p, std::basic_string_view<Char> const prefix, F&& f)
|
||||
{
|
||||
if (!p) return;
|
||||
|
||||
tst_node::for_each(p->lt, prefix, f);
|
||||
std::basic_string<Char> s = std::basic_string<Char>(prefix) + p->id;
|
||||
tst_node::for_each(p->eq, s, f);
|
||||
if (p->data)
|
||||
{
|
||||
f(s, *p->data);
|
||||
}
|
||||
tst_node::for_each(p->gt, prefix, f);
|
||||
}
|
||||
|
||||
friend struct allocator_ops<tst_node>;
|
||||
|
||||
BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS Alloc alloc;
|
||||
BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS node_allocator_type node_alloc;
|
||||
Char id; // the node's identity character
|
||||
T* data = nullptr; // optional data
|
||||
tst_node* lt = nullptr; // left pointer
|
||||
tst_node* eq = nullptr; // middle pointer
|
||||
tst_node* gt = nullptr; // right pointer
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -8,66 +7,276 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_LITERAL_STRING_APR_18_2006_1125PM)
|
||||
#define BOOST_SPIRIT_X3_LITERAL_STRING_APR_18_2006_1125PM
|
||||
|
||||
#include <boost/spirit/home/x3/string/detail/string_parse.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/skip_over.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/spirit/home/x3/string/detail/string_parse.hpp>
|
||||
#include <boost/spirit/home/x3/support/no_case.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/utf8.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard_wide.hpp>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename String, typename Encoding, typename Attribute = std::basic_string<typename Encoding::char_type>>
|
||||
template <typename String, typename Encoding,
|
||||
typename Attribute = std::basic_string<typename Encoding::char_type>>
|
||||
struct literal_string : parser<literal_string<String, Encoding, Attribute>>
|
||||
{
|
||||
static_assert(
|
||||
!std::is_pointer_v<std::decay_t<String>>,
|
||||
"`literal_string` for raw character pointer/array is banned; it has an undetectable risk of holding a dangling pointer."
|
||||
);
|
||||
static_assert(std::is_convertible_v<String, std::basic_string_view<typename String::value_type>>);
|
||||
typedef typename Encoding::char_type char_type;
|
||||
typedef Encoding encoding;
|
||||
typedef Attribute attribute_type;
|
||||
static bool const has_attribute =
|
||||
!is_same<unused_type, attribute_type>::value;
|
||||
static bool const handles_container = has_attribute;
|
||||
|
||||
using char_type = typename Encoding::char_type;
|
||||
using encoding = Encoding;
|
||||
using attribute_type = Attribute;
|
||||
static constexpr bool has_attribute = !std::is_same_v<unused_type, attribute_type>;
|
||||
static constexpr bool handles_container = has_attribute;
|
||||
|
||||
template<class... Args>
|
||||
requires std::is_constructible_v<String, Args...>
|
||||
constexpr literal_string(Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible_v<String, Args...>)
|
||||
: str(std::forward<Args>(args)...)
|
||||
constexpr literal_string(typename add_reference< typename add_const<String>::type >::type str)
|
||||
: str(str)
|
||||
{}
|
||||
|
||||
template <typename Iterator, typename Context, typename Attribute_>
|
||||
[[nodiscard]] constexpr bool parse(
|
||||
Iterator& first, Iterator const& last,
|
||||
Context const& context, unused_type, Attribute_& attr
|
||||
) const
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, unused_type, Attribute_& attr) const
|
||||
{
|
||||
x3::skip_over(first, last, context);
|
||||
return detail::string_parse(str, first, last, attr, x3::get_case_compare<encoding>(context));
|
||||
return detail::string_parse(str, first, last, attr, get_case_compare<encoding>(context));
|
||||
}
|
||||
|
||||
String str;
|
||||
};
|
||||
|
||||
namespace standard
|
||||
{
|
||||
constexpr literal_string<char const*, char_encoding::standard>
|
||||
string(char const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<char>, char_encoding::standard>
|
||||
string(std::basic_string<char> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline constexpr literal_string<char const*, char_encoding::standard, unused_type>
|
||||
lit(char const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
literal_string<std::basic_string<Char>, char_encoding::standard, unused_type>
|
||||
lit(std::basic_string<Char> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
namespace standard_wide
|
||||
{
|
||||
constexpr literal_string<wchar_t const*, char_encoding::standard_wide>
|
||||
string(wchar_t const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<wchar_t>, char_encoding::standard_wide>
|
||||
string(std::basic_string<wchar_t> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
constexpr literal_string<wchar_t const*, char_encoding::standard_wide, unused_type>
|
||||
lit(wchar_t const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<wchar_t>, char_encoding::standard_wide, unused_type>
|
||||
lit(std::basic_string<wchar_t> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_SPIRIT_X3_UNICODE)
|
||||
namespace unicode
|
||||
{
|
||||
constexpr literal_string<char32_t const*, char_encoding::unicode>
|
||||
string(char32_t const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<char32_t>, char_encoding::unicode>
|
||||
string(std::basic_string<char32_t> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
constexpr literal_string<char32_t const*, char_encoding::unicode, unused_type>
|
||||
lit(char32_t const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<char32_t>, char_encoding::unicode, unused_type>
|
||||
lit(std::basic_string<char32_t> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace ascii
|
||||
{
|
||||
constexpr literal_string<wchar_t const*, char_encoding::ascii>
|
||||
string(wchar_t const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<wchar_t>, char_encoding::ascii>
|
||||
string(std::basic_string<wchar_t> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
constexpr literal_string<char const*, char_encoding::ascii, unused_type>
|
||||
lit(char const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
literal_string<std::basic_string<Char>, char_encoding::ascii, unused_type>
|
||||
lit(std::basic_string<Char> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
}
|
||||
|
||||
namespace iso8859_1
|
||||
{
|
||||
constexpr literal_string<wchar_t const*, char_encoding::iso8859_1>
|
||||
string(wchar_t const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<wchar_t>, char_encoding::iso8859_1>
|
||||
string(std::basic_string<wchar_t> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
constexpr literal_string<char const*, char_encoding::iso8859_1, unused_type>
|
||||
lit(char const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
literal_string<std::basic_string<Char>, char_encoding::iso8859_1, unused_type>
|
||||
lit(std::basic_string<Char> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
}
|
||||
|
||||
using standard::string;
|
||||
using standard::lit;
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
using standard_wide::string;
|
||||
using standard_wide::lit;
|
||||
#endif
|
||||
|
||||
namespace extension
|
||||
{
|
||||
template <int N>
|
||||
struct as_parser<char[N]>
|
||||
{
|
||||
typedef literal_string<
|
||||
char const*, char_encoding::standard, unused_type>
|
||||
type;
|
||||
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(char const* s)
|
||||
{
|
||||
return type(s);
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
struct as_parser<char const[N]> : as_parser<char[N]> {};
|
||||
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
template <int N>
|
||||
struct as_parser<wchar_t[N]>
|
||||
{
|
||||
typedef literal_string<
|
||||
wchar_t const*, char_encoding::standard_wide, unused_type>
|
||||
type;
|
||||
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(wchar_t const* s)
|
||||
{
|
||||
return type(s);
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
struct as_parser<wchar_t const[N]> : as_parser<wchar_t[N]> {};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct as_parser<char const*>
|
||||
{
|
||||
typedef literal_string<
|
||||
char const*, char_encoding::standard, unused_type>
|
||||
type;
|
||||
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(char const* s)
|
||||
{
|
||||
return type(s);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
struct as_parser< std::basic_string<Char> >
|
||||
{
|
||||
typedef literal_string<
|
||||
Char const*, char_encoding::standard, unused_type>
|
||||
type;
|
||||
|
||||
typedef type value_type;
|
||||
|
||||
static type call(std::basic_string<Char> const& s)
|
||||
{
|
||||
return type(s.c_str());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename String, typename Encoding, typename Attribute>
|
||||
struct get_info<literal_string<String, Encoding, Attribute>>
|
||||
{
|
||||
using result_type = std::string;
|
||||
[[nodiscard]] constexpr std::string operator()(literal_string<String, Encoding, Attribute> const& p) const
|
||||
typedef std::string result_type;
|
||||
std::string operator()(literal_string<String, Encoding, Attribute> const& p) const
|
||||
{
|
||||
return '"' + x3::to_utf8(p.str) + '"';
|
||||
return '"' + to_utf8(p.str) + '"';
|
||||
}
|
||||
};
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,298 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_STRING_STRING_HPP
|
||||
#define BOOST_SPIRIT_X3_STRING_STRING_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/string/literal_string.hpp>
|
||||
#include <boost/spirit/home/x3/char/literal_char.hpp> // required for "c" -> 'c' optimization
|
||||
#include <boost/spirit/home/x3/support/traits/string_traits.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/char_encoding/detail/encoding_warning.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/standard_wide.hpp>
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
# include <boost/spirit/home/x3/char_encoding/unicode.hpp>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
namespace standard
|
||||
{
|
||||
inline namespace helpers
|
||||
{
|
||||
template <traits::CppStringLike<char> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::standard>
|
||||
string(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::standard>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
// Optimize `literal_string{'c'}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard, std::basic_string<char>>
|
||||
string(char ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
// Optimize `literal_string{"c"}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard, std::basic_string<char>>
|
||||
string(traits::X3VagueArrayOf2Chars<char> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
|
||||
template <traits::CppStringLike<char> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::standard, unused_type>
|
||||
lit(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::standard, unused_type>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
} // helpers
|
||||
|
||||
template <typename T>
|
||||
requires traits::CharIncompatibleWith<T, char> || traits::StringLikeIncompatibleWith<T, char>
|
||||
constexpr void string(T&&) = delete; // Mixing incompatible character types is not allowed
|
||||
} // standard
|
||||
|
||||
using standard::helpers::string;
|
||||
using standard::helpers::lit;
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
namespace standard_wide
|
||||
{
|
||||
inline namespace helpers
|
||||
{
|
||||
template <traits::CppStringLike<wchar_t> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::standard_wide>
|
||||
string(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::standard_wide>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
// Optimize `literal_string{'c'}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard_wide, std::basic_string<wchar_t>>
|
||||
string(wchar_t ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
// Optimize `literal_string{L"c"}` into `literal_char{L'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard_wide, std::basic_string<wchar_t>>
|
||||
string(traits::X3VagueArrayOf2Chars<wchar_t> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
|
||||
template <traits::CppStringLike<wchar_t> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::standard_wide, unused_type>
|
||||
lit(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::standard_wide, unused_type>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
} // helpers
|
||||
|
||||
template <typename T>
|
||||
requires traits::CharIncompatibleWith<T, wchar_t> || traits::StringLikeIncompatibleWith<T, wchar_t>
|
||||
constexpr void string(T&&) = delete; // Mixing incompatible character types is not allowed
|
||||
} // standard_wide
|
||||
|
||||
using standard_wide::helpers::string;
|
||||
using standard_wide::helpers::lit;
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
namespace unicode
|
||||
{
|
||||
inline namespace helpers
|
||||
{
|
||||
// TODO: add `char8_t` and `char16_t` overloads
|
||||
template <traits::CppStringLike<char32_t> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::unicode>
|
||||
string(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::unicode>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
// Optimize `literal_string{'c'}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::unicode, std::basic_string<char32_t>>
|
||||
string(char32_t ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
// Optimize `literal_string{U"c"}` into `literal_char{U'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::unicode, std::basic_string<char32_t>>
|
||||
string(traits::X3VagueArrayOf2Chars<char32_t> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
|
||||
template <traits::CppStringLike<char32_t> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::unicode, unused_type>
|
||||
lit(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::unicode, unused_type>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
} // helpers
|
||||
|
||||
template <typename T>
|
||||
requires traits::CharIncompatibleWith<T, char32_t> || traits::StringLikeIncompatibleWith<T, char32_t>
|
||||
constexpr void string(T&&) = delete; // Mixing incompatible character types is not allowed
|
||||
}
|
||||
|
||||
using unicode::helpers::string;
|
||||
using unicode::helpers::lit;
|
||||
#endif
|
||||
|
||||
namespace [[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]] ascii
|
||||
{
|
||||
template <traits::CppStringLike<char> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::ascii>
|
||||
string(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::ascii>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
// Optimize `literal_string{'c'}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::ascii, std::basic_string<char>>
|
||||
string(char ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
// Optimize `literal_string{"c"}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::ascii, std::basic_string<char>>
|
||||
string(traits::X3VagueArrayOf2Chars<char> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
|
||||
template <traits::CppStringLike<char> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::ascii, unused_type>
|
||||
lit(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::ascii, unused_type>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires traits::CharIncompatibleWith<T, char> || traits::StringLikeIncompatibleWith<T, char>
|
||||
constexpr void string(T&&) = delete; // Mixing incompatible character types is not allowed
|
||||
} // ascii
|
||||
|
||||
namespace [[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]] iso8859_1
|
||||
{
|
||||
template <traits::CppStringLike<char> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::iso8859_1>
|
||||
string(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::iso8859_1>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
// Optimize `literal_string{'c'}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::iso8859_1, std::basic_string<char>>
|
||||
string(char ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
// Optimize `literal_string{"c"}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::iso8859_1, std::basic_string<char>>
|
||||
string(traits::X3VagueArrayOf2Chars<char> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
|
||||
template <traits::CppStringLike<char> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::iso8859_1, unused_type>
|
||||
lit(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::iso8859_1, unused_type>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires traits::CharIncompatibleWith<T, char> || traits::StringLikeIncompatibleWith<T, char>
|
||||
constexpr void string(T&&) = delete; // Mixing incompatible character types is not allowed
|
||||
} // iso8859_1
|
||||
|
||||
namespace extension
|
||||
{
|
||||
template <traits::CharLike CharT, std::size_t N>
|
||||
struct as_parser<CharT[N]>
|
||||
{
|
||||
using type = literal_string<std::basic_string_view<CharT>, traits::char_encoding_for<CharT>, unused_type>;
|
||||
using value_type = type;
|
||||
|
||||
[[nodiscard]] static constexpr type call(CharT const* s)
|
||||
{
|
||||
return type(s);
|
||||
}
|
||||
};
|
||||
|
||||
template <traits::CharLike CharT, std::size_t N>
|
||||
struct as_parser<CharT const[N]> : as_parser<CharT[N]> {};
|
||||
|
||||
template <traits::CharLike CharT>
|
||||
struct as_parser<CharT const*>
|
||||
{
|
||||
using type = literal_string<std::basic_string_view<CharT>, traits::char_encoding_for<CharT>, unused_type>;
|
||||
using value_type = type;
|
||||
|
||||
[[nodiscard]] static constexpr type call(CharT const* s)
|
||||
{
|
||||
return type(std::basic_string_view<CharT>{s});
|
||||
}
|
||||
};
|
||||
|
||||
template <traits::CharLike CharT>
|
||||
struct as_parser<std::basic_string<CharT>>
|
||||
{
|
||||
using type = literal_string<std::basic_string<CharT>, traits::char_encoding_for<CharT>, unused_type>;
|
||||
using value_type = type;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] static constexpr type call(T&& str)
|
||||
noexcept(std::is_nothrow_constructible_v<type, T>)
|
||||
{
|
||||
return type(std::forward<T>(str));
|
||||
}
|
||||
};
|
||||
|
||||
template <traits::CharLike CharT>
|
||||
struct as_parser<std::basic_string_view<CharT>>
|
||||
{
|
||||
using type = literal_string<std::basic_string_view<CharT>, traits::char_encoding_for<CharT>, unused_type>;
|
||||
using value_type = type;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] static constexpr type call(T&& str)
|
||||
noexcept(std::is_nothrow_constructible_v<type, T>)
|
||||
{
|
||||
return type(std::forward<T>(str));
|
||||
}
|
||||
};
|
||||
} // extension
|
||||
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013 Carl Barron
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -17,161 +16,99 @@
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
#include <boost/spirit/home/x3/support/no_case.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/char_encoding/detail/encoding_warning.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/iso8859_1.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/standard_wide.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/iso8859_1.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard_wide.hpp>
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
# include <boost/spirit/home/x3/char_encoding/unicode.hpp>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <ranges>
|
||||
#include <iterator>
|
||||
#include <initializer_list>
|
||||
#include <iterator> // std::begin
|
||||
#include <memory> // std::shared_ptr
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
|
||||
#endif
|
||||
|
||||
#define BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING(old_api) \
|
||||
"Use `shared_" old_api "` instead. `" old_api "` has had a " \
|
||||
"*implicit* trait where the underlying storage is shared via " \
|
||||
"`std::shared_ptr`. This disallows `constexpr` usage in generic " \
|
||||
"scenarios where the sharing is not actually needed at all. Even " \
|
||||
"for non-`constexpr` usage, the old name `" old_api "` does not " \
|
||||
"represent this trait, so the usage of the old API is strongly " \
|
||||
"discouraged."
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename Derived, bool IsShared, typename Encoding, typename T, typename Lookup>
|
||||
struct symbols_parser_impl : parser<Derived>
|
||||
template <
|
||||
typename Encoding
|
||||
, typename T = unused_type
|
||||
, typename Lookup = tst<typename Encoding::char_type, T> >
|
||||
struct symbols_parser : parser<symbols_parser<Encoding, T, Lookup>>
|
||||
{
|
||||
using char_type = typename Encoding::char_type; // the character type
|
||||
using encoding = Encoding;
|
||||
using value_type = T; // the value associated with each entry
|
||||
using attribute_type = value_type;
|
||||
typedef typename Encoding::char_type char_type; // the character type
|
||||
typedef Encoding encoding;
|
||||
typedef T value_type; // the value associated with each entry
|
||||
typedef value_type attribute_type;
|
||||
|
||||
static constexpr bool has_attribute = !std::is_same_v<unused_type, attribute_type>;
|
||||
static constexpr bool handles_container = traits::is_container_v<attribute_type>;
|
||||
static bool const has_attribute =
|
||||
!std::is_same<unused_type, attribute_type>::value;
|
||||
static bool const handles_container =
|
||||
traits::is_container<attribute_type>::value;
|
||||
|
||||
constexpr symbols_parser_impl(std::string_view name = "symbols")
|
||||
requires(IsShared)
|
||||
: add{*this}
|
||||
, remove{*this}
|
||||
, lookup(std::make_shared<Lookup>())
|
||||
, name_(name)
|
||||
symbols_parser(std::string const& name = "symbols")
|
||||
: add{*this}
|
||||
, remove{*this}
|
||||
, lookup(std::make_shared<Lookup>())
|
||||
, name_(name)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr symbols_parser_impl(std::string_view name = "symbols")
|
||||
requires(!IsShared)
|
||||
: add{*this}
|
||||
, remove{*this}
|
||||
, lookup(std::make_unique<Lookup>())
|
||||
, name_(name)
|
||||
symbols_parser(symbols_parser const& syms)
|
||||
: add{*this}
|
||||
, remove{*this}
|
||||
, lookup(syms.lookup)
|
||||
, name_(syms.name_)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr symbols_parser_impl(symbols_parser_impl const& syms)
|
||||
requires(IsShared)
|
||||
: add{*this}
|
||||
, remove{*this}
|
||||
, lookup(syms.lookup)
|
||||
, name_(syms.name_)
|
||||
template <typename Symbols>
|
||||
symbols_parser(Symbols const& syms, std::string const& name = "symbols")
|
||||
: symbols_parser(name)
|
||||
{
|
||||
for (auto& sym : syms)
|
||||
add(sym);
|
||||
}
|
||||
|
||||
constexpr symbols_parser_impl(symbols_parser_impl const& syms)
|
||||
requires(!IsShared)
|
||||
: add{*this}
|
||||
, remove{*this}
|
||||
, lookup(std::make_unique<Lookup>(*syms.lookup))
|
||||
, name_(syms.name_)
|
||||
template <typename Symbols, typename Data>
|
||||
symbols_parser(Symbols const& syms, Data const& data
|
||||
, std::string const& name = "symbols")
|
||||
: symbols_parser(name)
|
||||
{
|
||||
using std::begin;
|
||||
auto di = begin(data);
|
||||
for (auto& sym : syms)
|
||||
add(sym, *di++);
|
||||
}
|
||||
|
||||
constexpr symbols_parser_impl(symbols_parser_impl&&) noexcept = default;
|
||||
|
||||
template <std::ranges::forward_range Symbols>
|
||||
requires std::convertible_to<std::ranges::range_value_t<Symbols>, std::basic_string_view<char_type>>
|
||||
constexpr symbols_parser_impl(Symbols const& syms, std::string const& name = "symbols")
|
||||
: symbols_parser_impl(name)
|
||||
symbols_parser(std::initializer_list<std::pair<char_type const*, T>> syms
|
||||
, std::string const & name="symbols")
|
||||
: symbols_parser(name)
|
||||
{
|
||||
for (auto const& sym : syms)
|
||||
{
|
||||
this->add(sym);
|
||||
}
|
||||
}
|
||||
|
||||
template <std::ranges::forward_range Symbols, std::ranges::forward_range Data>
|
||||
requires
|
||||
std::convertible_to<std::ranges::range_value_t<Symbols>, std::basic_string_view<char_type>> &&
|
||||
std::convertible_to<std::ranges::range_value_t<Data>, T>
|
||||
constexpr symbols_parser_impl(
|
||||
Symbols const& syms, Data const& data, std::string const& name = "symbols"
|
||||
)
|
||||
: symbols_parser_impl(name)
|
||||
{
|
||||
auto di = std::ranges::begin(data);
|
||||
for (auto const& sym : syms)
|
||||
{
|
||||
this->add(sym, *di++);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr symbols_parser_impl(
|
||||
std::initializer_list<std::pair<char_type const*, T>> syms,
|
||||
std::string const & name="symbols"
|
||||
)
|
||||
: symbols_parser_impl(name)
|
||||
{
|
||||
for (auto const& sym : syms)
|
||||
{
|
||||
for (auto& sym : syms)
|
||||
add(sym.first, sym.second);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr symbols_parser_impl(
|
||||
std::initializer_list<char_type const*> syms,
|
||||
std::string const &name="symbols"
|
||||
)
|
||||
: symbols_parser_impl(name)
|
||||
symbols_parser(std::initializer_list<char_type const*> syms
|
||||
, std::string const &name="symbols")
|
||||
: symbols_parser(name)
|
||||
{
|
||||
for (auto const& str : syms)
|
||||
{
|
||||
for (auto str : syms)
|
||||
add(str);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr symbols_parser_impl& operator=(symbols_parser_impl const& rhs)
|
||||
symbols_parser&
|
||||
operator=(symbols_parser const& rhs)
|
||||
{
|
||||
name_ = rhs.name_;
|
||||
if constexpr (IsShared)
|
||||
{
|
||||
lookup = rhs.lookup;
|
||||
}
|
||||
else
|
||||
{
|
||||
*lookup = *rhs.lookup;
|
||||
}
|
||||
lookup = rhs.lookup;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr symbols_parser_impl& operator=(symbols_parser_impl&&) = default;
|
||||
|
||||
constexpr void clear() noexcept
|
||||
void clear()
|
||||
{
|
||||
lookup->clear();
|
||||
}
|
||||
@@ -179,87 +116,93 @@ namespace detail
|
||||
struct adder;
|
||||
struct remover;
|
||||
|
||||
constexpr symbols_parser_impl& operator=(std::initializer_list<char_type const*> const& syms)
|
||||
template <typename Str>
|
||||
adder const&
|
||||
operator=(Str const& str)
|
||||
{
|
||||
lookup->clear();
|
||||
|
||||
for (auto const& sym : syms)
|
||||
{
|
||||
this->add(sym);
|
||||
}
|
||||
|
||||
return *this;
|
||||
return add(str);
|
||||
}
|
||||
|
||||
constexpr adder const&
|
||||
operator=(std::basic_string_view<char_type> const s)
|
||||
template <typename Str>
|
||||
friend adder const&
|
||||
operator+=(symbols_parser& sym, Str const& str)
|
||||
{
|
||||
lookup->clear();
|
||||
return this->add(s);
|
||||
return sym.add(str);
|
||||
}
|
||||
|
||||
friend constexpr adder const&
|
||||
operator+=(symbols_parser_impl& sym, std::basic_string_view<char_type> const s)
|
||||
template <typename Str>
|
||||
friend remover const&
|
||||
operator-=(symbols_parser& sym, Str const& str)
|
||||
{
|
||||
return sym.add(s);
|
||||
}
|
||||
|
||||
friend constexpr remover const&
|
||||
operator-=(symbols_parser_impl& sym, std::basic_string_view<char_type> const s)
|
||||
{
|
||||
return sym.remove(s);
|
||||
return sym.remove(str);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
constexpr void for_each(F&& f) const
|
||||
void for_each(F f) const
|
||||
{
|
||||
lookup->for_each(std::forward<F>(f));
|
||||
lookup->for_each(f);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
constexpr void for_each(F&& f)
|
||||
template <typename Str>
|
||||
value_type& at(Str const& str)
|
||||
{
|
||||
lookup->for_each(std::forward<F>(f));
|
||||
return *lookup->add(traits::get_string_begin<char_type>(str)
|
||||
, traits::get_string_end<char_type>(str), T());
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr value_type& at(std::basic_string_view<char_type> const s)
|
||||
{
|
||||
return *lookup->add(s.begin(), s.end(), T{});
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator>
|
||||
[[nodiscard]] constexpr value_type* prefix_find(Iterator& first, Iterator const& last) noexcept
|
||||
template <typename Iterator>
|
||||
value_type* prefix_find(Iterator& first, Iterator const& last)
|
||||
{
|
||||
return lookup->find(first, last, case_compare<Encoding>());
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator>
|
||||
[[nodiscard]] constexpr value_type const* prefix_find(Iterator& first, Iterator const& last) const noexcept
|
||||
template <typename Iterator>
|
||||
value_type const* prefix_find(Iterator& first, Iterator const& last) const
|
||||
{
|
||||
return lookup->find(first, last, case_compare<Encoding>());
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr value_type* find(std::basic_string_view<char_type> const s) noexcept
|
||||
template <typename Str>
|
||||
value_type* find(Str const& str)
|
||||
{
|
||||
return this->find_impl(s.begin(), s.end());
|
||||
return find_impl(traits::get_string_begin<char_type>(str)
|
||||
, traits::get_string_end<char_type>(str));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr value_type const* find(std::basic_string_view<char_type> const s) const noexcept
|
||||
template <typename Str>
|
||||
value_type const* find(Str const& str) const
|
||||
{
|
||||
return this->find_impl(s.begin(), s.end());
|
||||
return find_impl(traits::get_string_begin<char_type>(str)
|
||||
, traits::get_string_end<char_type>(str));
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator, typename Context, typename Attribute>
|
||||
[[nodiscard]] constexpr bool parse(
|
||||
Iterator& first, Iterator const& last, Context const& context, unused_type, Attribute& attr
|
||||
) const noexcept(
|
||||
noexcept(x3::skip_over(first, last, context)) &&
|
||||
noexcept(x3::traits::move_to(std::declval<value_type const&>(), attr))
|
||||
)
|
||||
private:
|
||||
|
||||
template <typename Iterator>
|
||||
value_type* find_impl(Iterator begin, Iterator end)
|
||||
{
|
||||
value_type* r = lookup->find(begin, end, case_compare<Encoding>());
|
||||
return begin == end ? r : 0;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
value_type const* find_impl(Iterator begin, Iterator end) const
|
||||
{
|
||||
value_type const* r = lookup->find(begin, end, case_compare<Encoding>());
|
||||
return begin == end ? r : 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
template <typename Iterator, typename Context, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, unused_type, Attribute& attr) const
|
||||
{
|
||||
x3::skip_over(first, last, context);
|
||||
|
||||
if (value_type const* val_ptr = lookup->find(first, last, x3::get_case_compare<Encoding>(context)))
|
||||
if (value_type const* val_ptr
|
||||
= lookup->find(first, last, get_case_compare<Encoding>(context)))
|
||||
{
|
||||
x3::traits::move_to(*val_ptr, attr);
|
||||
return true;
|
||||
@@ -267,214 +210,124 @@ namespace detail
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr void name(std::string const &str)
|
||||
void name(std::string const &str)
|
||||
{
|
||||
name_ = str;
|
||||
}
|
||||
[[nodiscard]] constexpr std::string const& name() const noexcept
|
||||
std::string const &name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
struct [[maybe_unused]] adder
|
||||
struct adder
|
||||
{
|
||||
template <std::forward_iterator Iterator>
|
||||
[[maybe_unused]] constexpr adder const&
|
||||
template <typename Iterator>
|
||||
adder const&
|
||||
operator()(Iterator first, Iterator last, T const& val) const
|
||||
{
|
||||
sym.lookup->add(first, last, val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[maybe_unused]] constexpr adder const&
|
||||
operator()(std::basic_string_view<char_type> const s, T const& val = T{}) const
|
||||
template <typename Str>
|
||||
adder const&
|
||||
operator()(Str const& s, T const& val = T()) const
|
||||
{
|
||||
sym.lookup->add(s.begin(), s.end(), val);
|
||||
sym.lookup->add(traits::get_string_begin<char_type>(s)
|
||||
, traits::get_string_end<char_type>(s), val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[maybe_unused, deprecated("Don't rely on overloaded comma operator. It's the leftover from the black magic in the 2000s.")]]
|
||||
constexpr adder const&
|
||||
operator,(std::basic_string_view<char_type> const s) const
|
||||
template <typename Str>
|
||||
adder const&
|
||||
operator,(Str const& s) const
|
||||
{
|
||||
sym.lookup->add(s.begin(), s.end(), T{});
|
||||
sym.lookup->add(traits::get_string_begin<char_type>(s)
|
||||
, traits::get_string_end<char_type>(s), T());
|
||||
return *this;
|
||||
}
|
||||
|
||||
symbols_parser_impl& sym;
|
||||
symbols_parser& sym;
|
||||
};
|
||||
|
||||
struct [[maybe_unused]] remover
|
||||
struct remover
|
||||
{
|
||||
template <std::forward_iterator Iterator>
|
||||
[[maybe_unused]] constexpr remover const&
|
||||
template <typename Iterator>
|
||||
remover const&
|
||||
operator()(Iterator const& first, Iterator const& last) const
|
||||
{
|
||||
sym.lookup->remove(first, last);
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[maybe_unused]] constexpr remover const&
|
||||
operator()(std::basic_string_view<char_type> const s) const
|
||||
template <typename Str>
|
||||
remover const&
|
||||
operator()(Str const& s) const
|
||||
{
|
||||
sym.lookup->remove(s.begin(), s.end());
|
||||
sym.lookup->remove(traits::get_string_begin<char_type>(s)
|
||||
, traits::get_string_end<char_type>(s));
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[maybe_unused, deprecated("Don't rely on overloaded comma operator. It's the leftover from the black magic in the 2000s.")]]
|
||||
constexpr remover const&
|
||||
operator,(std::basic_string_view<char_type> const s) const
|
||||
template <typename Str>
|
||||
remover const&
|
||||
operator,(Str const& s) const
|
||||
{
|
||||
sym.lookup->remove(s.begin(), s.end());
|
||||
sym.lookup->remove(traits::get_string_begin<char_type>(s)
|
||||
, traits::get_string_end<char_type>(s));
|
||||
return *this;
|
||||
}
|
||||
|
||||
symbols_parser_impl& sym;
|
||||
symbols_parser& sym;
|
||||
};
|
||||
|
||||
[[maybe_unused]] adder add;
|
||||
[[maybe_unused]] remover remove;
|
||||
|
||||
private:
|
||||
template <std::forward_iterator Iterator>
|
||||
[[nodiscard]] constexpr value_type* find_impl(Iterator begin, Iterator end) noexcept
|
||||
{
|
||||
value_type* r = lookup->find(begin, end, case_compare<Encoding>());
|
||||
return begin == end ? r : 0;
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator>
|
||||
[[nodiscard]] constexpr value_type const* find_impl(Iterator begin, Iterator end) const noexcept
|
||||
{
|
||||
value_type const* r = lookup->find(begin, end, case_compare<Encoding>());
|
||||
return begin == end ? r : 0;
|
||||
}
|
||||
|
||||
std::conditional_t<IsShared, std::shared_ptr<Lookup>, std::unique_ptr<Lookup>> lookup;
|
||||
adder add;
|
||||
remover remove;
|
||||
std::shared_ptr<Lookup> lookup;
|
||||
std::string name_;
|
||||
};
|
||||
} // detail
|
||||
|
||||
template <typename Encoding, typename T = unused_type, typename Lookup = tst<typename Encoding::char_type, T>>
|
||||
struct shared_symbols_parser
|
||||
: detail::symbols_parser_impl<shared_symbols_parser<Encoding, T, Lookup>, true, Encoding, T, Lookup>
|
||||
{
|
||||
using base_type = detail::symbols_parser_impl<shared_symbols_parser<Encoding, T, Lookup>, true, Encoding, T, Lookup>;
|
||||
using base_type::base_type;
|
||||
using base_type::operator=;
|
||||
};
|
||||
|
||||
template <typename Encoding, typename T = unused_type, typename Lookup = tst<typename Encoding::char_type, T>>
|
||||
struct [[deprecated(BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING("symbols_parser"))]]
|
||||
symbols_parser : shared_symbols_parser<Encoding, T, Lookup>
|
||||
{
|
||||
using base_type = shared_symbols_parser<Encoding, T, Lookup>;
|
||||
using base_type::base_type;
|
||||
using base_type::operator=;
|
||||
};
|
||||
|
||||
template <typename Encoding, typename T = unused_type, typename Lookup = tst<typename Encoding::char_type, T>>
|
||||
struct unique_symbols_parser
|
||||
: detail::symbols_parser_impl<unique_symbols_parser<Encoding, T, Lookup>, false, Encoding, T, Lookup>
|
||||
{
|
||||
using base_type = detail::symbols_parser_impl<unique_symbols_parser<Encoding, T, Lookup>, false, Encoding, T, Lookup>;
|
||||
using base_type::base_type;
|
||||
using base_type::operator=;
|
||||
};
|
||||
|
||||
template <typename Encoding, typename T, typename Lookup>
|
||||
struct get_info<shared_symbols_parser<Encoding, T, Lookup>>
|
||||
struct get_info<symbols_parser<Encoding, T, Lookup>>
|
||||
{
|
||||
using result_type = std::string const&;
|
||||
|
||||
[[nodiscard]] constexpr result_type operator()(shared_symbols_parser<Encoding, T, Lookup> const& symbols) const noexcept
|
||||
{
|
||||
return symbols.name();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Encoding, typename T, typename Lookup>
|
||||
struct get_info<unique_symbols_parser<Encoding, T, Lookup>>
|
||||
{
|
||||
using result_type = std::string const&;
|
||||
|
||||
[[nodiscard]] constexpr result_type operator()(unique_symbols_parser<Encoding, T, Lookup> const& symbols) const noexcept
|
||||
{
|
||||
return symbols.name();
|
||||
}
|
||||
typedef std::string result_type;
|
||||
result_type operator()(symbols_parser< Encoding, T
|
||||
, Lookup
|
||||
> const& symbols) const
|
||||
{
|
||||
return symbols.name();
|
||||
}
|
||||
};
|
||||
|
||||
namespace standard
|
||||
{
|
||||
template <typename T = unused_type>
|
||||
using symbols [[deprecated(BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING("symbols"))]]
|
||||
= x3::shared_symbols_parser<char_encoding::standard, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using shared_symbols = x3::shared_symbols_parser<char_encoding::standard, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using unique_symbols = x3::unique_symbols_parser<char_encoding::standard, T>;
|
||||
} // standard
|
||||
using symbols = symbols_parser<char_encoding::standard, T>;
|
||||
}
|
||||
|
||||
using standard::symbols;
|
||||
using standard::shared_symbols;
|
||||
using standard::unique_symbols;
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
namespace standard_wide
|
||||
{
|
||||
template <typename T = unused_type>
|
||||
using symbols [[deprecated(BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING("symbols"))]]
|
||||
= x3::shared_symbols_parser<char_encoding::standard_wide, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using shared_symbols = x3::shared_symbols_parser<char_encoding::standard_wide, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using unique_symbols = x3::unique_symbols_parser<char_encoding::standard_wide, T>;
|
||||
} // standard_wide
|
||||
using symbols = symbols_parser<char_encoding::standard_wide, T>;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace [[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]] ascii
|
||||
namespace ascii
|
||||
{
|
||||
template <typename T = unused_type>
|
||||
using symbols [[deprecated(BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING("symbols"))]]
|
||||
= x3::shared_symbols_parser<char_encoding::ascii, T>;
|
||||
using symbols = symbols_parser<char_encoding::ascii, T>;
|
||||
}
|
||||
|
||||
template <typename T = unused_type>
|
||||
using shared_symbols = x3::shared_symbols_parser<char_encoding::ascii, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using unique_symbols = x3::unique_symbols_parser<char_encoding::ascii, T>;
|
||||
} // ascii
|
||||
|
||||
namespace [[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]] iso8859_1
|
||||
namespace iso8859_1
|
||||
{
|
||||
template <typename T = unused_type>
|
||||
using symbols [[deprecated(BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING("symbols"))]]
|
||||
= x3::shared_symbols_parser<char_encoding::iso8859_1, T>;
|
||||
using symbols = symbols_parser<char_encoding::iso8859_1, T>;
|
||||
}
|
||||
|
||||
template <typename T = unused_type>
|
||||
using shared_symbols = x3::shared_symbols_parser<char_encoding::iso8859_1, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using unique_symbols = x3::unique_symbols_parser<char_encoding::iso8859_1, T>;
|
||||
} // iso8859_1
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
namespace unicode {
|
||||
template <typename T = unused_type>
|
||||
using shared_symbols = x3::shared_symbols_parser<char_encoding::unicode, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using unique_symbols = x3::unique_symbols_parser<char_encoding::unicode, T>;
|
||||
} // unicode
|
||||
#endif
|
||||
|
||||
} // boost::spirit::x3
|
||||
|
||||
#undef BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING
|
||||
}}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -8,208 +7,129 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_TST_JUNE_03_2007_1031AM)
|
||||
#define BOOST_SPIRIT_X3_TST_JUNE_03_2007_1031AM
|
||||
|
||||
#include <boost/spirit/home/x3/core/config.hpp>
|
||||
#include <boost/spirit/home/x3/string/detail/tst_node.hpp>
|
||||
#include <boost/spirit/home/x3/support/allocator.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/spirit/home/x3/string/detail/tst.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
struct tst_pass_through
|
||||
{
|
||||
template <typename Char>
|
||||
[[nodiscard]] constexpr Char operator()(Char ch) const noexcept
|
||||
Char operator()(Char ch) const
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char, typename T, typename Alloc = std::allocator<T>>
|
||||
template <typename Char, typename T>
|
||||
struct tst
|
||||
{
|
||||
using char_type = Char; // the character type
|
||||
using value_type = T; // the value associated with each entry
|
||||
using allocator_type = Alloc;
|
||||
using node = detail::tst_node<Char, T>;
|
||||
using node_allocator_type = std::allocator_traits<Alloc>::template rebind_alloc<node>;
|
||||
typedef Char char_type; // the character type
|
||||
typedef T value_type; // the value associated with each entry
|
||||
typedef detail::tst_node<Char, T> node;
|
||||
|
||||
constexpr tst() noexcept(std::is_nothrow_default_constructible_v<Alloc>) = default;
|
||||
|
||||
constexpr explicit tst(Alloc const& alloc) noexcept
|
||||
: alloc_(alloc)
|
||||
, node_alloc_(alloc_)
|
||||
{}
|
||||
|
||||
constexpr ~tst() noexcept
|
||||
{
|
||||
detail::allocator_ops<tst>::template destroy_deallocate<&tst::node_alloc_, &tst::root_>(*this);
|
||||
}
|
||||
|
||||
constexpr tst(tst const& other)
|
||||
: alloc_(std::allocator_traits<Alloc>::select_on_container_copy_construction(other.alloc_))
|
||||
, node_alloc_(std::allocator_traits<node_allocator_type>::select_on_container_copy_construction(other.node_alloc_))
|
||||
, root_(detail::allocator_ops<tst>::template copy_construct<&tst::node_alloc_, &tst::root_>(*this, other))
|
||||
tst()
|
||||
: root(0)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr tst(tst&& other) noexcept
|
||||
: alloc_(std::move(other.alloc_))
|
||||
, node_alloc_(std::move(other.node_alloc_))
|
||||
, root_(std::exchange(other.root_, nullptr))
|
||||
~tst()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
constexpr tst& operator=(tst const& other)
|
||||
tst(tst const& rhs)
|
||||
: root(0)
|
||||
{
|
||||
if (this == std::addressof(other)) return *this;
|
||||
detail::allocator_ops<tst>::template copy_assign<&tst::node_alloc_, &tst::root_>(*this, other);
|
||||
detail::allocator_ops<tst>::template copy_assign<&tst::alloc_>(*this, other);
|
||||
return *this;
|
||||
copy(rhs);
|
||||
}
|
||||
|
||||
constexpr tst& operator=(tst&& other)
|
||||
noexcept(detail::allocator_ops<tst>::template move_assign_noexcept<allocator_type, node_allocator_type>)
|
||||
tst& operator=(tst const& rhs)
|
||||
{
|
||||
if (this == std::addressof(other)) return *this;
|
||||
detail::allocator_ops<tst>::template move_assign<&tst::node_alloc_, &tst::root_>(*this, std::move(other));
|
||||
detail::allocator_ops<tst>::template move_assign<&tst::alloc_>(*this, std::move(other));
|
||||
return *this;
|
||||
return assign(rhs);
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator, typename CaseCompare>
|
||||
[[nodiscard]] constexpr T* find(Iterator& first, Iterator last, CaseCompare caseCompare) const noexcept
|
||||
template <typename Iterator, typename CaseCompare>
|
||||
T* find(Iterator& first, Iterator last, CaseCompare caseCompare) const
|
||||
{
|
||||
return node::find(root_, first, last, caseCompare);
|
||||
return node::find(root, first, last, caseCompare);
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator, typename Val>
|
||||
constexpr T* add(Iterator first, Iterator last, Val&& val)
|
||||
/*template <typename Iterator>
|
||||
T* find(Iterator& first, Iterator last) const
|
||||
{
|
||||
if (first == last) return nullptr;
|
||||
if (!root_)
|
||||
{
|
||||
root_ = std::allocator_traits<node_allocator_type>::allocate(node_alloc_, 1);
|
||||
std::allocator_traits<node_allocator_type>::construct(node_alloc_, root_, *first, alloc_);
|
||||
}
|
||||
return find(first, last, case_compare<tst_pass_through());
|
||||
}*/
|
||||
|
||||
return this->add(root_, first, last, std::forward<Val>(val));
|
||||
template <typename Iterator>
|
||||
T* add(
|
||||
Iterator first
|
||||
, Iterator last
|
||||
, typename boost::call_traits<T>::param_type val)
|
||||
{
|
||||
return node::add(root, first, last, val, this);
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator>
|
||||
constexpr void remove(Iterator first, Iterator last) noexcept
|
||||
template <typename Iterator>
|
||||
void remove(Iterator first, Iterator last)
|
||||
{
|
||||
this->remove(root_, first, last);
|
||||
node::remove(root, first, last, this);
|
||||
}
|
||||
|
||||
constexpr void clear() noexcept
|
||||
void clear()
|
||||
{
|
||||
if (!root_) return;
|
||||
std::allocator_traits<node_allocator_type>::destroy(node_alloc_, root_);
|
||||
std::allocator_traits<node_allocator_type>::deallocate(node_alloc_, root_, 1);
|
||||
root_ = nullptr;
|
||||
node::destruct_node(root, this);
|
||||
root = 0;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
constexpr void for_each(F&& f) const
|
||||
void for_each(F f) const
|
||||
{
|
||||
node::for_each(root_, {}, std::forward<F>(f));
|
||||
node::for_each(root, std::basic_string<Char>(), f);
|
||||
}
|
||||
|
||||
friend struct detail::allocator_ops<tst>;
|
||||
|
||||
private:
|
||||
template <std::forward_iterator Iterator, typename Val>
|
||||
[[nodiscard]] constexpr T*
|
||||
add(node* root, Iterator first, Iterator last, Val&& val)
|
||||
|
||||
friend struct detail::tst_node<Char, T>;
|
||||
|
||||
void copy(tst const& rhs)
|
||||
{
|
||||
BOOST_ASSERT(root != nullptr);
|
||||
BOOST_ASSERT(first != last);
|
||||
|
||||
node** pp = &root;
|
||||
auto c = *first;
|
||||
|
||||
while (true)
|
||||
{
|
||||
node* const p = *pp;
|
||||
|
||||
if (c == p->id)
|
||||
{
|
||||
if (++first == last)
|
||||
{
|
||||
if (!p->data)
|
||||
{
|
||||
p->data = std::allocator_traits<Alloc>::allocate(alloc_, 1);
|
||||
std::allocator_traits<Alloc>::construct(alloc_, p->data, std::forward<Val>(val));
|
||||
}
|
||||
return p->data;
|
||||
}
|
||||
pp = &p->eq;
|
||||
c = *first;
|
||||
}
|
||||
else if (c < p->id)
|
||||
{
|
||||
pp = &p->lt;
|
||||
}
|
||||
else
|
||||
{
|
||||
pp = &p->gt;
|
||||
}
|
||||
|
||||
if (!*pp)
|
||||
{
|
||||
*pp = std::allocator_traits<node_allocator_type>::allocate(node_alloc_, 1);
|
||||
std::allocator_traits<node_allocator_type>::construct(node_alloc_, *pp, c);
|
||||
}
|
||||
}
|
||||
root = node::clone_node(rhs.root, this);
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator>
|
||||
constexpr void
|
||||
remove(node*& p, Iterator first, Iterator last) noexcept
|
||||
tst& assign(tst const& rhs)
|
||||
{
|
||||
if (!p || first == last) return;
|
||||
|
||||
auto c = *first;
|
||||
|
||||
if (c == p->id)
|
||||
if (this != &rhs)
|
||||
{
|
||||
if (++first == last)
|
||||
{
|
||||
if (p->data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc_, p->data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc_, p->data, 1);
|
||||
p->data = nullptr;
|
||||
}
|
||||
}
|
||||
this->remove(p->eq, first, last);
|
||||
}
|
||||
else if (c < p->id)
|
||||
{
|
||||
this->remove(p->lt, first, last);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->remove(p->gt, first, last);
|
||||
}
|
||||
|
||||
if (!p->data && !p->lt && !p->eq && !p->gt)
|
||||
{
|
||||
std::allocator_traits<node_allocator_type>::destroy(node_alloc_, p);
|
||||
std::allocator_traits<node_allocator_type>::deallocate(node_alloc_, p, 1);
|
||||
p = nullptr;
|
||||
clear();
|
||||
copy(rhs);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS Alloc alloc_;
|
||||
BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS node_allocator_type node_alloc_;
|
||||
node* root_ = nullptr;
|
||||
node* root;
|
||||
|
||||
node* new_node(Char id)
|
||||
{
|
||||
return new node(id);
|
||||
}
|
||||
|
||||
T* new_data(typename boost::call_traits<T>::param_type val)
|
||||
{
|
||||
return new T(val);
|
||||
}
|
||||
|
||||
void delete_node(node* p)
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
|
||||
void delete_data(T* p)
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
};
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -8,10 +7,9 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_TST_MAP_JUNE_03_2007_1143AM)
|
||||
#define BOOST_SPIRIT_X3_TST_MAP_JUNE_03_2007_1143AM
|
||||
|
||||
#include <boost/spirit/home/x3/string/tst.hpp>
|
||||
#include <boost/spirit/home/x3/string/detail/tst.hpp>
|
||||
#include <unordered_map>
|
||||
#include <boost/pool/object_pool.hpp>
|
||||
#include <boost/call_traits.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
|
||||
@@ -1,252 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_X3_SUPPORT_ALLOCATOR_HPP)
|
||||
#define BOOST_SPIRIT_X3_SUPPORT_ALLOCATOR_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3::detail {
|
||||
|
||||
template <typename Klass>
|
||||
struct allocator_ops
|
||||
{
|
||||
template <typename... Allocs>
|
||||
static constexpr bool move_assign_noexcept = std::conjunction_v<
|
||||
std::disjunction<
|
||||
typename std::allocator_traits<Allocs>::propagate_on_container_move_assignment,
|
||||
typename std::allocator_traits<Allocs>::is_always_equal
|
||||
>...
|
||||
>;
|
||||
|
||||
template <auto AllocMem, auto Mem>
|
||||
[[nodiscard]] static constexpr auto copy_construct(Klass& self, Klass const& other)
|
||||
-> std::remove_reference_t<decltype(self.*Mem)>
|
||||
{
|
||||
if (!(other.*Mem)) return nullptr;
|
||||
|
||||
using Alloc = std::remove_reference_t<decltype(self.*AllocMem)>;
|
||||
auto& alloc = self.*AllocMem;
|
||||
auto* data = std::allocator_traits<Alloc>::allocate(alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(alloc, data, *(other.*Mem));
|
||||
return data;
|
||||
}
|
||||
|
||||
template <auto AllocMem, auto... Mems>
|
||||
static constexpr void destroy_deallocate(Klass& self) noexcept
|
||||
{
|
||||
static_assert(sizeof...(Mems) > 0);
|
||||
(allocator_ops::destroy_deallocate_impl<AllocMem, Mems>(self), ...);
|
||||
}
|
||||
|
||||
template <auto AllocMem, auto... Mems>
|
||||
static constexpr void copy_assign(Klass& self, Klass const& other)
|
||||
{
|
||||
BOOST_ASSERT(std::addressof(self) != std::addressof(other));
|
||||
|
||||
(allocator_ops::copy_assign_impl<AllocMem, Mems>(self, other), ...);
|
||||
|
||||
using Alloc = std::remove_reference_t<decltype(self.*AllocMem)>;
|
||||
constexpr bool pocca = std::allocator_traits<Alloc>::propagate_on_container_copy_assignment::value;
|
||||
if constexpr (pocca)
|
||||
{
|
||||
self.*AllocMem = other.*AllocMem;
|
||||
}
|
||||
}
|
||||
|
||||
template <auto AllocMem, auto... Mems>
|
||||
static constexpr void move_assign(Klass& self, Klass&& other)
|
||||
noexcept(move_assign_noexcept<decltype(self.*AllocMem)>)
|
||||
{
|
||||
BOOST_ASSERT(std::addressof(self) != std::addressof(other));
|
||||
|
||||
(allocator_ops::move_assign_impl<AllocMem, Mems>(self, std::move(other)), ...);
|
||||
|
||||
using Alloc = std::remove_reference_t<decltype(self.*AllocMem)>;
|
||||
constexpr bool pocca = std::allocator_traits<Alloc>::propagate_on_container_move_assignment::value;
|
||||
if constexpr (pocca)
|
||||
{
|
||||
self.*AllocMem = std::move(other.*AllocMem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
template <auto AllocMem, auto Mem>
|
||||
static constexpr void destroy_deallocate_impl(Klass& self) noexcept
|
||||
{
|
||||
auto& data = self.*Mem;
|
||||
if (!data) return;
|
||||
|
||||
using Alloc = std::remove_reference_t<decltype(self.*AllocMem)>;
|
||||
auto& alloc = self.*AllocMem;
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
}
|
||||
|
||||
template <auto AllocMem, auto Mem>
|
||||
static constexpr void copy_assign_impl(Klass& self, Klass const& other)
|
||||
{
|
||||
using Alloc = std::remove_reference_t<decltype(self.*AllocMem)>;
|
||||
constexpr bool pocca = std::allocator_traits<Alloc>::propagate_on_container_copy_assignment::value;
|
||||
|
||||
auto& data = self.*Mem;
|
||||
auto& alloc = self.*AllocMem;
|
||||
|
||||
auto const& other_data = other.*Mem;
|
||||
auto const& other_alloc = other.*AllocMem;
|
||||
|
||||
if (other_data)
|
||||
{
|
||||
if constexpr (std::allocator_traits<Alloc>::is_always_equal::value)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
*data = *other_data;
|
||||
return;
|
||||
}
|
||||
if constexpr (pocca)
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(other_alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(other_alloc, data, *other_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(alloc, data, *other_data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (alloc == other_alloc)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
*data = *other_data;
|
||||
return;
|
||||
}
|
||||
if constexpr (pocca)
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(other_alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(other_alloc, data, *other_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(alloc, data, *other_data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
data = nullptr;
|
||||
}
|
||||
if constexpr (pocca)
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(other_alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(other_alloc, data, *other_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(alloc, data, *other_data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else // !other_data
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
data = nullptr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
template <auto AllocMem, auto Mem>
|
||||
static constexpr void move_assign_impl(Klass& self, Klass&& other)
|
||||
noexcept(move_assign_noexcept<std::remove_reference_t<decltype(self.*AllocMem)>>)
|
||||
{
|
||||
using Alloc = std::remove_reference_t<decltype(self.*AllocMem)>;
|
||||
constexpr bool pocma = std::allocator_traits<Alloc>::propagate_on_container_move_assignment::value;
|
||||
|
||||
auto& data = self.*Mem;
|
||||
auto& alloc = self.*AllocMem;
|
||||
|
||||
auto& other_data = other.*Mem;
|
||||
auto& other_alloc = other.*AllocMem;
|
||||
|
||||
if (other_data)
|
||||
{
|
||||
if constexpr (std::allocator_traits<Alloc>::is_always_equal::value)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
}
|
||||
data = std::exchange(other_data, nullptr);
|
||||
return;
|
||||
}
|
||||
else if (alloc == other_alloc)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
}
|
||||
data = std::exchange(other_data, nullptr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
}
|
||||
if constexpr (pocma)
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(other_alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(other_alloc, data, std::move(*other_data));
|
||||
}
|
||||
else
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(alloc, data, std::move(*other_data));
|
||||
}
|
||||
|
||||
std::allocator_traits<Alloc>::destroy(other_alloc, other_data);
|
||||
std::allocator_traits<Alloc>::deallocate(other_alloc, other_data, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else // !other_data
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
data = nullptr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::detail
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -12,9 +11,7 @@
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/char/char_class_tags.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
struct no_case_tag {};
|
||||
|
||||
@@ -22,20 +19,19 @@ namespace boost::spirit::x3
|
||||
struct case_compare
|
||||
{
|
||||
template <typename Char, typename CharSet>
|
||||
[[nodiscard]] constexpr bool in_set(Char ch, CharSet const& set) noexcept
|
||||
bool in_set(Char ch, CharSet const& set)
|
||||
{
|
||||
static_assert(noexcept(set.test(ch)));
|
||||
return set.test(ch);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
[[nodiscard]] constexpr std::int32_t operator()(Char lc, Char rc) const noexcept
|
||||
int32_t operator()(Char lc, Char rc) const
|
||||
{
|
||||
return lc - rc;
|
||||
}
|
||||
|
||||
template <typename CharClassTag>
|
||||
[[nodiscard]] constexpr CharClassTag get_char_class_tag(CharClassTag tag) const noexcept
|
||||
CharClassTag get_char_class_tag(CharClassTag tag) const
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
@@ -45,18 +41,17 @@ namespace boost::spirit::x3
|
||||
struct no_case_compare
|
||||
{
|
||||
template <typename Char, typename CharSet>
|
||||
[[nodiscard]] bool in_set(Char ch_, CharSet const& set) noexcept // TODO: constexpr
|
||||
bool in_set(Char ch_, CharSet const& set)
|
||||
{
|
||||
using char_type = typename Encoding::classify_type;
|
||||
auto ch = char_type(ch_);
|
||||
static_assert(noexcept(set.test(ch)));
|
||||
return set.test(ch)
|
||||
|| set.test(Encoding::islower(ch)
|
||||
? Encoding::toupper(ch) : Encoding::tolower(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
[[nodiscard]] std::int32_t operator()(Char lc_, Char const rc_) const noexcept // TODO: constexpr
|
||||
int32_t operator()(Char lc_, Char const rc_) const
|
||||
{
|
||||
using char_type = typename Encoding::classify_type;
|
||||
auto lc = char_type(lc_);
|
||||
@@ -66,45 +61,43 @@ namespace boost::spirit::x3
|
||||
}
|
||||
|
||||
template <typename CharClassTag>
|
||||
[[nodiscard]] constexpr CharClassTag get_char_class_tag(CharClassTag tag) const noexcept
|
||||
CharClassTag get_char_class_tag(CharClassTag tag) const
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr alpha_tag get_char_class_tag(lower_tag) const noexcept
|
||||
alpha_tag get_char_class_tag(lower_tag ) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr alpha_tag get_char_class_tag(upper_tag) const noexcept
|
||||
alpha_tag get_char_class_tag(upper_tag ) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
namespace detail
|
||||
template <typename Encoding>
|
||||
case_compare<Encoding> get_case_compare_impl(unused_type const&)
|
||||
{
|
||||
template <typename Encoding>
|
||||
[[nodiscard]] constexpr case_compare<Encoding> get_case_compare_impl(unused_type const&) noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename Encoding>
|
||||
[[nodiscard]] constexpr no_case_compare<Encoding> get_case_compare_impl(no_case_tag const&) noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
} // detail
|
||||
|
||||
template <typename Encoding, typename Context>
|
||||
[[nodiscard]] constexpr decltype(auto) get_case_compare(Context const& context) noexcept
|
||||
{
|
||||
return detail::get_case_compare_impl<Encoding>(x3::get<no_case_tag>(context));
|
||||
return {};
|
||||
}
|
||||
|
||||
auto const no_case_compare_ = no_case_tag{}; // TODO: this should be private
|
||||
template <typename Encoding>
|
||||
no_case_compare<Encoding> get_case_compare_impl(no_case_tag const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
} // boost::spirit::x3
|
||||
template <typename Encoding, typename Context>
|
||||
inline decltype(auto) get_case_compare(Context const& context)
|
||||
{
|
||||
return get_case_compare_impl<Encoding>(x3::get<no_case_tag>(context));
|
||||
}
|
||||
|
||||
auto const no_case_compare_ = no_case_tag{};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
Copyright (c) 2011 Jan Frederick Eick
|
||||
Copyright (c) 2011 Christopher Jefferson
|
||||
Copyright (c) 2006 Stephen Nutt
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -16,7 +15,7 @@
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_type.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/numeric_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/char_encoding_traits.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/ascii.hpp>
|
||||
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
#include <boost/preprocessor/iteration/local.hpp>
|
||||
@@ -123,7 +122,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
return (Radix <= 10 || (ch >= '0' && ch <= '9'))
|
||||
? ch - '0'
|
||||
: traits::char_encoding_traits<Char>::encoding_type::tolower(ch) - 'a' + 10;
|
||||
: char_encoding::ascii::tolower(ch) - 'a' + 10;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -343,7 +342,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
|
||||
if (count + leading_zeros >= MinDigits)
|
||||
{
|
||||
traits::move_to(std::move(val), attr);
|
||||
traits::move_to(val, attr);
|
||||
first = it;
|
||||
return true;
|
||||
}
|
||||
@@ -445,7 +444,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
if (count == 0) // must have at least one digit
|
||||
return false;
|
||||
traits::move_to(std::move(val), attr);
|
||||
traits::move_to(val, attr);
|
||||
first = it;
|
||||
return true;
|
||||
}
|
||||
@@ -459,7 +458,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
, SPIRIT_NUMERIC_INNER_LOOP, _)
|
||||
}
|
||||
|
||||
traits::move_to(std::move(val), attr);
|
||||
traits::move_to(val, attr);
|
||||
first = it;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2011 Jan Frederick Eick
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -78,7 +77,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
T attr;
|
||||
if (call(first, last, attr))
|
||||
{
|
||||
traits::move_to(std::move(attr), attr_);
|
||||
traits::move_to(attr, attr_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -132,7 +131,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
T attr;
|
||||
if (call(first, last, attr))
|
||||
{
|
||||
traits::move_to(std::move(attr), attr_);
|
||||
traits::move_to(attr, attr_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
78
include/boost/spirit/home/x3/support/subcontext.hpp
Normal file
78
include/boost/spirit/home/x3/support/subcontext.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013 Agustin Berge
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_X3_SUBCONTEXT_APR_15_2013_0840AM)
|
||||
#define BOOST_SPIRIT_X3_SUBCONTEXT_APR_15_2013_0840AM
|
||||
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename... T>
|
||||
struct subcontext;
|
||||
|
||||
template <>
|
||||
struct subcontext<>
|
||||
{
|
||||
template <typename Context>
|
||||
subcontext(Context const& /*context*/)
|
||||
{}
|
||||
|
||||
template <typename ID_>
|
||||
unused_type
|
||||
get(ID_) const
|
||||
{
|
||||
return unused;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct subcontext<T>
|
||||
: context<typename T::first_type, typename T::second_type>
|
||||
{
|
||||
typedef context<
|
||||
typename T::first_type, typename T::second_type
|
||||
> context_type;
|
||||
|
||||
template <typename Context>
|
||||
subcontext(Context const& context)
|
||||
: context_type(x3::get<typename T::first_type>(context))
|
||||
{}
|
||||
|
||||
using context_type::get;
|
||||
};
|
||||
|
||||
template <typename T, typename... Tail>
|
||||
struct subcontext<T, Tail...>
|
||||
: subcontext<Tail...>
|
||||
, context<
|
||||
typename T::first_type, typename T::second_type
|
||||
, subcontext<Tail...>
|
||||
>
|
||||
{
|
||||
typedef subcontext<Tail...> base_type;
|
||||
typedef context<
|
||||
typename T::first_type, typename T::second_type
|
||||
, base_type
|
||||
> context_type;
|
||||
|
||||
template <typename Context>
|
||||
subcontext(Context const& context)
|
||||
: base_type(context)
|
||||
, context_type(
|
||||
x3::get<typename T::first_type>(context)
|
||||
, *static_cast<base_type*>(this))
|
||||
{}
|
||||
|
||||
using context_type::get;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -8,22 +8,22 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_ATTRIBUTE_CATEGORY_JAN_4_2012_1150AM)
|
||||
#define BOOST_SPIRIT_X3_ATTRIBUTE_CATEGORY_JAN_4_2012_1150AM
|
||||
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/logical.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/support/category_of.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/is_variant.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/is_range.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/container_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/optional_traits.hpp>
|
||||
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/support/category_of.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
struct unused_type;
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
struct unused_attribute {};
|
||||
struct plain_attribute {};
|
||||
@@ -36,89 +36,60 @@ namespace boost::spirit::x3::traits
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct attribute_category
|
||||
{
|
||||
using type = plain_attribute;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct attribute_category<T const> : attribute_category<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct attribute_category<T&> : attribute_category<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct attribute_category<T const&> : attribute_category<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct attribute_category<T&&> : attribute_category<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct attribute_category<T const&&> : attribute_category<T> {};
|
||||
|
||||
template <typename T>
|
||||
using attribute_category_t = typename attribute_category<T>::type;
|
||||
: mpl::identity<plain_attribute> {};
|
||||
|
||||
template <>
|
||||
struct attribute_category<unused_type>
|
||||
{
|
||||
using type = unused_attribute;
|
||||
};
|
||||
: mpl::identity<unused_attribute> {};
|
||||
|
||||
template <typename T, typename AttributeCategoryTag>
|
||||
concept CategorizedAttr = std::is_same_v<typename attribute_category<T>::type, AttributeCategoryTag>;
|
||||
template <>
|
||||
struct attribute_category<unused_type const>
|
||||
: mpl::identity<unused_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
concept NonUnusedAttr = !CategorizedAttr<T, unused_attribute>;
|
||||
struct attribute_category< T
|
||||
, typename enable_if<
|
||||
typename mpl::eval_if<
|
||||
fusion::traits::is_sequence<T>
|
||||
, fusion::traits::is_associative<T>
|
||||
, mpl::false_
|
||||
>::type >::type >
|
||||
: mpl::identity<associative_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
requires
|
||||
fusion::traits::is_sequence<T>::value &&
|
||||
fusion::traits::is_associative<T>::value
|
||||
struct attribute_category<T>
|
||||
{
|
||||
using type = associative_attribute;
|
||||
};
|
||||
struct attribute_category< T
|
||||
, typename enable_if<
|
||||
mpl::and_<
|
||||
fusion::traits::is_sequence<T>
|
||||
, mpl::not_<fusion::traits::is_associative<T> >
|
||||
> >::type >
|
||||
: mpl::identity<tuple_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
requires
|
||||
fusion::traits::is_sequence<T>::value &&
|
||||
(!fusion::traits::is_associative<T>::value)
|
||||
struct attribute_category<T>
|
||||
{
|
||||
using type = tuple_attribute;
|
||||
};
|
||||
struct attribute_category<T,
|
||||
typename enable_if<traits::is_variant<T>>::type>
|
||||
: mpl::identity<variant_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
requires is_variant_v<T>
|
||||
struct attribute_category<T>
|
||||
{
|
||||
using type = variant_attribute;
|
||||
};
|
||||
struct attribute_category<T,
|
||||
typename enable_if<traits::is_optional<T>>::type>
|
||||
: mpl::identity<optional_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
requires is_optional_v<T>
|
||||
struct attribute_category<T>
|
||||
{
|
||||
using type = optional_attribute;
|
||||
};
|
||||
struct attribute_category<T,
|
||||
typename enable_if<traits::is_range<T>>::type>
|
||||
: mpl::identity<range_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
requires is_range_v<T>
|
||||
struct attribute_category<T>
|
||||
{
|
||||
using type = range_attribute;
|
||||
};
|
||||
struct attribute_category< T
|
||||
, typename enable_if<
|
||||
mpl::and_<
|
||||
traits::is_container<T>
|
||||
, mpl::not_<fusion::traits::is_sequence<T> >
|
||||
, mpl::not_<traits::is_range<T> >
|
||||
> >::type >
|
||||
: mpl::identity<container_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
requires
|
||||
(!traits::is_range_v<T>) &&
|
||||
traits::is_container_v<T> &&
|
||||
(!fusion::traits::is_sequence<T>::value)
|
||||
struct attribute_category<T>
|
||||
{
|
||||
using type = container_attribute;
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013 Agustin Berge
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -9,9 +9,11 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_ATTRIBUTE_OF_JAN_7_2012_0914AM)
|
||||
#define BOOST_SPIRIT_X3_ATTRIBUTE_OF_JAN_7_2012_0914AM
|
||||
|
||||
#include <type_traits>
|
||||
#include <boost/spirit/home/x3/support/utility/sfinae.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Get the attribute type of a component. By default, this gets the
|
||||
@@ -22,37 +24,31 @@ namespace boost::spirit::x3::traits
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
struct attribute_of;
|
||||
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
using attribute_of_t = typename attribute_of<Component, Context>::type;
|
||||
|
||||
template <typename Component, typename Context>
|
||||
requires requires {
|
||||
typename Component::attribute_type;
|
||||
}
|
||||
struct attribute_of<Component, Context>
|
||||
namespace detail
|
||||
{
|
||||
using type = typename Component::attribute_type;
|
||||
};
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
struct default_attribute_of;
|
||||
|
||||
template <typename Component, typename Context>
|
||||
requires requires {
|
||||
typename Component::template attribute<Context>::type;
|
||||
}
|
||||
struct attribute_of<Component, Context>
|
||||
{
|
||||
using type = typename Component::template attribute<Context>::type;
|
||||
};
|
||||
template <typename Component, typename Context>
|
||||
struct default_attribute_of<Component, Context,
|
||||
typename disable_if_substitution_failure<
|
||||
typename Component::attribute_type>::type>
|
||||
: mpl::identity<typename Component::attribute_type> {};
|
||||
|
||||
template <typename Component, typename Context>
|
||||
requires Component::is_pass_through_unary
|
||||
struct attribute_of<Component, Context>
|
||||
{
|
||||
static_assert(requires {
|
||||
typename Component::subject_type;
|
||||
});
|
||||
using type = typename attribute_of<typename Component::subject_type, Context>::type;
|
||||
};
|
||||
template <typename Component, typename Context>
|
||||
struct default_attribute_of<Component, Context,
|
||||
typename disable_if_substitution_failure<
|
||||
typename Component::template attribute<Context>::type>::type>
|
||||
: Component::template attribute<Context> {};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
template <typename Component, typename Context>
|
||||
struct default_attribute_of<Component, Context,
|
||||
typename enable_if_c<Component::is_pass_through_unary>::type>
|
||||
: attribute_of<typename Component::subject_type, Context>{};
|
||||
}
|
||||
|
||||
template <typename Component, typename Context, typename Enable>
|
||||
struct attribute_of : detail::default_attribute_of<Component, Context> {};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -8,20 +8,19 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_ATTRIBUTE_TYPE_JAN_5_2012_0358PM)
|
||||
#define BOOST_SPIRIT_X3_ATTRIBUTE_TYPE_JAN_5_2012_0358PM
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
// Retrieve the attribute type to use from the given type.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Retrieve the attribute type to use from the given type
|
||||
//
|
||||
// This is needed to extract the correct attribute type from proxy classes
|
||||
// as utilized in `FUSION_ADAPT_ADT` et. al.
|
||||
// as utilized in FUSION_ADAPT_ADT et. al.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Attribute, typename Enable = void>
|
||||
struct attribute_type
|
||||
{
|
||||
using type = Attribute;
|
||||
};
|
||||
struct attribute_type : mpl::identity<Attribute> {};
|
||||
|
||||
template <typename Attribute>
|
||||
using attribute_type_t = typename attribute_type<Attribute>::type;
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_SUPPORT_TRAITS_CHAR_ENCODING_TRAITS_HPP
|
||||
#define BOOST_SPIRIT_X3_SUPPORT_TRAITS_CHAR_ENCODING_TRAITS_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/char/char.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/char/literal_char.hpp>
|
||||
#include <boost/spirit/home/x3/string/literal_string.hpp>
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
# include <boost/spirit/home/x3/char_encoding/unicode.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename Encoding>
|
||||
struct char_encoding_traits_impl
|
||||
{
|
||||
using encoding_type = Encoding;
|
||||
|
||||
template <class... Args>
|
||||
[[nodiscard]] static constexpr auto lit(Args&&... args)
|
||||
noexcept(noexcept(Encoding::lit(std::forward<Args>(args)...)))
|
||||
{
|
||||
return Encoding::lit(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
[[nodiscard]] static constexpr auto string(Args&&... args)
|
||||
noexcept(noexcept(Encoding::string(std::forward<Args>(args)...)))
|
||||
{
|
||||
return Encoding::string(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
|
||||
template <traits::CharLike CharT>
|
||||
struct char_encoding_traits;
|
||||
|
||||
template <>
|
||||
struct char_encoding_traits<char> : detail::char_encoding_traits_impl<char_encoding::standard> {};
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
template <>
|
||||
struct char_encoding_traits<wchar_t> : detail::char_encoding_traits_impl<char_encoding::standard_wide> {};
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
template <>
|
||||
struct char_encoding_traits<char32_t> : detail::char_encoding_traits_impl<char_encoding::unicode> {};
|
||||
#endif
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -12,55 +12,49 @@
|
||||
#include <boost/fusion/support/category_of.hpp>
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/fusion/include/deque.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/type_traits/make_void.hpp>
|
||||
|
||||
#include <ranges>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename T>
|
||||
struct is_container : std::false_type {};
|
||||
|
||||
// TODO: fully replace this trait using std::ranges
|
||||
template <typename T>
|
||||
requires
|
||||
//std::ranges::range<T> && // TODO: this breaks `fusion::vector<>`; test case in omit.cpp.
|
||||
requires {
|
||||
typename T::value_type;
|
||||
typename T::iterator;
|
||||
typename T::size_type;
|
||||
typename T::reference;
|
||||
}
|
||||
struct is_container<T> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_container_v = is_container<T>::value;
|
||||
|
||||
template <typename T>
|
||||
concept ContainerAttr = is_container_v<std::remove_cvref_t<T>>;
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct is_associative : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
requires requires {
|
||||
typename T::key_type;
|
||||
}
|
||||
struct is_associative<T> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_associative_v = is_associative<T>::value;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This file contains some container utils for stl containers.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T, typename Enabler = void>
|
||||
struct is_container_impl : mpl::false_ {};
|
||||
|
||||
template <typename T>
|
||||
struct remove_value_const : std::type_identity<T> {};
|
||||
struct is_container_impl<T, void_t<
|
||||
typename T::value_type, typename T::iterator,
|
||||
typename T::size_type, typename T::reference> > : mpl::true_ {};
|
||||
|
||||
template <typename T, typename Enabler = void>
|
||||
struct is_associative_impl : mpl::false_ {};
|
||||
|
||||
template <typename T>
|
||||
struct is_associative_impl<T, void_t<typename T::key_type>>
|
||||
: mpl::true_ {};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using is_container = typename detail::is_container_impl<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using is_associative = typename detail::is_associative_impl<T>::type;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
{
|
||||
template <typename T>
|
||||
struct remove_value_const : mpl::identity<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct remove_value_const<T const> : remove_value_const<T> {};
|
||||
@@ -68,21 +62,18 @@ namespace boost::spirit::x3::traits
|
||||
template <typename F, typename S>
|
||||
struct remove_value_const<std::pair<F, S>>
|
||||
{
|
||||
using first_type = typename remove_value_const<F>::type;
|
||||
using second_type = typename remove_value_const<S>::type;
|
||||
using type = std::pair<first_type, second_type>;
|
||||
typedef typename remove_value_const<F>::type first_type;
|
||||
typedef typename remove_value_const<S>::type second_type;
|
||||
typedef std::pair<first_type, second_type> type;
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Container, typename Enable = void>
|
||||
struct container_value
|
||||
: detail::remove_value_const<typename Container::value_type>
|
||||
: detail::remove_value_const<typename Container::value_type>
|
||||
{};
|
||||
|
||||
template <typename Container>
|
||||
using container_value_t = typename container_value<Container>::type;
|
||||
|
||||
template <typename Container>
|
||||
struct container_value<Container const> : container_value<Container> {};
|
||||
|
||||
@@ -91,36 +82,32 @@ namespace boost::spirit::x3::traits
|
||||
// saved to container, we simply return whole fusion::map as is
|
||||
// so that check can be done in traits::is_substitute specialisation
|
||||
template <typename T>
|
||||
struct container_value<
|
||||
T,
|
||||
std::enable_if_t<
|
||||
std::conditional_t<
|
||||
fusion::traits::is_sequence<T>::value,
|
||||
fusion::traits::is_associative<T>,
|
||||
std::false_type
|
||||
>::type::value
|
||||
>
|
||||
> : std::type_identity<T> {};
|
||||
struct container_value<T
|
||||
, typename enable_if<typename mpl::eval_if <
|
||||
fusion::traits::is_sequence<T>
|
||||
, fusion::traits::is_associative<T>
|
||||
, mpl::false_ >::type >::type>
|
||||
: mpl::identity<T> {};
|
||||
|
||||
template <>
|
||||
struct container_value<unused_type> : std::type_identity<unused_type> {};
|
||||
struct container_value<unused_type> : mpl::identity<unused_type> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Container, typename Enable = void>
|
||||
struct container_iterator
|
||||
: std::type_identity<typename Container::iterator> {};
|
||||
: mpl::identity<typename Container::iterator> {};
|
||||
|
||||
template <typename Container>
|
||||
struct container_iterator<Container const>
|
||||
: std::type_identity<typename Container::const_iterator> {};
|
||||
: mpl::identity<typename Container::const_iterator> {};
|
||||
|
||||
template <>
|
||||
struct container_iterator<unused_type>
|
||||
: std::type_identity<unused_type const*> {};
|
||||
: mpl::identity<unused_type const*> {};
|
||||
|
||||
template <>
|
||||
struct container_iterator<unused_type const>
|
||||
: std::type_identity<unused_type const*> {};
|
||||
: mpl::identity<unused_type const*> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Container, typename T>
|
||||
@@ -169,13 +156,13 @@ namespace boost::spirit::x3::traits
|
||||
{
|
||||
private:
|
||||
template <typename Iterator>
|
||||
static void insert(Container& c, Iterator first, Iterator last, std::false_type)
|
||||
static void insert(Container& c, Iterator first, Iterator last, mpl::false_)
|
||||
{
|
||||
c.insert(c.end(), first, last);
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static void insert(Container& c, Iterator first, Iterator last, std::true_type)
|
||||
static void insert(Container& c, Iterator first, Iterator last, mpl::true_)
|
||||
{
|
||||
c.insert(first, last);
|
||||
}
|
||||
@@ -203,26 +190,23 @@ namespace boost::spirit::x3::traits
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Container, typename Enable = void>
|
||||
struct is_empty_container;
|
||||
|
||||
[[nodiscard]] constexpr bool is_empty(unused_type) noexcept
|
||||
struct is_empty_container
|
||||
{
|
||||
return true;
|
||||
}
|
||||
static bool call(Container const& c)
|
||||
{
|
||||
return c.empty();
|
||||
}
|
||||
};
|
||||
|
||||
template <ContainerAttr Container>
|
||||
[[nodiscard]] constexpr bool is_empty(Container const& c) noexcept
|
||||
template <typename Container>
|
||||
inline bool is_empty(Container const& c)
|
||||
{
|
||||
return is_empty_container<Container>::call(c);
|
||||
}
|
||||
|
||||
template <ContainerAttr Container>
|
||||
requires requires {
|
||||
std::ranges::empty(std::declval<Container const&>());
|
||||
}
|
||||
[[nodiscard]] constexpr bool is_empty(Container const& c) noexcept
|
||||
inline bool is_empty(unused_type)
|
||||
{
|
||||
return std::ranges::empty(c);
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -340,17 +324,17 @@ namespace boost::spirit::x3::traits
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct build_container : std::type_identity<std::vector<T>> {};
|
||||
struct build_container : mpl::identity<std::vector<T>> {};
|
||||
|
||||
template <typename T>
|
||||
struct build_container<boost::fusion::deque<T> > : build_container<T> {};
|
||||
|
||||
template <>
|
||||
struct build_container<unused_type> : std::type_identity<unused_type> {};
|
||||
struct build_container<unused_type> : mpl::identity<unused_type> {};
|
||||
|
||||
template <>
|
||||
struct build_container<char> : std::type_identity<std::string> {};
|
||||
struct build_container<char> : mpl::identity<std::string> {};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2013 Agustin Berge
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -9,21 +8,20 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_HANDLES_CONTAINER_DEC_18_2010_0920AM)
|
||||
#define BOOST_SPIRIT_X3_HANDLES_CONTAINER_DEC_18_2010_0920AM
|
||||
|
||||
#include <type_traits>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Whether a component handles container attributes intrinsically
|
||||
// (or whether container attributes need to be split up separately).
|
||||
// By default, this gets the Component's handles_container nested value.
|
||||
// Components may specialize this if such a handles_container is not
|
||||
// Components may specialize this if such a handles_container is not
|
||||
// readily available (e.g. expensive to compute at compile time).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
struct handles_container : std::bool_constant<Component::handles_container> {};
|
||||
struct handles_container : mpl::bool_<Component::handles_container> {};
|
||||
|
||||
template <typename Component, typename Context>
|
||||
constexpr bool handles_container_v = handles_container<Component, Context>::value;
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013 Agustin Berge
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -10,54 +10,50 @@
|
||||
#define BOOST_SPIRIT_X3_HAS_ATTRIBUTE_JUN_6_2012_1714PM
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/sfinae.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
struct unused_type;
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
// TODO: make these 'Component' depend on the concept.
|
||||
// It is currently hard to implement due to circular dependency.
|
||||
|
||||
// Whether a component has an attribute. By default, this compares the
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Whether a component has an attribute. By default, this compares the
|
||||
// component attribute against unused_type. If the component provides a
|
||||
// nested constant expression has_attribute as a hint, that value is used
|
||||
// instead. Components may specialize this.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
struct has_attribute
|
||||
struct has_attribute;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
static_assert(requires {
|
||||
typename attribute_of<Component, Context>::type;
|
||||
});
|
||||
static constexpr bool value = !std::is_same_v<attribute_of_t<Component, Context>, unused_type>;
|
||||
};
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
struct default_has_attribute
|
||||
: mpl::not_<is_same<unused_type,
|
||||
typename attribute_of<Component, Context>::type>> {};
|
||||
|
||||
template <typename Component, typename Context>
|
||||
constexpr bool has_attribute_v = has_attribute<Component, Context>::value;
|
||||
template <typename Component, typename Context>
|
||||
struct default_has_attribute<Component, Context,
|
||||
typename disable_if_substitution_failure<
|
||||
mpl::bool_<Component::has_attribute>>::type>
|
||||
: mpl::bool_<Component::has_attribute> {};
|
||||
|
||||
template <typename Component, typename Context>
|
||||
struct default_has_attribute<Component, Context,
|
||||
typename enable_if_c<Component::is_pass_through_unary>::type>
|
||||
: has_attribute<typename Component::subject_type, Context> {};
|
||||
}
|
||||
|
||||
template <typename Component, typename Context, typename Enable>
|
||||
struct has_attribute : detail::default_has_attribute<Component, Context> {};
|
||||
|
||||
template <typename Component, typename Context>
|
||||
requires requires {
|
||||
{ Component::has_attribute } -> std::same_as<bool>;
|
||||
}
|
||||
struct has_attribute<Component, Context>
|
||||
: std::bool_constant<Component::has_attribute>
|
||||
{};
|
||||
|
||||
template <typename Component, typename Context>
|
||||
requires Component::is_pass_through_unary
|
||||
struct has_attribute<Component, Context>
|
||||
{
|
||||
static_assert(requires {
|
||||
typename Component::subject_type;
|
||||
});
|
||||
static constexpr bool value = has_attribute_v<typename Component::subject_type, Context>;
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2014 Agustin Berge
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -9,19 +8,26 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_IS_PARSER_MAY_20_2013_0235PM)
|
||||
#define BOOST_SPIRIT_X3_IS_PARSER_MAY_20_2013_0235PM
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/sfinae.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
// is_parser<T>: metafunction that evaluates to `std::true_type` if `T`
|
||||
// models `X3Subject`, `std::false_type` otherwise
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// is_parser<T>: metafunction that evaluates to mpl::true_ if a type T
|
||||
// can be used as a parser, mpl::false_ otherwise
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Enable = void>
|
||||
struct [[deprecated("Use the concept `x3::X3Subject`")]]
|
||||
is_parser : std::bool_constant<X3Subject<T>>
|
||||
struct is_parser
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
template <typename T>
|
||||
struct is_parser<T, typename disable_if_substitution_failure<
|
||||
typename extension::as_parser<T>::type>::type>
|
||||
: mpl::true_
|
||||
{};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -8,27 +8,20 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_IS_RANGE_DEC_06_2017_1900PM)
|
||||
#define BOOST_SPIRIT_X3_IS_RANGE_DEC_06_2017_1900PM
|
||||
|
||||
#include <boost/range/range_fwd.hpp> // TODO: remove this
|
||||
#include <boost/range/range_fwd.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename T, typename Enable = void>
|
||||
struct is_range : std::false_type {};
|
||||
struct is_range
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_range_v = is_range<T>::value;
|
||||
|
||||
template <typename T>
|
||||
struct [[deprecated("Use std::ranges::subrange")]]
|
||||
is_range<boost::iterator_range<T>> : std::true_type {};
|
||||
|
||||
template <std::input_or_output_iterator It, std::sentinel_for<It> Se, std::ranges::subrange_kind Kind>
|
||||
struct is_range<std::ranges::subrange<It, Se, Kind>> : std::true_type {};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
struct is_range<boost::iterator_range<T>>
|
||||
: mpl::true_
|
||||
{};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -9,8 +9,6 @@
|
||||
#define BOOST_SPIRIT_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/container_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/tuple_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/optional_traits.hpp>
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/include/map.hpp>
|
||||
#include <boost/fusion/include/value_at_key.hpp>
|
||||
@@ -22,148 +20,140 @@
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/mpl/logical.hpp>
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/mpl/count_if.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Find out if T can be a (strong) substitute for Attribute
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Attribute, typename Enable = void>
|
||||
struct is_substitute;
|
||||
|
||||
template <typename T, typename Attribute>
|
||||
constexpr bool is_substitute_v = is_substitute<T, Attribute>::value;
|
||||
|
||||
template <typename Variant, typename Attribute>
|
||||
struct variant_has_substitute;
|
||||
|
||||
// TODO: reduce MPL usage
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T, typename Attribute>
|
||||
struct value_type_is_substitute
|
||||
: is_substitute<container_value_t<T>, container_value_t<Attribute>>
|
||||
: is_substitute<
|
||||
typename container_value<T>::type
|
||||
, typename container_value<Attribute>::type>
|
||||
{};
|
||||
|
||||
template <typename T, typename Attribute, typename Enable = void>
|
||||
struct is_substitute_impl : std::false_type {};
|
||||
struct is_substitute_impl : mpl::false_ {};
|
||||
|
||||
template <typename T, typename Attribute>
|
||||
requires std::conjunction_v<
|
||||
fusion::traits::is_sequence<T>,
|
||||
fusion::traits::is_sequence<Attribute>
|
||||
>
|
||||
struct is_substitute_impl<T, Attribute>
|
||||
: mpl::equal<T, Attribute, is_substitute<mpl::_1, mpl::_2>>
|
||||
{};
|
||||
struct is_substitute_impl<T, Attribute,
|
||||
typename enable_if<
|
||||
mpl::and_<
|
||||
fusion::traits::is_sequence<T>,
|
||||
fusion::traits::is_sequence<Attribute>,
|
||||
mpl::equal<T, Attribute, is_substitute<mpl::_1, mpl::_2>>
|
||||
>
|
||||
>::type>
|
||||
: mpl::true_ {};
|
||||
|
||||
template <typename T, typename Attribute>
|
||||
requires
|
||||
is_container_v<T> &&
|
||||
is_container_v<Attribute>
|
||||
struct is_substitute_impl<T, Attribute>
|
||||
: value_type_is_substitute<T, Attribute>
|
||||
{};
|
||||
struct is_substitute_impl<T, Attribute,
|
||||
typename enable_if<
|
||||
mpl::and_<
|
||||
is_container<T>,
|
||||
is_container<Attribute>,
|
||||
value_type_is_substitute<T, Attribute>
|
||||
>
|
||||
>::type>
|
||||
: mpl::true_ {};
|
||||
|
||||
template <typename T, typename Attribute>
|
||||
requires is_variant_v<Attribute>
|
||||
struct is_substitute_impl<T, Attribute>
|
||||
: variant_has_substitute<Attribute, T>
|
||||
struct is_substitute_impl<T, Attribute,
|
||||
typename enable_if<
|
||||
is_variant<Attribute>
|
||||
>::type>
|
||||
: variant_has_substitute<Attribute, T>
|
||||
{};
|
||||
}
|
||||
|
||||
template <typename T, typename Attribute, typename Enable>
|
||||
template <typename T, typename Attribute, typename Enable /*= void*/>
|
||||
struct is_substitute
|
||||
: std::disjunction<
|
||||
std::is_same<T, Attribute>,
|
||||
detail::is_substitute_impl<T, Attribute>
|
||||
>
|
||||
{};
|
||||
: mpl::or_<
|
||||
is_same<T, Attribute>,
|
||||
detail::is_substitute_impl<T, Attribute>> {};
|
||||
|
||||
// for reference T
|
||||
template <typename T, typename Attribute>
|
||||
struct is_substitute<T&, Attribute>
|
||||
: is_substitute<T, Attribute>
|
||||
{};
|
||||
template <typename T, typename Attribute, typename Enable>
|
||||
struct is_substitute<T&, Attribute, Enable>
|
||||
: is_substitute<T, Attribute, Enable> {};
|
||||
|
||||
// for reference Attribute
|
||||
template <typename T, typename Attribute>
|
||||
struct is_substitute<T, Attribute&>
|
||||
: is_substitute<T, Attribute>
|
||||
{};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename Key, typename Value, typename Map>
|
||||
struct has_fusion_kv_in_map : std::false_type {};
|
||||
|
||||
template <typename Key, typename Value, typename Map>
|
||||
requires fusion::result_of::has_key<Map, Key>::value
|
||||
struct has_fusion_kv_in_map<Key, Value, Map> : is_substitute<
|
||||
typename fusion::result_of::value_at_key<Map, Key>::type,
|
||||
Value
|
||||
> {};
|
||||
} // detail
|
||||
template <typename T, typename Attribute, typename Enable>
|
||||
struct is_substitute<T, Attribute&, Enable>
|
||||
: is_substitute<T, Attribute, Enable> {};
|
||||
|
||||
// 2 element mpl tuple is compatible with fusion::map if:
|
||||
// - it's first element type is existing key in map
|
||||
// - it second element type is compatible to type stored at the key in map
|
||||
template <typename T, typename Attribute>
|
||||
requires std::conjunction_v<
|
||||
fusion::traits::is_sequence<T>,
|
||||
fusion::traits::is_sequence<Attribute>,
|
||||
traits::has_size<T, 2>,
|
||||
fusion::traits::is_associative<Attribute>
|
||||
>
|
||||
struct is_substitute<T, Attribute>
|
||||
struct is_substitute<T, Attribute
|
||||
, typename enable_if<
|
||||
typename mpl::eval_if<
|
||||
mpl::and_<fusion::traits::is_sequence<T>
|
||||
, fusion::traits::is_sequence<Attribute>>
|
||||
, mpl::and_<traits::has_size<T, 2>
|
||||
, fusion::traits::is_associative<Attribute>>
|
||||
, mpl::false_>::type>::type>
|
||||
|
||||
{
|
||||
// Checking that "p_key >> p_value" parser can
|
||||
// checking that "p_key >> p_value" parser can
|
||||
// store it's result in fusion::map attribute
|
||||
using p_key = typename mpl::at_c<T, 0>::type;
|
||||
using p_value = typename mpl::at_c<T, 1>::type;
|
||||
typedef typename mpl::at_c<T, 0>::type p_key;
|
||||
typedef typename mpl::at_c<T, 1>::type p_value;
|
||||
|
||||
// For simple `p_key` type we just check that
|
||||
// for simple p_key type we just check that
|
||||
// such key can be found in attr and that value under that key
|
||||
// matches `p_value`.
|
||||
// matches p_value
|
||||
template <typename Key, typename Value, typename Map>
|
||||
struct has_kv_in_map
|
||||
: mpl::eval_if<
|
||||
fusion::result_of::has_key<Map, Key>
|
||||
, mpl::apply<
|
||||
is_substitute<
|
||||
fusion::result_of::value_at_key<mpl::_1, Key>
|
||||
, Value>
|
||||
, Map>
|
||||
, mpl::false_>
|
||||
{};
|
||||
|
||||
// Otherwise, if p_key is variant over multiple types (as a result of
|
||||
// "(key1|key2|key3) >> p_value" parser), check that all
|
||||
// keys are found in `fusion::map` attribute and that values
|
||||
// under these keys match `p_value`.
|
||||
// if p_key is variant over multiple types (as a result of
|
||||
// "(key1|key2|key3) >> p_value" parser) check that all
|
||||
// keys are found in fusion::map attribute and that values
|
||||
// under these keys match p_value
|
||||
template <typename Variant>
|
||||
struct variant_kv
|
||||
: mpl::equal_to<
|
||||
mpl::size<typename Variant::types>,
|
||||
mpl::size<
|
||||
mpl::filter_view<
|
||||
typename Variant::types,
|
||||
detail::has_fusion_kv_in_map<mpl::_1, p_value, Attribute>
|
||||
>
|
||||
>
|
||||
mpl::size< typename Variant::types>
|
||||
, mpl::size< mpl::filter_view<typename Variant::types
|
||||
, has_kv_in_map<mpl::_1, p_value, Attribute>>>
|
||||
>
|
||||
{};
|
||||
|
||||
static constexpr bool value = std::conditional_t<
|
||||
is_variant_v<p_key>,
|
||||
variant_kv<p_key>,
|
||||
detail::has_fusion_kv_in_map<p_key, p_value, Attribute>
|
||||
>::value;
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_variant<p_key>
|
||||
, variant_kv<p_key>
|
||||
, has_kv_in_map<p_key, p_value, Attribute>
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
#if BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL
|
||||
template <typename T, typename Attribute>
|
||||
struct [[deprecated("Use std::optional")]] is_substitute<boost::optional<T>, boost::optional<Attribute>>
|
||||
: is_substitute<T, Attribute>
|
||||
{};
|
||||
#endif
|
||||
|
||||
template <typename T, typename Attribute>
|
||||
struct is_substitute<std::optional<T>, std::optional<Attribute>>
|
||||
: is_substitute<T, Attribute>
|
||||
{};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
struct is_substitute<optional<T>, optional<Attribute>>
|
||||
: is_substitute<T, Attribute> {};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -8,40 +8,34 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_IS_VARIANT_JAN_10_2012_0823AM)
|
||||
#define BOOST_SPIRIT_X3_IS_VARIANT_JAN_10_2012_0823AM
|
||||
|
||||
#include <boost/variant/variant_fwd.hpp> // TODO: remove this
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/mpl/has_xxx.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
// TODO: define a legit concept for determining variant-like types
|
||||
namespace detail
|
||||
{
|
||||
// By declaring a nested struct in your class/struct, you tell
|
||||
// spirit that it is regarded as a variant type. The minimum
|
||||
// required interface for such a variant is that it has constructors
|
||||
// for various types supported by your variant and a typedef 'types'
|
||||
// which is an mpl sequence of the contained types.
|
||||
//
|
||||
// This is an intrusive interface. For a non-intrusive interface,
|
||||
// use the is_variant trait.
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(adapted_variant_tag)
|
||||
}
|
||||
|
||||
template <typename T, typename Enabled = void>
|
||||
struct is_variant : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_variant_v = is_variant<T>::value;
|
||||
|
||||
// By declaring a nested struct named `adapted_variant_tag` in
|
||||
// your class, you tell spirit that it is regarded as a variant type.
|
||||
// The minimum required interface for such a variant is that it has
|
||||
// constructors for various types supported by your variant and a
|
||||
// typedef 'types' which is an mpl sequence of the contained types.
|
||||
// Note (2025): The above spec is obsolete and will change in the near future.
|
||||
//
|
||||
// This is an intrusive interface. For a non-intrusive interface,
|
||||
// specialize the is_variant trait.
|
||||
template <typename T>
|
||||
requires requires {
|
||||
typename T::adapted_variant_tag;
|
||||
}
|
||||
struct is_variant<T> : std::true_type
|
||||
template <typename T, typename Enable = void>
|
||||
struct is_variant
|
||||
: detail::has_adapted_variant_tag<T>
|
||||
{};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
|
||||
: std::true_type
|
||||
: mpl::true_
|
||||
{};
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013 Agustin Berge
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -17,259 +17,212 @@
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/include/front.hpp>
|
||||
#include <boost/fusion/include/move.hpp>
|
||||
#include <boost/fusion/include/copy.hpp>
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
|
||||
# include <boost/range/iterator_range_core.hpp> // deprecated
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <iterator>
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
// Identical types ---------------------------------------
|
||||
//
|
||||
// Note that these overloads must be strictly "more constrained"
|
||||
// than any of the other overloads.
|
||||
//
|
||||
// Such resolution should be possible even without an extra
|
||||
// constraint that checks `std::is_same_v<Source, Dest>`, thanks to
|
||||
// the ordinary overload resolution rules of C++.
|
||||
template <typename Source, typename Dest>
|
||||
inline void move_to(Source&& src, Dest& dest);
|
||||
|
||||
template <typename T>
|
||||
requires (!CategorizedAttr<T, unused_attribute>)
|
||||
constexpr void move_to(T const&& src, T& dest)
|
||||
noexcept(std::is_nothrow_assignable_v<T&, T const&&>)
|
||||
inline void move_to(T& src, T& dest);
|
||||
|
||||
template <typename T>
|
||||
inline void move_to(T const& src, T& dest);
|
||||
|
||||
template <typename T>
|
||||
inline void move_to(T&& src, T& dest);
|
||||
|
||||
template <typename Iterator, typename Dest>
|
||||
inline void move_to(Iterator first, Iterator last, Dest& dest);
|
||||
|
||||
template <typename Dest>
|
||||
inline void move_to(unused_type, Dest&) {}
|
||||
|
||||
template <typename Source>
|
||||
inline void move_to(Source&, unused_type) {}
|
||||
|
||||
inline void move_to(unused_type, unused_type) {}
|
||||
|
||||
template <typename Iterator>
|
||||
inline void
|
||||
move_to(Iterator, Iterator, unused_type) {}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source&, Dest&, unused_attribute) {}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to_plain(Source& src, Dest& dest, mpl::false_) // src is not a single-element tuple
|
||||
{
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to_plain(Source& src, Dest& dest, mpl::true_) // src is a single-element tuple
|
||||
{
|
||||
dest = std::move(fusion::front(src));
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source& src, Dest& dest, plain_attribute)
|
||||
{
|
||||
typename mpl::and_<
|
||||
fusion::traits::is_sequence<Source>,
|
||||
is_size_one_sequence<Source> >
|
||||
is_single_element_sequence;
|
||||
|
||||
move_to_plain(src, dest, is_single_element_sequence);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline typename enable_if<is_container<Source>>::type
|
||||
move_to(Source& src, Dest& dest, container_attribute)
|
||||
{
|
||||
traits::move_to(src.begin(), src.end(), dest);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline typename enable_if<
|
||||
mpl::and_<
|
||||
is_same_size_sequence<Dest, Source>,
|
||||
mpl::not_<is_size_one_sequence<Dest> > >
|
||||
>::type
|
||||
move_to(Source& src, Dest& dest, tuple_attribute)
|
||||
{
|
||||
fusion::move(std::move(src), dest);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline typename enable_if<
|
||||
is_size_one_sequence<Dest>
|
||||
>::type
|
||||
move_to(Source& src, Dest& dest, tuple_attribute)
|
||||
{
|
||||
traits::move_to(src, fusion::front(dest));
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source& src, Dest& dest, variant_attribute, mpl::false_)
|
||||
{
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to_variant_from_single_element_sequence(Source& src, Dest& dest, mpl::false_)
|
||||
{
|
||||
// dest is a variant, src is a single element fusion sequence that the variant
|
||||
// cannot directly hold. We'll try to unwrap the single element fusion sequence.
|
||||
|
||||
// Make sure that the Dest variant can really hold Source
|
||||
static_assert(variant_has_substitute<Dest, typename fusion::result_of::front<Source>::type>::value,
|
||||
"Error! The destination variant (Dest) cannot hold the source type (Source)");
|
||||
|
||||
dest = std::move(fusion::front(src));
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to_variant_from_single_element_sequence(Source& src, Dest& dest, mpl::true_)
|
||||
{
|
||||
// dest is a variant, src is a single element fusion sequence that the variant
|
||||
// *can* directly hold.
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source& src, Dest& dest, variant_attribute, mpl::true_)
|
||||
{
|
||||
move_to_variant_from_single_element_sequence(src, dest, variant_has_substitute<Dest, Source>());
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source& src, Dest& dest, variant_attribute tag)
|
||||
{
|
||||
move_to(src, dest, tag, is_size_one_sequence<Source>());
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source& src, Dest& dest, optional_attribute)
|
||||
{
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
inline void
|
||||
move_to(Iterator, Iterator, unused_type, unused_attribute) {}
|
||||
|
||||
template <typename Iterator, typename Dest>
|
||||
inline void
|
||||
move_to(Iterator first, Iterator last, Dest& dest, container_attribute)
|
||||
{
|
||||
if (is_empty(dest))
|
||||
dest = Dest(first, last);
|
||||
else
|
||||
append(dest, first, last);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Dest>
|
||||
inline typename enable_if<
|
||||
is_size_one_sequence<Dest>
|
||||
>::type
|
||||
move_to(Iterator first, Iterator last, Dest& dest, tuple_attribute)
|
||||
{
|
||||
traits::move_to(first, last, fusion::front(dest));
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
inline void
|
||||
move_to(Iterator first, Iterator last, boost::iterator_range<Iterator>& rng, range_attribute)
|
||||
{
|
||||
rng = {first, last};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void move_to(Source&& src, Dest& dest)
|
||||
{
|
||||
detail::move_to(src, dest, typename attribute_category<Dest>::type());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void move_to(T& src, T& dest)
|
||||
{
|
||||
BOOST_ASSERT(boost::addressof(src) != boost::addressof(dest));
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires (!CategorizedAttr<T, unused_attribute>)
|
||||
constexpr void move_to(T&& src, T& dest)
|
||||
noexcept(std::is_nothrow_assignable_v<T&, T&&>)
|
||||
{
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires (!CategorizedAttr<T, unused_attribute>)
|
||||
constexpr void move_to(T const& src, T& dest)
|
||||
noexcept(std::is_nothrow_copy_assignable_v<T>)
|
||||
inline void move_to(T const& src, T& dest)
|
||||
{
|
||||
BOOST_ASSERT(boost::addressof(src) != boost::addressof(dest));
|
||||
dest = src;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires (!CategorizedAttr<T, unused_attribute>)
|
||||
constexpr void move_to(T&, T&) noexcept
|
||||
inline void move_to(T&& src, T& dest)
|
||||
{
|
||||
static_assert(
|
||||
!std::is_const_v<T>,
|
||||
"`x3::move_to(T const&, T const&)` is not allowed"
|
||||
);
|
||||
|
||||
static_assert(
|
||||
false,
|
||||
"lvalue reference detected on the `src` argument of `x3::move_to`. "
|
||||
"The caller is definitely lacking `std::move` or `std::forward`. If you "
|
||||
"intend to *copy* the mutable value, apply `x3::move_to(std::as_const(attr_), attr)`."
|
||||
);
|
||||
// Banned: possible, but bug-prone.
|
||||
// dest = std::move(src);
|
||||
BOOST_ASSERT(boost::addressof(src) != boost::addressof(dest));
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
// unused_type -------------------------------------------
|
||||
template <typename Source, typename Dest>
|
||||
requires
|
||||
CategorizedAttr<Source, unused_attribute> ||
|
||||
CategorizedAttr<Dest, unused_attribute>
|
||||
constexpr void move_to(Source&&, Dest&) noexcept
|
||||
template <typename Iterator, typename Dest>
|
||||
inline void move_to(Iterator first, Iterator last, Dest& dest)
|
||||
{
|
||||
// $$$ Use std::move_iterator when iterator is not a const-iterator $$$
|
||||
detail::move_to(first, last, dest, typename attribute_category<Dest>::type());
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Dest>
|
||||
requires
|
||||
std::is_same_v<std::remove_const_t<Dest>, unused_type>
|
||||
constexpr void
|
||||
move_to(It, Se, Dest&) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
// Category specific --------------------------------------
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<plain_attribute> Dest>
|
||||
requires is_size_one_sequence_v<Source>
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(noexcept(dest = std::forward_like<Source>(fusion::front(std::forward<Source>(src)))))
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
dest = std::forward_like<Source>(fusion::front(std::forward<Source>(src)));
|
||||
}
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<plain_attribute> Dest>
|
||||
requires (!is_size_one_sequence_v<Source>)
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(std::is_nothrow_assignable_v<Dest&, Source&&>)
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
static_assert(std::is_assignable_v<Dest&, Source&&>);
|
||||
dest = std::forward<Source>(src);
|
||||
}
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<tuple_attribute> Dest>
|
||||
requires
|
||||
is_same_size_sequence_v<Dest, Source> &&
|
||||
(!is_size_one_sequence_v<Dest>)
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(
|
||||
std::is_rvalue_reference_v<Source&&> ?
|
||||
noexcept(fusion::move(std::move(src), dest)) :
|
||||
noexcept(fusion::copy(src, dest))
|
||||
)
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
|
||||
if constexpr (std::is_rvalue_reference_v<Source&&>)
|
||||
{
|
||||
fusion::move(std::move(src), dest);
|
||||
}
|
||||
else
|
||||
{
|
||||
fusion::copy(src, dest);
|
||||
}
|
||||
}
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<variant_attribute> Dest>
|
||||
requires is_size_one_sequence_v<Source> && variant_has_substitute_v<Dest, Source>
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(std::is_nothrow_assignable_v<Dest&, Source&&>)
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
|
||||
// dest is a variant, src is a single element fusion sequence that the variant
|
||||
// *can* directly hold.
|
||||
dest = std::forward<Source>(src);
|
||||
}
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<variant_attribute> Dest>
|
||||
requires is_size_one_sequence_v<Source> && (!variant_has_substitute_v<Dest, Source>)
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(noexcept(dest = std::forward_like<Source>(fusion::front(std::forward<Source>(src)))))
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
|
||||
// dest is a variant, src is a single element fusion sequence that the variant
|
||||
// cannot directly hold. We'll try to unwrap the single element fusion sequence.
|
||||
|
||||
// Make sure that the Dest variant can really hold Source
|
||||
static_assert(
|
||||
variant_has_substitute_v<Dest, typename fusion::result_of::front<Source>::type>,
|
||||
"Error! The destination variant (Dest) cannot hold the source type (Source)"
|
||||
);
|
||||
|
||||
dest = std::forward_like<Source>(fusion::front(std::forward<Source>(src)));
|
||||
}
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<variant_attribute> Dest>
|
||||
requires (!is_size_one_sequence_v<Source>)
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(std::is_nothrow_assignable_v<Dest&, Source&&>)
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
dest = std::forward<Source>(src);
|
||||
}
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<optional_attribute> Dest>
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(std::is_nothrow_assignable_v<Dest&, Source&&>)
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
dest = std::forward<Source>(src);
|
||||
}
|
||||
|
||||
// Containers -------------------------------------------------
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, CategorizedAttr<container_attribute> Dest>
|
||||
constexpr void
|
||||
move_to(It first, Se last, Dest& dest)
|
||||
// never noexcept, requires container insertion
|
||||
{
|
||||
if (traits::is_empty(dest))
|
||||
{
|
||||
dest = Dest(first, last);
|
||||
}
|
||||
else
|
||||
{
|
||||
traits::append(dest, first, last);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
|
||||
template <std::forward_iterator It>
|
||||
constexpr void
|
||||
move_to(It first, It last, boost::iterator_range<It>& rng)
|
||||
{
|
||||
rng = {first, last};
|
||||
}
|
||||
#endif
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, std::ranges::subrange_kind Kind>
|
||||
constexpr void
|
||||
move_to(It first, Se last, std::ranges::subrange<It, Se, Kind>& rng)
|
||||
{
|
||||
rng = std::ranges::subrange<It, Se, Kind>(std::move(first), std::move(last));
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, CategorizedAttr<tuple_attribute> Dest>
|
||||
requires is_size_one_sequence_v<Dest>
|
||||
constexpr void
|
||||
move_to(It first, Se last, Dest& dest)
|
||||
noexcept(noexcept(traits::move_to(first, last, fusion::front(dest))))
|
||||
{
|
||||
traits::move_to(first, last, fusion::front(dest));
|
||||
}
|
||||
|
||||
template <ContainerAttr Source, CategorizedAttr<container_attribute> Dest>
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
// TODO: noexcept
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
|
||||
if constexpr (std::is_rvalue_reference_v<Source&&>)
|
||||
{
|
||||
traits::move_to(std::make_move_iterator(std::ranges::begin(src)), std::make_move_iterator(std::ranges::end(src)), dest);
|
||||
}
|
||||
else
|
||||
{
|
||||
traits::move_to(std::ranges::begin(src), std::ranges::end(src), dest);
|
||||
}
|
||||
}
|
||||
|
||||
// Size-one fusion tuple forwarding
|
||||
template <NonUnusedAttr Source, CategorizedAttr<tuple_attribute> Dest>
|
||||
requires is_size_one_sequence_v<Dest>
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(noexcept(traits::move_to(std::forward<Source>(src), fusion::front(dest))))
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
|
||||
traits::move_to(std::forward<Source>(src), fusion::front(dest));
|
||||
}
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -10,87 +10,65 @@
|
||||
#define BOOST_SPIRIT_X3_OPTIONAL_TRAITS_FEBRUARY_06_2007_1001AM
|
||||
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL
|
||||
# define BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL 1
|
||||
#endif
|
||||
|
||||
#if BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL
|
||||
# include <boost/optional/optional.hpp>
|
||||
#endif
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Enable = void>
|
||||
struct is_optional : std::false_type {};
|
||||
struct is_optional
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_optional_v = is_optional<T>::value;
|
||||
struct is_optional<boost::optional<T>>
|
||||
: mpl::true_
|
||||
{};
|
||||
|
||||
#if BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL
|
||||
template <typename T>
|
||||
struct [[deprecated("Use std::optional")]] is_optional<boost::optional<T>> : std::true_type {};
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct is_optional<std::optional<T>> : std::true_type {};
|
||||
|
||||
// Build a optional type from T. Return unused_type if T is unused_type.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// build_optional
|
||||
//
|
||||
// Build a boost::optional from T. Return unused_type if T is unused_type.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct build_optional
|
||||
{
|
||||
#if BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL
|
||||
using type [[deprecated("Use std::optional")]] = boost::optional<T>;
|
||||
#else
|
||||
using type = std::optional<T>;
|
||||
#endif
|
||||
typedef boost::optional<T> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using build_optional_t = typename build_optional<T>::type;
|
||||
|
||||
#if BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL
|
||||
template <typename T>
|
||||
struct [[deprecated("Use std::optional")]] build_optional<boost::optional<T>>
|
||||
struct build_optional<boost::optional<T> >
|
||||
{
|
||||
using type = boost::optional<T>;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct build_optional<std::optional<T>>
|
||||
{
|
||||
using type = std::optional<T>;
|
||||
typedef boost::optional<T> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct build_optional<unused_type>
|
||||
{
|
||||
using type = unused_type;
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// optional_value
|
||||
//
|
||||
// Get the optional's value_type. Handles unused_type as well.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct optional_value { using type = typename T::value_type; };
|
||||
struct optional_value : mpl::identity<T> {};
|
||||
|
||||
template <typename T>
|
||||
using optional_value_t = typename optional_value<T>::type;
|
||||
struct optional_value<boost::optional<T> >
|
||||
: mpl::identity<T> {};
|
||||
|
||||
template <>
|
||||
struct optional_value<unused_type>
|
||||
{
|
||||
using type = unused_type;
|
||||
};
|
||||
: mpl::identity<unused_type> {};
|
||||
|
||||
template <>
|
||||
struct optional_value<unused_type const>
|
||||
{
|
||||
using type = unused_type;
|
||||
};
|
||||
: mpl::identity<unused_type> {};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -10,16 +9,16 @@
|
||||
#define BOOST_SPIRIT_X3_PRINT_ATTRIBUTE_JANUARY_20_2013_0814AM
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/is_variant.hpp>
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
# include <boost/spirit/home/x3/char_encoding/unicode.hpp>
|
||||
# include <boost/spirit/home/support/char_encoding/unicode.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename Out, typename T>
|
||||
void print_attribute(Out& out, T const& val);
|
||||
@@ -166,6 +165,6 @@ namespace boost::spirit::x3::traits
|
||||
{
|
||||
print_attribute_debug<Out, T>::call(out, val);
|
||||
}
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2019 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -8,29 +7,28 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_PSEUDO_ATTRIBUTE_OF_MAY_15_2019_1012PM)
|
||||
#define BOOST_SPIRIT_X3_PSEUDO_ATTRIBUTE_OF_MAY_15_2019_1012PM
|
||||
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Pseudo attributes are placeholders for parsers that can only know
|
||||
// its actual attribute at parse time. This trait customization point
|
||||
// provides a mechanism to convert the trait to the actual trait at
|
||||
// parse time.
|
||||
template <typename Context, typename Attribute, std::forward_iterator It, std::sentinel_for<It> Se = It, typename Enable = void>
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Context, typename Attribute, typename Iterator
|
||||
, typename Enable = void>
|
||||
struct pseudo_attribute
|
||||
{
|
||||
using attribute_type = Attribute;
|
||||
using type = Attribute;
|
||||
|
||||
[[nodiscard]] static constexpr type&& call(It&, Se const&, Attribute&& attribute) noexcept
|
||||
static type&& call(Iterator&, Iterator const&, attribute_type&& attribute)
|
||||
{
|
||||
return static_cast<type&&>(attribute);
|
||||
return std::forward<type>(attribute);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Context, typename Attribute, std::forward_iterator It, std::sentinel_for<It> Se>
|
||||
using pseudo_attribute_t = typename pseudo_attribute<Context, Attribute, It, Se>::type;
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2010 Bryce Lelbach
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
Copyright (c) 2010 Bryce Lelbach
|
||||
|
||||
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)
|
||||
@@ -10,113 +9,146 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_STRING_TRAITS_OCTOBER_2008_1252PM)
|
||||
#define BOOST_SPIRIT_X3_STRING_TRAITS_OCTOBER_2008_1252PM
|
||||
|
||||
#if defined(BOOST_SPIRIT_UNICODE) && !defined(BOOST_SPIRIT_X3_UNICODE)
|
||||
# error "`BOOST_SPIRIT_UNICODE` has no effect on X3. #define `BOOST_SPIRIT_X3_UNICODE`"
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_SPIRIT_X3_NO_STANDARD_WIDE) && !defined(BOOST_SPIRIT_X3_NO_STANDARD_WIDE)
|
||||
# error "`BOOST_SPIRIT_X3_NO_STANDARD_WIDE` has no effect on X3. #define `BOOST_SPIRIT_X3_NO_STANDARD_WIDE`"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost::spirit::x3::char_encoding
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
struct standard;
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Get the C string from a string
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename String>
|
||||
struct extract_c_string;
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
struct standard_wide;
|
||||
#endif
|
||||
template <typename String>
|
||||
struct extract_c_string
|
||||
{
|
||||
template <typename T>
|
||||
static T const* call (T* str)
|
||||
{
|
||||
return (T const*)str;
|
||||
}
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
struct unicode;
|
||||
#endif
|
||||
} // boost::spirit::x3::char_encoding
|
||||
template <typename T>
|
||||
static T const* call (T const* str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
{
|
||||
// Forwarder that strips const
|
||||
template <typename T>
|
||||
concept CharLike =
|
||||
std::same_as<std::remove_cvref_t<T>, char> ||
|
||||
std::same_as<std::remove_cvref_t<T>, wchar_t> ||
|
||||
std::same_as<std::remove_cvref_t<T>, char8_t> ||
|
||||
std::same_as<std::remove_cvref_t<T>, char16_t> ||
|
||||
std::same_as<std::remove_cvref_t<T>, char32_t>;
|
||||
struct extract_c_string<T const>
|
||||
{
|
||||
static decltype(auto) call(T const str)
|
||||
{
|
||||
return extract_c_string<T>::call(str);
|
||||
}
|
||||
};
|
||||
|
||||
// Spirit has historically converted "c" to 'c'.
|
||||
//
|
||||
// While we think it's still useful to retain the conversion,
|
||||
// we need to avoid further conversion to `std::basic_string_view`,
|
||||
// which leads to performance overhead. This trait enables
|
||||
// detection of such arrays.
|
||||
//
|
||||
// Note that the status quo introduces ambiguity in determining
|
||||
// {'c', '\0'} and {'c', 'd'}, but we're not aware of any practical
|
||||
// usage of non-null-terminated character array in the context of
|
||||
// DSL on parser combinator.
|
||||
//
|
||||
// However, if compelling use cases emerge, we may revise these
|
||||
// semantics. Versioned as `X3` for forward compatibility.
|
||||
template <typename T, typename CharT>
|
||||
concept X3VagueArrayOf2Chars =
|
||||
std::same_as<std::remove_all_extents_t<std::remove_cvref_t<T>>, CharT> &&
|
||||
std::is_bounded_array_v<std::remove_cvref_t<T>> &&
|
||||
std::extent_v<std::remove_cvref_t<T>> == 2;
|
||||
// Forwarder that strips references
|
||||
template <typename T>
|
||||
struct extract_c_string<T&>
|
||||
{
|
||||
static decltype(auto) call(T& str)
|
||||
{
|
||||
return extract_c_string<T>::call(str);
|
||||
}
|
||||
};
|
||||
|
||||
// Main utility to guide `char_`, `lit` and `string` to be
|
||||
// resolved into either `x3::literal_char` or `x3::literal_string`.
|
||||
//
|
||||
// This may also be used in other codes which require the same
|
||||
// semantics.
|
||||
template <typename T, typename CharT>
|
||||
concept CppStringLike =
|
||||
// This avoids converting `CharT[2]` to `std::basic_string_view`.
|
||||
(!X3VagueArrayOf2Chars<T, CharT>) &&
|
||||
// All other types that are *naturally* convertible to `std::basic_string_view`.
|
||||
std::convertible_to<std::decay_t<T>, std::basic_string_view<CharT>>;
|
||||
// Forwarder that strips const references
|
||||
template <typename T>
|
||||
struct extract_c_string<T const&>
|
||||
{
|
||||
static decltype(auto) call(T const& str)
|
||||
{
|
||||
return extract_c_string<T>::call(str);
|
||||
}
|
||||
};
|
||||
|
||||
// Mixing incompatible character types is semantically wrong.
|
||||
// Don't do that. It may even lead to security vulnerabilities.
|
||||
template <typename T, typename ExpectedCharT>
|
||||
concept CharIncompatibleWith =
|
||||
CharLike<T> &&
|
||||
!std::same_as<std::remove_cvref_t<T>, ExpectedCharT>;
|
||||
template <typename T, typename Traits, typename Allocator>
|
||||
struct extract_c_string<std::basic_string<T, Traits, Allocator> >
|
||||
{
|
||||
typedef std::basic_string<T, Traits, Allocator> string;
|
||||
|
||||
// Mixing incompatible character types is semantically wrong.
|
||||
// Don't do that. It may even lead to security vulnerabilities.
|
||||
template <typename T, typename ExpectedCharT>
|
||||
concept StringLikeIncompatibleWith =
|
||||
CharLike<std::remove_const_t<std::remove_pointer_t<std::decay_t<T>>>> &&
|
||||
!std::convertible_to<T, std::basic_string_view<ExpectedCharT>>;
|
||||
static T const* call (string const& str)
|
||||
{
|
||||
return str.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <CharLike CharT> struct char_encoding_for_impl;
|
||||
template <> struct char_encoding_for_impl<char> { using type = char_encoding::standard; };
|
||||
template <typename T>
|
||||
decltype(auto) get_c_string(T* str)
|
||||
{
|
||||
return extract_c_string<T*>::call(str);
|
||||
}
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
template <> struct char_encoding_for_impl<wchar_t> { using type = char_encoding::standard_wide; };
|
||||
#endif
|
||||
template <typename T>
|
||||
decltype(auto) get_c_string(T const* str)
|
||||
{
|
||||
return extract_c_string<T const*>::call(str);
|
||||
}
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
template <> struct char_encoding_for_impl<char8_t> { using type = char_encoding::unicode; };
|
||||
template <> struct char_encoding_for_impl<char16_t> { using type = char_encoding::unicode; };
|
||||
template <> struct char_encoding_for_impl<char32_t> { using type = char_encoding::unicode; };
|
||||
#endif
|
||||
} // detail
|
||||
template <typename String>
|
||||
decltype(auto) get_c_string(String& str)
|
||||
{
|
||||
return extract_c_string<String>::call(str);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
using maybe_owning_string = std::conditional_t<
|
||||
std::is_pointer_v<std::decay_t<T>>,
|
||||
std::basic_string_view<std::remove_const_t<std::remove_pointer_t<std::decay_t<T>>>>,
|
||||
std::remove_cvref_t<T>
|
||||
>;
|
||||
template <typename String>
|
||||
decltype(auto) get_c_string(String const& str)
|
||||
{
|
||||
return extract_c_string<String>::call(str);
|
||||
}
|
||||
|
||||
template <CharLike CharT>
|
||||
using char_encoding_for = typename detail::char_encoding_for_impl<CharT>::type;
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Get the begin/end iterators from a string
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
// Implementation for C-style strings.
|
||||
|
||||
template <typename T>
|
||||
inline T const* get_string_begin(T const* str) { return str; }
|
||||
|
||||
template <typename T>
|
||||
inline T* get_string_begin(T* str) { return str; }
|
||||
|
||||
template <typename T>
|
||||
inline T const* get_string_end(T const* str)
|
||||
{
|
||||
T const* last = str;
|
||||
while (*last)
|
||||
last++;
|
||||
return last;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T* get_string_end(T* str)
|
||||
{
|
||||
T* last = str;
|
||||
while (*last)
|
||||
last++;
|
||||
return last;
|
||||
}
|
||||
|
||||
// Implementation for containers (includes basic_string).
|
||||
template <typename T, typename Str>
|
||||
inline typename Str::const_iterator get_string_begin(Str const& str)
|
||||
{ return str.begin(); }
|
||||
|
||||
template <typename T, typename Str>
|
||||
inline typename Str::iterator
|
||||
get_string_begin(Str& str)
|
||||
{ return str.begin(); }
|
||||
|
||||
template <typename T, typename Str>
|
||||
inline typename Str::const_iterator get_string_end(Str const& str)
|
||||
{ return str.end(); }
|
||||
|
||||
template <typename T, typename Str>
|
||||
inline typename Str::iterator
|
||||
get_string_end(Str& str)
|
||||
{ return str.end(); }
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2012 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -9,7 +9,9 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_ATTRIBUTE_TRANSFORM_JAN_8_2012_0721PM)
|
||||
#define BOOST_SPIRIT_X3_ATTRIBUTE_TRANSFORM_JAN_8_2012_0721PM
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// transform_attribute
|
||||
@@ -22,12 +24,6 @@ namespace boost::spirit::x3::traits
|
||||
template <typename Exposed, typename Transformed, typename Tag
|
||||
, typename Enable = void>
|
||||
struct transform_attribute;
|
||||
|
||||
template <typename Exposed, typename Transformed, typename Tag>
|
||||
concept Transformable = requires {
|
||||
typename transform_attribute<Exposed, Transformed, Tag>::type;
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -11,69 +10,48 @@
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/include/is_view.hpp>
|
||||
#include <boost/fusion/include/size.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
// Note that these metafunctions MUST be explicitly derived from `std::bool_constant`,
|
||||
// because they are used for tag dispatch in some locations.
|
||||
// Beware that `std::conjunction` / `std::disjunction` is not guaranteed to derive
|
||||
// from `std::bool_constant`.
|
||||
|
||||
template <typename A, typename B>
|
||||
struct has_same_size
|
||||
: std::bool_constant<
|
||||
fusion::result_of::size<std::remove_cvref_t<A>>::value ==
|
||||
fusion::result_of::size<std::remove_cvref_t<B>>::value
|
||||
>
|
||||
: mpl::bool_<(
|
||||
fusion::result_of::size<A>::value ==
|
||||
fusion::result_of::size<B>::value
|
||||
)>
|
||||
{};
|
||||
|
||||
template <typename A, typename B>
|
||||
constexpr bool has_same_size_v = has_same_size<A, B>::value;
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
struct has_size
|
||||
: std::bool_constant<fusion::result_of::size<std::remove_cvref_t<T>>::value == N>
|
||||
: mpl::bool_<(fusion::result_of::size<T>::value == N)>
|
||||
{};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
constexpr bool has_size_v = has_size<T, N>::value;
|
||||
|
||||
template <typename A, typename B>
|
||||
struct is_same_size_sequence
|
||||
: std::bool_constant<std::conjunction_v<
|
||||
fusion::traits::is_sequence<std::remove_cvref_t<A>>,
|
||||
fusion::traits::is_sequence<std::remove_cvref_t<B>>,
|
||||
has_same_size<A, B>
|
||||
>>
|
||||
: mpl::and_<
|
||||
fusion::traits::is_sequence<A>
|
||||
, fusion::traits::is_sequence<B>
|
||||
, has_same_size<A, B>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename A, typename B>
|
||||
constexpr bool is_same_size_sequence_v = is_same_size_sequence<A, B>::value;
|
||||
|
||||
template <typename Seq>
|
||||
struct is_size_one_sequence
|
||||
: std::bool_constant<std::conjunction_v<
|
||||
fusion::traits::is_sequence<std::remove_cvref_t<Seq>>,
|
||||
has_size<Seq, 1>
|
||||
>>
|
||||
: mpl::and_<
|
||||
fusion::traits::is_sequence<Seq>
|
||||
, has_size<Seq, 1>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Seq>
|
||||
constexpr bool is_size_one_sequence_v = is_size_one_sequence<Seq>::value;
|
||||
|
||||
template <typename View>
|
||||
struct is_size_one_view
|
||||
: std::bool_constant<std::conjunction_v<
|
||||
fusion::traits::is_view<std::remove_cvref_t<View>>,
|
||||
has_size<View, 1>
|
||||
>>
|
||||
: mpl::and_<
|
||||
fusion::traits::is_view<View>
|
||||
, has_size<View, 1>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename View>
|
||||
constexpr bool is_size_one_view_v = is_size_one_view<View>::value;
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -9,9 +9,9 @@
|
||||
#define BOOST_SPIRIT_X3_VARIANT_FIND_SUBSTITUTE_APR_18_2014_930AM
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
|
||||
#include <boost/mpl/find.hpp> // TODO: remove this
|
||||
#include <boost/mpl/find.hpp>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename Variant, typename T>
|
||||
struct variant_find_substitute
|
||||
@@ -19,34 +19,33 @@ namespace boost::spirit::x3::traits
|
||||
// Get the type from the Variant that can be a substitute for T.
|
||||
// If none is found, just return T
|
||||
|
||||
using variant_type = Variant;
|
||||
using types = typename variant_type::types;
|
||||
using end = typename mpl::end<types>::type;
|
||||
typedef Variant variant_type;
|
||||
typedef typename variant_type::types types;
|
||||
typedef typename mpl::end<types>::type end;
|
||||
|
||||
using iter_1 = typename mpl::find<types, T>::type;
|
||||
typedef typename mpl::find<types, T>::type iter_1;
|
||||
|
||||
using iter = typename mpl::eval_if<
|
||||
std::is_same<iter_1, end>,
|
||||
mpl::find_if<types, traits::is_substitute<T, mpl::_1> >,
|
||||
std::type_identity<iter_1>
|
||||
>::type;
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<iter_1, end>,
|
||||
mpl::find_if<types, traits::is_substitute<T, mpl::_1> >,
|
||||
mpl::identity<iter_1>
|
||||
>::type
|
||||
iter;
|
||||
|
||||
using type = typename mpl::eval_if<
|
||||
std::is_same<iter, end>,
|
||||
std::type_identity<T>,
|
||||
mpl::deref<iter>
|
||||
>::type;
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<iter, end>,
|
||||
mpl::identity<T>,
|
||||
mpl::deref<iter>
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Variant, typename T>
|
||||
using variant_find_substitute_t = typename variant_find_substitute<Variant, T>::type;
|
||||
|
||||
|
||||
template <typename Variant>
|
||||
struct variant_find_substitute<Variant, Variant>
|
||||
{
|
||||
using type = Variant;
|
||||
};
|
||||
: mpl::identity<Variant> {};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
@@ -9,49 +9,43 @@
|
||||
#define BOOST_SPIRIT_X3_VARIANT_HAS_SUBSTITUTE_APR_18_2014_925AM
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
|
||||
#include <boost/mpl/find.hpp> // TODO: remove this
|
||||
#include <boost/mpl/find.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
namespace detail
|
||||
template <typename Variant, typename T>
|
||||
struct variant_has_substitute_impl
|
||||
{
|
||||
template <typename Variant, typename T>
|
||||
struct variant_has_substitute_impl
|
||||
{
|
||||
// Find a type from the Variant that can be a substitute for T.
|
||||
// return true_ if one is found, else false_
|
||||
// Find a type from the Variant that can be a substitute for T.
|
||||
// return true_ if one is found, else false_
|
||||
|
||||
using variant_type = Variant;
|
||||
using types = typename variant_type::types;
|
||||
using end = typename mpl::end<types>::type;
|
||||
using iter_1 = typename mpl::find<types, T>::type;
|
||||
typedef Variant variant_type;
|
||||
typedef typename variant_type::types types;
|
||||
typedef typename mpl::end<types>::type end;
|
||||
|
||||
using iter = typename mpl::eval_if<
|
||||
std::is_same<iter_1, end>,
|
||||
typedef typename mpl::find<types, T>::type iter_1;
|
||||
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<iter_1, end>,
|
||||
mpl::find_if<types, traits::is_substitute<T, mpl::_1>>,
|
||||
std::type_identity<iter_1>
|
||||
>::type;
|
||||
mpl::identity<iter_1>
|
||||
>::type
|
||||
iter;
|
||||
|
||||
using type = std::bool_constant<!std::is_same_v<iter, end>>;
|
||||
};
|
||||
} // detail
|
||||
typedef mpl::not_<is_same<iter, end>> type;
|
||||
};
|
||||
|
||||
template <typename Variant, typename T>
|
||||
struct variant_has_substitute
|
||||
: detail::variant_has_substitute_impl<Variant, T>::type
|
||||
{};
|
||||
|
||||
template <typename Variant, typename T>
|
||||
constexpr bool variant_has_substitute_v = variant_has_substitute<Variant, T>::value;
|
||||
: variant_has_substitute_impl<Variant, T>::type {};
|
||||
|
||||
template <typename T>
|
||||
struct variant_has_substitute<unused_type, T> : std::true_type {};
|
||||
struct variant_has_substitute<unused_type, T> : mpl::true_ {};
|
||||
|
||||
template <typename T>
|
||||
struct variant_has_substitute<unused_type const, T> : std::true_type {};
|
||||
struct variant_has_substitute<unused_type const, T> : mpl::true_ {};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2015 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -8,18 +7,15 @@
|
||||
#if !defined(BOOST_SPIRIT_X3__ANNOTATE_ON_SUCCESS_HPP)
|
||||
#define BOOST_SPIRIT_X3__ANNOTATE_ON_SUCCESS_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/spirit/home/x3/support/ast/variant.hpp>
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/error_reporting.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/lambda_visitor.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/is_variant.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
struct error_handler_tag;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The on_success handler tags the AST with the iterator position
|
||||
// for error handling.
|
||||
//
|
||||
@@ -29,37 +25,13 @@ namespace boost::spirit::x3
|
||||
// x3/support/ast.
|
||||
//
|
||||
// We'll ask the X3's error_handler utility to do these.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct annotate_on_success
|
||||
{
|
||||
// Catch-all default overload
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename T, typename Context>
|
||||
constexpr void
|
||||
on_success(It const& first, Se const& last, T& ast, Context const& context)
|
||||
{
|
||||
auto&& error_handler_ref = x3::get<error_handler_tag>(context);
|
||||
static_assert(
|
||||
!std::is_same_v<std::remove_cvref_t<decltype(error_handler_ref)>, unused_type>,
|
||||
"This rule is derived from `x3::annotate_on_success`, but no reference was bound to "
|
||||
"`x3::error_handler_tag`. You must provide a viable error handler via `x3::with`."
|
||||
);
|
||||
|
||||
// unwrap `reference_wrapper` if neccessary
|
||||
if constexpr (requires {
|
||||
error_handler_ref.get().tag(ast, first, last);
|
||||
})
|
||||
{
|
||||
error_handler_ref.get().tag(ast, first, last);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_handler_ref.tag(ast, first, last);
|
||||
}
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename... Types, typename Context>
|
||||
constexpr void
|
||||
on_success(It const& first, Se const& last, x3::variant<Types...>& ast, Context const& context)
|
||||
template <typename Iterator, typename Context, typename... Types>
|
||||
inline void on_success(Iterator const& first, Iterator const& last
|
||||
, variant<Types...>& ast, Context const& context)
|
||||
{
|
||||
ast.apply_visitor(x3::make_lambda_visitor<void>([&](auto& node)
|
||||
{
|
||||
@@ -67,13 +39,21 @@ namespace boost::spirit::x3
|
||||
}));
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename T, typename Context>
|
||||
constexpr void
|
||||
on_success(It const& first, Se const& last, forward_ast<T>& ast, Context const& context)
|
||||
template <typename T, typename Iterator, typename Context>
|
||||
inline void on_success(Iterator const& first, Iterator const& last
|
||||
, forward_ast<T>& ast, Context const& context)
|
||||
{
|
||||
this->on_success(first, last, ast.get(), context);
|
||||
}
|
||||
|
||||
template <typename T, typename Iterator, typename Context>
|
||||
inline typename disable_if<traits::is_variant<T>>::type on_success(Iterator const& first, Iterator const& last
|
||||
, T& ast, Context const& context)
|
||||
{
|
||||
auto& error_handler = x3::get<error_handler_tag>(context).get();
|
||||
error_handler.tag(ast, first, last);
|
||||
}
|
||||
};
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2023 Nikita Kniazev
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -10,165 +9,121 @@
|
||||
#define BOOST_SPIRIT_X3_UC_TYPES_NOVEMBER_23_2008_0840PM
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
using ucs4_char = char32_t;
|
||||
using utf8_char = char;
|
||||
using ucs4_string = std::basic_string<ucs4_char>;
|
||||
using utf8_string = std::basic_string<utf8_char>;
|
||||
typedef char32_t ucs4_char;
|
||||
typedef char utf8_char;
|
||||
typedef std::basic_string<ucs4_char> ucs4_string;
|
||||
typedef std::basic_string<utf8_char> utf8_string;
|
||||
|
||||
namespace detail {
|
||||
constexpr void utf8_put_encode(utf8_string& out, ucs4_char x) noexcept
|
||||
{
|
||||
// https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf D90
|
||||
if (x > 0x10FFFFul || (0xD7FFul < x && x < 0xE000ul)) [[unlikely]]
|
||||
x = 0xFFFDul;
|
||||
namespace detail {
|
||||
inline void utf8_put_encode(utf8_string& out, ucs4_char x)
|
||||
{
|
||||
// https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf D90
|
||||
if (BOOST_UNLIKELY(x > 0x10FFFFul || (0xD7FFul < x && x < 0xE000ul)))
|
||||
x = 0xFFFDul;
|
||||
|
||||
// Table 3-6. UTF-8 Bit Distribution
|
||||
if (x < 0x80ul) {
|
||||
out.push_back(static_cast<unsigned char>(x));
|
||||
}
|
||||
else if (x < 0x800ul) {
|
||||
out.push_back(static_cast<unsigned char>(0xC0ul + (x >> 6)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
else if (x < 0x10000ul) {
|
||||
out.push_back(static_cast<unsigned char>(0xE0ul + (x >> 12)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 6) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
else {
|
||||
out.push_back(static_cast<unsigned char>(0xF0ul + (x >> 18)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 12) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 6) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
// Table 3-6. UTF-8 Bit Distribution
|
||||
if (x < 0x80ul) {
|
||||
out.push_back(static_cast<unsigned char>(x));
|
||||
}
|
||||
else if (x < 0x800ul) {
|
||||
out.push_back(static_cast<unsigned char>(0xC0ul + (x >> 6)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
else if (x < 0x10000ul) {
|
||||
out.push_back(static_cast<unsigned char>(0xE0ul + (x >> 12)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 6) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
else {
|
||||
out.push_back(static_cast<unsigned char>(0xF0ul + (x >> 18)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 12) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 6) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
[[nodiscard]] constexpr utf8_string to_utf8(Char value)
|
||||
inline utf8_string to_utf8(Char value)
|
||||
{
|
||||
utf8_string result;
|
||||
using UChar = std::make_unsigned_t<Char>;
|
||||
typedef typename std::make_unsigned<Char>::type UChar;
|
||||
detail::utf8_put_encode(result, static_cast<UChar>(value));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
[[nodiscard]] constexpr utf8_string to_utf8(Char const* str)
|
||||
inline utf8_string to_utf8(Char const* str)
|
||||
{
|
||||
utf8_string result;
|
||||
using UChar = typename std::make_unsigned<Char>::type;
|
||||
typedef typename std::make_unsigned<Char>::type UChar;
|
||||
while (*str)
|
||||
{
|
||||
detail::utf8_put_encode(result, static_cast<UChar>(*str++));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Char, typename Traits>
|
||||
[[nodiscard]] constexpr utf8_string
|
||||
to_utf8(std::basic_string_view<Char, Traits> const str)
|
||||
template <typename Char, typename Traits, typename Allocator>
|
||||
inline utf8_string
|
||||
to_utf8(std::basic_string<Char, Traits, Allocator> const& str)
|
||||
{
|
||||
utf8_string result;
|
||||
using UChar = typename std::make_unsigned<Char>::type;
|
||||
typedef typename std::make_unsigned<Char>::type UChar;
|
||||
for (Char ch : str)
|
||||
{
|
||||
detail::utf8_put_encode(result, static_cast<UChar>(ch));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Char, typename Traits>
|
||||
[[nodiscard]] constexpr utf8_string
|
||||
to_utf8(std::basic_string<Char, Traits> const& str)
|
||||
{
|
||||
utf8_string result;
|
||||
using UChar = typename std::make_unsigned<Char>::type;
|
||||
for (Char ch : str)
|
||||
{
|
||||
detail::utf8_put_encode(result, static_cast<UChar>(ch));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Assume wchar_t content is UTF-16 on MSVC, or mingw/wineg++ with -fshort-wchar
|
||||
#if defined(_MSC_VER) || defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2
|
||||
[[nodiscard]] constexpr utf8_string to_utf8(wchar_t value)
|
||||
inline utf8_string to_utf8(wchar_t value)
|
||||
{
|
||||
utf8_string result;
|
||||
detail::utf8_put_encode(result, static_cast<std::make_unsigned_t<wchar_t>>(value));
|
||||
detail::utf8_put_encode(result, static_cast<std::make_unsigned<wchar_t>::type>(value));
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <std::forward_iterator It>
|
||||
requires std::is_same_v<std::remove_const_t<std::iter_value_t<It>>, wchar_t>
|
||||
[[nodiscard]] constexpr ucs4_char decode_utf16(It& s) noexcept
|
||||
inline ucs4_char decode_utf16(wchar_t const*& s)
|
||||
{
|
||||
using uwchar_t = std::make_unsigned<wchar_t>::type;
|
||||
typedef std::make_unsigned<wchar_t>::type uwchar_t;
|
||||
|
||||
uwchar_t x(*s);
|
||||
if (x < 0xD800ul || x > 0xDFFFul)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
// expected high-surrogate
|
||||
if ((x >> 10) != 0b110110ul) [[unlikely]]
|
||||
{
|
||||
if (BOOST_UNLIKELY((x >> 10) != 0b110110ul))
|
||||
return 0xFFFDul;
|
||||
}
|
||||
|
||||
uwchar_t y(*++s);
|
||||
// expected low-surrogate
|
||||
if ((y >> 10) != 0b110111ul) [[unlikely]]
|
||||
{
|
||||
if (BOOST_UNLIKELY((y >> 10) != 0b110111ul))
|
||||
return 0xFFFDul;
|
||||
}
|
||||
|
||||
return ((x & 0x3FFul) << 10) + (y & 0x3FFul) + 0x10000ul;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
[[nodiscard]] constexpr utf8_string
|
||||
to_utf8(std::basic_string_view<wchar_t, Traits> const str)
|
||||
inline utf8_string to_utf8(wchar_t const* str)
|
||||
{
|
||||
utf8_string result;
|
||||
for (auto it = str.begin(); it != str.end(); ++it)
|
||||
{
|
||||
detail::utf8_put_encode(result, detail::decode_utf16(it));
|
||||
}
|
||||
for (ucs4_char c; (c = detail::decode_utf16(str)) != ucs4_char(); ++str)
|
||||
detail::utf8_put_encode(result, c);
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr utf8_string to_utf8(wchar_t const* str)
|
||||
template <typename Traits, typename Allocator>
|
||||
inline utf8_string
|
||||
to_utf8(std::basic_string<wchar_t, Traits, Allocator> const& str)
|
||||
{
|
||||
return x3::to_utf8(std::basic_string_view(str));
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
[[nodiscard]] constexpr utf8_string
|
||||
to_utf8(std::basic_string<wchar_t, Traits> const& str)
|
||||
{
|
||||
utf8_string result;
|
||||
for (auto it = str.begin(); it != str.end(); ++it)
|
||||
{
|
||||
detail::utf8_put_encode(result, detail::decode_utf16(it));
|
||||
}
|
||||
return result;
|
||||
return to_utf8(str.c_str());
|
||||
}
|
||||
#endif
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user