Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a7c3fedf2 | ||
|
|
e6cd3eaaec | ||
|
|
f18ce1b7d3 | ||
|
|
f8ea4ea47d | ||
|
|
e262466260 | ||
|
|
85dab53916 | ||
|
|
38a07a3304 | ||
|
|
039c189491 | ||
|
|
a3473fd7be | ||
|
|
aa02264d2f | ||
|
|
d9f431c9bd | ||
|
|
f3016baacb | ||
|
|
638c1db7fc | ||
|
|
37cfc0b63f | ||
|
|
c01efa343a | ||
|
|
4dc0a787ee | ||
|
|
9054e09967 | ||
|
|
ff18b2b5b4 | ||
|
|
769ecc83c7 | ||
|
|
87f0fb454b | ||
|
|
644a151070 | ||
|
|
e0c7d453e3 | ||
|
|
38226f2a6b | ||
|
|
1d515be714 | ||
|
|
b48833c5a7 | ||
|
|
ee88b9670a | ||
|
|
f8aa528686 | ||
|
|
552ba7e687 | ||
|
|
2251d3813a | ||
|
|
6df5cc4024 | ||
|
|
faffbd78a7 | ||
|
|
f60aedbf65 | ||
|
|
282fbc0791 | ||
|
|
bb27b0e6ef | ||
|
|
2d60c74d00 | ||
|
|
c05af363e6 | ||
|
|
ef05cd2bc0 | ||
|
|
58c71a9e3f | ||
|
|
3ec2e646fa | ||
|
|
cca31d2225 | ||
|
|
919570c46a | ||
|
|
82b704f693 | ||
|
|
a46f01e603 | ||
|
|
705e687028 | ||
|
|
99ff66bc23 | ||
|
|
2e7935e569 | ||
|
|
51d3808418 | ||
|
|
1d72fbe950 | ||
|
|
0fcedefbfb | ||
|
|
005cdc7b84 | ||
|
|
d191cd86ac | ||
|
|
d40ed35011 | ||
|
|
8727e11e85 | ||
|
|
32a757f84c | ||
|
|
1bd47e0244 | ||
|
|
87f335c560 | ||
|
|
dba7d055aa | ||
|
|
92c1a456ae | ||
|
|
f80c4995de | ||
|
|
0716f1d59b | ||
|
|
886b73af33 | ||
|
|
091df3ab02 | ||
|
|
ad2ddd249c | ||
|
|
45dbbe88b1 | ||
|
|
4c88da02c5 | ||
|
|
f081edd09e | ||
|
|
01a46937a0 | ||
|
|
0575cf7291 | ||
|
|
0ff77971aa | ||
|
|
c9eb8622c3 | ||
|
|
ed88e12e60 | ||
|
|
4131ae7244 | ||
|
|
48f2a0ca10 | ||
|
|
0c2dfbdd96 | ||
|
|
6715a02339 | ||
|
|
7a1d0aaf2d | ||
|
|
de5e439187 | ||
|
|
62c3c6a567 | ||
|
|
9df4c535e9 | ||
|
|
7a4b317288 | ||
|
|
297ee84733 | ||
|
|
92276e73a2 | ||
|
|
1501b4df45 | ||
|
|
9198728b43 | ||
|
|
d5bbfbd41d | ||
|
|
0c0d674e1d | ||
|
|
27b0008c56 | ||
|
|
01046e779c | ||
|
|
3c02670f0f | ||
|
|
59e3223d0d | ||
|
|
09161b1444 | ||
|
|
e7ffdc5574 | ||
|
|
4937938362 | ||
|
|
7e21423866 | ||
|
|
38f2d1fcd4 | ||
|
|
987e7e17c3 | ||
|
|
2c0dd72332 | ||
|
|
d308e4ed6f | ||
|
|
61af1763fd | ||
|
|
edf3cbbd3e | ||
|
|
06c85fb955 | ||
|
|
2d28bfea79 | ||
|
|
9d58618750 | ||
|
|
c38c965434 | ||
|
|
96cacc78c0 | ||
|
|
6f2801248c | ||
|
|
cbc33f36f5 | ||
|
|
41f503de5d | ||
|
|
64405f6f62 | ||
|
|
64961bf692 | ||
|
|
9fdd7fca0b | ||
|
|
eb30417eed | ||
|
|
a6220b8f4b | ||
|
|
bbb9dae8a3 | ||
|
|
53259db5e7 | ||
|
|
28bc929bb6 | ||
|
|
031ddb7bb8 | ||
|
|
8d219a6b27 | ||
|
|
1c244eb19b | ||
|
|
c74080e656 | ||
|
|
cba165c27b | ||
|
|
e73b93f61f | ||
|
|
8011459a1e | ||
|
|
6695fcd3af | ||
|
|
5ac98bc208 | ||
|
|
48e83fcaab | ||
|
|
7c6b5c955e | ||
|
|
68e1ab7160 | ||
|
|
8920ef895b | ||
|
|
73dc6295a7 | ||
|
|
6d7c3cbb47 | ||
|
|
072d49e59c | ||
|
|
eb8720d5ea | ||
|
|
b90b78c79c | ||
|
|
6b434e934c | ||
|
|
15376f4393 | ||
|
|
dff1b6cd36 |
@@ -41,7 +41,7 @@ jobs:
|
||||
python-version: '3.8'
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
@@ -71,6 +71,7 @@ jobs:
|
||||
-G "Unix Makefiles" \
|
||||
-DRE2C_BUILD_LIBS=ON \
|
||||
-DRE2C_BUILD_RE2GO=OFF \
|
||||
-DRE2C_BUILD_RE2RUST=OFF \
|
||||
-DRE2C_BUILD_BENCHMARKS=ON \
|
||||
-DCMAKE_CXX_FLAGS="-O3"
|
||||
|
||||
|
||||
+25
-142
@@ -24,89 +24,38 @@ jobs:
|
||||
# Linux
|
||||
- name: linux-gcc-ubsan-ootree
|
||||
os: ubuntu-latest
|
||||
generator: Unix Makefiles
|
||||
build-type: Ubsan
|
||||
build-dir: .build
|
||||
cxx-flags: -O2
|
||||
skeleton: ${{ false }}
|
||||
|
||||
- name: linux-gcc-asan-ootree
|
||||
os: ubuntu-latest
|
||||
generator: Unix Makefiles
|
||||
build-type: Asan
|
||||
build-dir: .build
|
||||
cxx-flags: -O2
|
||||
skeleton: ${{ false }}
|
||||
|
||||
- name: linux-gcc-debug-ootree-skeleton
|
||||
os: ubuntu-latest
|
||||
generator: Unix Makefiles
|
||||
build-type: Debug
|
||||
build-dir: .build
|
||||
cxx-flags: -O2
|
||||
skeleton: ${{ true }}
|
||||
|
||||
- name: linux-gcc-debug-intree-m32-skeleton
|
||||
os: ubuntu-latest
|
||||
generator: Unix Makefiles
|
||||
build-type: Debug
|
||||
build-dir: .
|
||||
cxx-flags: -O2 -m32
|
||||
ld-flags: -m32
|
||||
skeleton: ${{ true }}
|
||||
|
||||
- name: linux-gcc-release-ootree-skeleton
|
||||
os: ubuntu-latest
|
||||
generator: Unix Makefiles
|
||||
build-type: Release
|
||||
build-dir: .build
|
||||
skeleton: ${{ true }}
|
||||
|
||||
# macOS
|
||||
- name: macos-clang-debug-ootree-skeleton
|
||||
os: macos-latest
|
||||
generator: Unix Makefiles
|
||||
build-type: Debug
|
||||
build-dir: .build
|
||||
cxx-flags: -O2
|
||||
skeleton: ${{ true }}
|
||||
|
||||
- name: macos-clang-debug-intree-skeleton
|
||||
os: macos-latest
|
||||
generator: Unix Makefiles
|
||||
build-type: Debug
|
||||
build-dir: .
|
||||
cxx-flags: -O2
|
||||
skeleton: ${{ true }}
|
||||
|
||||
- name: macos-clang-release-ootree-skeleton
|
||||
os: macos-latest
|
||||
generator: Unix Makefiles
|
||||
build-type: Release
|
||||
build-dir: .build
|
||||
skeleton: ${{ true }}
|
||||
|
||||
# Windows
|
||||
- name: windows-msvc-debug-ootree
|
||||
os: windows-latest
|
||||
generator: Visual Studio 16 2019
|
||||
build-type: Debug
|
||||
build-dir: .build
|
||||
skeleton: ${{ false }}
|
||||
|
||||
- name: windows-msvc-debug-intree
|
||||
os: windows-latest
|
||||
generator: Visual Studio 16 2019
|
||||
build-type: Debug
|
||||
build-dir: .
|
||||
skeleton: ${{ false }}
|
||||
|
||||
- name: windows-msvc-release-ootree
|
||||
os: windows-latest
|
||||
generator: Visual Studio 16 2019
|
||||
build-type: Release
|
||||
build-dir: .build
|
||||
skeleton: ${{ false }}
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
@@ -127,16 +76,10 @@ jobs:
|
||||
case ${{ runner.os }} in
|
||||
Linux*)
|
||||
sudo apt install gcc-multilib g++-multilib # for -m32
|
||||
echo "CC=gcc" >> $GITHUB_ENV
|
||||
echo "CXX=g++" >> $GITHUB_ENV
|
||||
;;
|
||||
macOS*)
|
||||
sudo xcode-select -switch /Applications/Xcode.app
|
||||
|
||||
echo "CC=$(xcrun -f clang)" >> $GITHUB_ENV
|
||||
echo "CXX=$(xcrun -f clang++)" >> $GITHUB_ENV
|
||||
echo "SDKROOT=$(xcodebuild -version -sdk macosx Path)" >> $GITHUB_ENV
|
||||
|
||||
echo "$(xcodebuild -version -sdk macosx Path)" >> $GITHUB_PATH
|
||||
;;
|
||||
Windows*)
|
||||
@@ -158,108 +101,48 @@ jobs:
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install docutils pygments
|
||||
|
||||
- name: Prepare Configure Command
|
||||
id: configure-command
|
||||
run: |
|
||||
# Common CMake arguments
|
||||
args=( -S . -B ${{ matrix.build-dir }} )
|
||||
|
||||
# Generator's specific stuff.
|
||||
args+=( -G "${{ matrix.generator }}" )
|
||||
case "${{ matrix.generator }}" in
|
||||
'Visual Studio'*)
|
||||
args+=( -A x64 )
|
||||
;;
|
||||
*)
|
||||
# CMAKE_BUILD_TYPE is not used by multi-config build
|
||||
# types (e.g Visual Studio) at the configure time
|
||||
# thus we add it only for single-config build types
|
||||
args+=( -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} )
|
||||
;;
|
||||
esac
|
||||
|
||||
# CFLAGS, CXXFLAGS, LDFLAGS
|
||||
args+=( -DCMAKE_C_FLAGS="${{ matrix.cxx-flags }}" )
|
||||
args+=( -DCMAKE_CXX_FLAGS="${{ matrix.cxx-flags }}" )
|
||||
args+=( -DCMAKE_EXE_LINKER_FLAGS="${{ matrix.ld-flags }}" )
|
||||
args+=( -DCMAKE_SHARED_LINKER_FLAGS="${{ matrix.ld-flags }}" )
|
||||
|
||||
# Quote each argument to prevent word split.
|
||||
echo "::set-output name=cmake::$(printf " '%s'" "${args[@]}")"
|
||||
- name: Check Available Configure Presets
|
||||
run: cmake --list-presets
|
||||
|
||||
- name: Fast Configure
|
||||
run: |
|
||||
# Read prepared command into an array
|
||||
args=( ${{ steps.configure-command.outputs.cmake }} )
|
||||
|
||||
# Amend Build Options
|
||||
args+=( -DCMAKE_INSTALL_PREFIX="$(pwd)/install" )
|
||||
|
||||
# Disable some defaults for now to speed up the build as
|
||||
# they are not necessary in a minimal installation
|
||||
args+=( -DRE2C_BUILD_RE2GO=OFF )
|
||||
|
||||
# Print the resulting command line for debugging purposes
|
||||
printf "cmake" && printf " '%s'" "${args[@]}" && printf "\n"
|
||||
|
||||
# Run CMake, pass quoted arguments to prevent word split.
|
||||
printf " '%s'" "${args[@]}" | xargs cmake
|
||||
run: cmake --preset=${{ matrix.name }}-fast
|
||||
|
||||
- name: Fast Build
|
||||
run: cmake --build ${{ matrix.build-dir }} --config ${{ matrix.build-type }}
|
||||
run: cmake --build --preset=${{ matrix.name }}-fast
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
cmake --build ${{ matrix.build-dir }} --config ${{ matrix.build-type }} --target install
|
||||
echo -e "Install tree:\n$(find install | sed 's/^/-- /')"
|
||||
run: cmake --build --preset=${{ matrix.name }}-fast --target install
|
||||
|
||||
- name: Minimal Install Test
|
||||
working-directory: ./install/bin
|
||||
run: ./re2c --version
|
||||
|
||||
- name: Full Configure
|
||||
run: cmake --preset=${{ matrix.name }}-full
|
||||
|
||||
- name: Get build dir
|
||||
id: build-info
|
||||
run: |
|
||||
# Read prepared command into an array
|
||||
args=( ${{ steps.configure-command.outputs.cmake }} )
|
||||
|
||||
# Amend Build Options
|
||||
args+=( -DCMAKE_INSTALL_PREFIX="$(pwd)/install-2" -DRE2C_BUILD_RE2GO=ON -DRE2C_BUILD_LIBS=ON )
|
||||
args+=( -DRE2C_REBUILD_LEXERS=ON -DRE2C_FOR_BUILD="$(pwd)/install/bin/re2c" )
|
||||
|
||||
# Windows does not have a native 'man' and 'sed' commands.
|
||||
# Disabled until this https://github.com/skvadrik/re2c/issues/327
|
||||
# will be implemented
|
||||
case ${{ runner.os }} in
|
||||
Windows*)
|
||||
args+=( -DRE2C_REBUILD_DOCS=OFF )
|
||||
;;
|
||||
*)
|
||||
args+=( -DRE2C_REBUILD_DOCS=ON )
|
||||
;;
|
||||
esac
|
||||
|
||||
# Print the resulting command line for debugging purposes
|
||||
printf "cmake" && printf " '%s'" "${args[@]}" && printf "\n"
|
||||
|
||||
# Run CMake, pass quoted arguments to prevent word split.
|
||||
printf " '%s'" "${args[@]}" | xargs cmake
|
||||
if echo "${{ matrix.name }}" | grep -q "ootree"; then
|
||||
BUILD_DIR="$(pwd)/.build/${{ matrix.name }}-full"
|
||||
else
|
||||
BUILD_DIR="$(pwd)"
|
||||
fi
|
||||
echo "::set-output name=BUILD_DIR::$BUILD_DIR"
|
||||
|
||||
- name: Full Build
|
||||
run: |
|
||||
find src -name '*.re' | xargs touch
|
||||
cmake --build ${{ matrix.build-dir }} --config ${{ matrix.build-type }}
|
||||
cmake --build --preset=${{ matrix.name }}-full
|
||||
|
||||
- name: Test
|
||||
- name: Run Main Test Suite
|
||||
run: cmake --build --preset=${{ matrix.name }}-full --target tests
|
||||
|
||||
- name: Run Skeleton Tests
|
||||
if: "contains(matrix.name, 'skeleton')"
|
||||
# Remove the following line after fix Windows tests
|
||||
working-directory: ${{ matrix.build-dir }}
|
||||
run: |
|
||||
# main test suite
|
||||
cmake --build . --target check
|
||||
|
||||
# skeleton tests (if enabled)
|
||||
if [[ "x${{ matrix.skeleton }}" == "xtrue" ]] ; then
|
||||
python run_tests.py --skeleton
|
||||
fi
|
||||
working-directory: ${{ steps.build-info.outputs.BUILD_DIR }}
|
||||
run: python run_tests.py --skeleton
|
||||
|
||||
- name: Archive test artifacts
|
||||
# Run this step only if tests failed (otherwise there is nothing to upload).
|
||||
@@ -270,7 +153,7 @@ jobs:
|
||||
# use a different name per job.
|
||||
name: test-${{ matrix.name }}
|
||||
# Tests run in a temporary directory that has a name test_<timestamp>.
|
||||
path: ${{ matrix.build-dir }}/test_[0-9]*
|
||||
path: ${{ steps.build-info.outputs.BUILD_DIR }}/test_[0-9]*
|
||||
# Artifacts are retained for 90 days by default.
|
||||
# In fact we don't need such long period.
|
||||
# In fact, we don't need such long period.
|
||||
retention-days: 30
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
/test_*
|
||||
/.build*
|
||||
|
||||
# Ignore user defined CMake presets
|
||||
CMakeUserPresets.json
|
||||
|
||||
# The files autogenerated by automake.
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
|
||||
@@ -2,27 +2,23 @@ How to build
|
||||
============
|
||||
|
||||
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
To build re2c from a release tarball one needs only a C++ compiler and
|
||||
optionally Python 3 to run the tests.
|
||||
|
||||
To develop re2c one also needs CMake or Autotools. Re2c can be built with either
|
||||
of the two build systems, and they are both maintained and tested on CI. Other
|
||||
build dependencies include Bison (to rebuild parsers), rst2man (to rebuild
|
||||
documentation), Sphinx (to rebuild the website), and optionally Mingw and Wine
|
||||
(to run Windows tests on Linux). A few helper scripts are written in Haskell,
|
||||
but they are not essential for re2c development.
|
||||
To develop re2c one also needs CMake or Autotools (both build systems are
|
||||
maintained). Other dependencies include Bison (to rebuild parsers), rst2man (to
|
||||
rebuild documentation) and Sphinx (to rebuild the website). Benchmarks also use
|
||||
google-benchmark, re2 and Java. A few helper scripts are written in Haskell, but
|
||||
they are not essential for re2c development.
|
||||
|
||||
Re2c is a self-hosting lexer generator, meaning that parts of its source code
|
||||
re2c is a self-hosting lexer generator, meaning that parts of its source code
|
||||
are written in re2c (namely, all the source files that have a *.re* extension).
|
||||
By default re2c builds from pregenerated bootstrap files. To regenerate these
|
||||
files it is necessary to configure re2c in a special way and provide a path to
|
||||
an existing re2c binary (see the details below). Normally this is not necessary,
|
||||
and the pregenerated files can be used as long as the *.re* files are unchanged.
|
||||
|
||||
By default re2c builds from pre-generated bootstrap files. To build from source
|
||||
*.re* files, it is necessary to reconfigure the build and provide a path to an
|
||||
existing re2c binary that will be used for bootstrap (see the details below).
|
||||
|
||||
|
||||
Build (Autotools)
|
||||
@@ -51,6 +47,9 @@ The configure script has many options (to see them all, run
|
||||
* `--enable-golang`
|
||||
Build re2go (identical to `re2c --lang go`). This is on by default.
|
||||
|
||||
* `--enable-rust`
|
||||
Build re2rust (identical to `re2c --lang rust`). This is on by default.
|
||||
|
||||
* `--enable-lexers`
|
||||
Enable regeneration of *.re* files (as opposed to using bootstrap files).
|
||||
This requires setting `RE2C_FOR_BUILD` to an existing re2c executable
|
||||
@@ -64,7 +63,7 @@ The configure script has many options (to see them all, run
|
||||
|
||||
* `--enable-benchmarks-regenerate`
|
||||
Regenerate C code for Ragel and Kleenex benchmarks (this will download and
|
||||
build Ragel and Kleenex). Re2c benchmarks are always regenerated.
|
||||
build Ragel and Kleenex). re2c benchmarks are always regenerated.
|
||||
|
||||
* `--enable-libs`
|
||||
Build the experimental libre2c library that provides POSIX
|
||||
@@ -82,7 +81,6 @@ There is a bunch of build scripts for specialized builds with Asan, Ubsan,
|
||||
GLIBCXX_DEBUG, etc. in the ``build`` subdirectory.
|
||||
|
||||
|
||||
|
||||
Build (CMake)
|
||||
-------------
|
||||
|
||||
@@ -130,6 +128,10 @@ specific to re2c:
|
||||
* `-DRE2C_BUILD_RE2GO=yes`
|
||||
Build re2go executable (an alias to `re2c --lang go`). Enabled by default.
|
||||
|
||||
* `-DRE2C_BUILD_RE2RUST=yes`
|
||||
Build re2rust executable (an alias to `re2c --lang rust`). Enabled by
|
||||
default.
|
||||
|
||||
* `-DRE2C_REBUILD_LEXERS=yes`
|
||||
Enable regeneration of *.re* files (as opposed to using bootstrap files).
|
||||
This requires setting `-DRE2C_FOR_BUILD` to an existing re2c executable
|
||||
@@ -143,7 +145,7 @@ specific to re2c:
|
||||
|
||||
* `-DRE2C_REGEN_BENCHMARKS=yes`
|
||||
Regenerate C code for Ragel and Kleenex benchmarks (this will download and
|
||||
build Ragel and Kleenex). Re2c benchmarks are always regenerated.
|
||||
build Ragel and Kleenex). re2c benchmarks are always regenerated.
|
||||
|
||||
* `-DRE2C_BUILD_LIBS=yes`
|
||||
Build the experimental libre2c library that provides POSIX
|
||||
@@ -161,11 +163,10 @@ There is a bunch of build scripts for specialized builds with Asan, Ubsan,
|
||||
GLIBCXX_DEBUG, etc. in the ``build`` subdirectory.
|
||||
|
||||
|
||||
|
||||
Test
|
||||
----
|
||||
|
||||
Re2c has a main test suite and a number of unit tests. Run them all:
|
||||
re2c has a main test suite and a number of unit tests. Run them all:
|
||||
```
|
||||
$ make check
|
||||
```
|
||||
@@ -190,9 +191,9 @@ Check the distribution (works with Autotools):
|
||||
$ make distcheck
|
||||
```
|
||||
|
||||
Re2c provides a helper script `build/__alltest.sh` that builds and tests
|
||||
various re2c build flavours with Asan, Ubsan, GLIBCXX_DEBUG, etc. There is a
|
||||
couple of fuzz-testing Haskell scripts in the *fuzz* subdirectory; they are
|
||||
based on the QuickCheck library and can be easily modified to fuzz-test various
|
||||
aspects of re2c by comparing current re2c version against older versions or
|
||||
against other regular expression libraries.
|
||||
re2c provides a helper script `build/__alltest.sh` that builds and tests various
|
||||
re2c build flavours with Asan, Ubsan, GLIBCXX_DEBUG, etc. There is a couple of
|
||||
fuzz-testing Haskell scripts in the *fuzz* subdirectory; they are based on the
|
||||
QuickCheck library and can be easily modified to fuzz-test various aspects of
|
||||
re2c by comparing current re2c version against older versions or against other
|
||||
regular expression libraries.
|
||||
|
||||
@@ -1,6 +1,118 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
|
||||
----
|
||||
3.0x
|
||||
----
|
||||
|
||||
3.0 (2022-01-27)
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
- Added code generation backend for Rust:
|
||||
|
||||
+ Enabled with ``--lang rust`` option.
|
||||
+ A new ``re2rust`` binary (built by default, or configured with
|
||||
``--enable-rust`` Autoconf option and ``RE2C_BUILD_RE2RUST`` CMake option).
|
||||
|
||||
- Added options:
|
||||
|
||||
+ ``--loop-switch``
|
||||
+ ``--no-unsafe``
|
||||
|
||||
- Added configurations;
|
||||
|
||||
+ ``re2c:label:yyloop``
|
||||
+ ``re2c:unsafe``
|
||||
|
||||
- Renamed options to use common naming scheme. The old names are supported as
|
||||
aliases, so the change does not break existing code. Documentation has been
|
||||
updated to use new names.
|
||||
|
||||
+ ``--api`` is a new alias for ``--input``
|
||||
+ ``--ebcdic`` is a new alias for ``--ecb``
|
||||
+ ``--ucs2`` is a new alias for ``--wide-chars``
|
||||
+ ``--utf32`` is a new alias for ``--unicode``
|
||||
+ ``--utf16`` is a new alias for ``--utf-16``
|
||||
+ ``--utf8`` is a new alias for ``--utf-8``
|
||||
+ ``--header`` is a new alias for ``--type-header``
|
||||
|
||||
- Renamed configurations to use common naming scheme and support proper scoping
|
||||
under subcategories such as ``:define``, ``:label``, ``:variable``, etc. The
|
||||
old names are supported as aliases, so the change does not break existing
|
||||
code. Documentation has been updated to use new names.
|
||||
|
||||
+ ``re2c:api`` is a new alias for ``re2c:flags:input``
|
||||
+ ``re2c:bit-vectors`` is a new alias for ``re2c:flags:bit-vectors``
|
||||
+ ``re2c:case-insensitive`` is a new alias for ``re2c:flags:case-insensitive``
|
||||
+ ``re2c:case-inverted`` is a new alias for ``re2c:flags:case-inverted``
|
||||
+ ``re2c:case-ranges`` is a new alias for ``re2c:flags:case-ranges``
|
||||
+ ``re2c:cond:prefix`` is a new alias for ``re2c:condprefix``
|
||||
+ ``re2c:cond:enumprefix`` is a new alias for ``re2c:condenumprefix``
|
||||
+ ``re2c:computed-gotos`` is a new alias for ``re2c:flags:computed-gotos``
|
||||
+ ``re2c:computed-gotos:threshold`` is a new alias for ``re2c:cgoto:threshold``
|
||||
+ ``re2c:debug-output`` is a new alias for ``re2c:flags:debug-output``
|
||||
+ ``re2c:encoding:ebcdic`` is a new alias for ``re2c:flags:ecb``
|
||||
+ ``re2c:encoding:utf32`` is a new alias for ``re2c:flags:unicode``
|
||||
+ ``re2c:encoding:ucs2`` is a new alias for ``re2c:flags:wide-chars``
|
||||
+ ``re2c:encoding:utf16`` is a new alias for ``re2c:flags:utf-16``
|
||||
+ ``re2c:encoding:utf8`` is a new alias for ``re2c:flags:utf-8``
|
||||
+ ``re2c:encoding-policy`` is a new alias for ``re2c:flags:encoding-policy``
|
||||
+ ``re2c:empty-class`` is a new alias for ``re2c:flags:empty-class``
|
||||
+ ``re2c:header`` is a new alias for ``re2c:flags:type-header``
|
||||
+ ``re2c:label:prefix`` is a new alias for ``re2c:labelprefix``
|
||||
+ ``re2c:label:yyfill`` is a new alias for ``re2c:label:yyFillLabel``
|
||||
+ ``re2c:label:start`` is a new alias for ``re2c:startlabel``
|
||||
+ ``re2c:nested-ifs`` is a new alias for ``re2c:flags:nested-ifs``
|
||||
+ ``re2c:posix-captures`` is a new alias for ``re2c:flags:posix-captures``
|
||||
+ ``re2c:tags`` is a new alias for ``re2c:flags:tags``
|
||||
+ ``re2c:variable:yych:conversion`` is a new alias for ``re2c:yych:conversion``
|
||||
+ ``re2c:variable:yych:emit`` is a new alias for ``re2c:yych:emit``
|
||||
+ ``re2c:variable:yybm:hex`` is a new alias for ``re2c:yybm:hex``
|
||||
+ ``re2c:unsafe`` is a new alias for ``re2c:flags:unsafe``
|
||||
|
||||
- Added directive alias ``conditions:re2c`` for ``types:re2c``.
|
||||
|
||||
- Multiple small changes in code generation, including some formatting changes
|
||||
that result in large diffs in the generated code:
|
||||
|
||||
+ Do not allocate indices for unused state labels (this results in a change in
|
||||
state enumeration), commits
|
||||
`919570c4 <https://github.com/skvadrik/re2c/commit/919570c4>`_ and
|
||||
`82b704f6 <https://github.com/skvadrik/re2c/commit/82b704f6>`_.
|
||||
+ Do not generate redundant ``YYPEEK`` statements, commit
|
||||
`cca31d22 <https://github.com/skvadrik/re2c/commit/cca31d22>`_.
|
||||
+ Do not generate ``YYDEBUG`` statements for unused states labels, commit
|
||||
`a46f01e6 <https://github.com/skvadrik/re2c/commit/a46f01e6>`_.
|
||||
+ C backend: change formatting of switch statements, commit
|
||||
`ed88e12e <https://github.com/skvadrik/re2c/commit/ed88e12e>`_.
|
||||
+ Go backend: render continuous character ranges in compact form, commit
|
||||
`09161b14 <https://github.com/skvadrik/re2c/commit/09161b14>`_.
|
||||
+ Mark start and end of included .re files with line directives, commit
|
||||
`48e83fca <https://github.com/skvadrik/re2c/commit/48e83fca>`_.
|
||||
|
||||
- A fix to limit maximum allowed NFA and DFA size (to avoid out of memory
|
||||
crashes and stack overflows), commit
|
||||
`a3473fd7 <https://github.com/skvadrik/re2c/commit/a3473fd7>`_.
|
||||
|
||||
- A fix to correctly compute fixed tags in trailing context, commit
|
||||
`68e1ab71 <https://github.com/skvadrik/re2c/commit/68e1ab71>`_.
|
||||
|
||||
- A fix to generate non-overlapping names for s-tag and m-tag variables, commit
|
||||
`7c6b5c95 <https://github.com/skvadrik/re2c/commit/7c6b5c95>`_.
|
||||
|
||||
- Infrastructural: added support for CMake presets.
|
||||
|
||||
- Updated documentation.
|
||||
|
||||
- Backwards-incompatible changes that are unlikely to affect any users:
|
||||
|
||||
+ Restrict lexical contexts where ``%{`` is recognized as a block start,
|
||||
commit `dba7d055 <https://github.com/skvadrik/re2c/commit/dba7d055>`_.
|
||||
+ Emit an error when repetition lower bound exceeds upper bound, commit
|
||||
`039c1894 <https://github.com/skvadrik/re2c/commit/039c1894>`_.
|
||||
|
||||
|
||||
----
|
||||
2.2x
|
||||
----
|
||||
|
||||
+49
-6
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project(re2c VERSION 2.2 HOMEPAGE_URL "https://re2c.org/")
|
||||
project(re2c VERSION 3.0 HOMEPAGE_URL "https://re2c.org/")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
@@ -42,6 +42,7 @@ endif()
|
||||
option(RE2C_BUILD_LIBS "Build libraries" OFF)
|
||||
|
||||
option(RE2C_BUILD_RE2GO "Build re2go executable (an alias for `re2c --lang go`)" ON)
|
||||
option(RE2C_BUILD_RE2RUST "Build re2rust executable (an alias for `re2c --lang rust`)" ON)
|
||||
|
||||
option(RE2C_BUILD_BENCHMARKS "Build benchmarks" OFF)
|
||||
option(RE2C_REGEN_BENCHMARKS "Regenerate C code for benchmarks" OFF)
|
||||
@@ -145,6 +146,7 @@ set(re2c_sources
|
||||
src/codegen/gen_program.cc
|
||||
src/codegen/gen_state.cc
|
||||
src/codegen/helpers.cc
|
||||
src/codegen/remove_empty.cc
|
||||
src/codegen/render.cc
|
||||
src/options/opt.cc
|
||||
src/options/symtab.cc
|
||||
@@ -223,6 +225,12 @@ if (RE2C_BUILD_RE2GO)
|
||||
target_compile_definitions(re2go PUBLIC "RE2C_LANG=LANG_GO")
|
||||
endif()
|
||||
|
||||
# re2rust
|
||||
if (RE2C_BUILD_RE2RUST)
|
||||
add_executable(re2rust ${re2c_sources})
|
||||
target_compile_definitions(re2rust PUBLIC "RE2C_LANG=LANG_RUST")
|
||||
endif()
|
||||
|
||||
re2c_bootstrap_lexer("src/parse/lex.re" "src/parse/lex.cc" "src/parse/lex.h")
|
||||
re2c_bootstrap_lexer("src/parse/lex_conf.re" "src/parse/lex_conf.cc")
|
||||
re2c_bootstrap_lexer("src/options/parse_opts.re" "src/options/parse_opts.cc")
|
||||
@@ -233,6 +241,7 @@ re2c_bootstrap_parser("src/parse/parser.ypp" "src/parse/parser.cc" "src/parse/pa
|
||||
set(re2c_docs_sources
|
||||
"${re2c_manpage_source}"
|
||||
"doc/manual/api/interface.rst_"
|
||||
"doc/manual/conditions/blocks.rst_"
|
||||
"doc/manual/conditions/conditions.rst_"
|
||||
"doc/manual/configurations/configurations.rst_"
|
||||
"doc/manual/directives/directives.rst_"
|
||||
@@ -257,17 +266,22 @@ set(re2c_docs_sources
|
||||
"doc/manual/state/state.rst_"
|
||||
"doc/manual/submatch/submatch_example_mtags.rst_"
|
||||
"doc/manual/submatch/submatch_example_posix.rst_"
|
||||
"doc/manual/submatch/submatch_example_stags.rst_"
|
||||
"doc/manual/submatch/submatch_example_stags_fill.rst_"
|
||||
"doc/manual/submatch/submatch_example_stags.rst_"
|
||||
"doc/manual/submatch/submatch.rst_"
|
||||
"doc/manual/syntax/syntax.rst_"
|
||||
"doc/manual/synopsis.rst_"
|
||||
"doc/manual/syntax/api1.rst_"
|
||||
"doc/manual/syntax/api2_c.rst_"
|
||||
"doc/manual/syntax/api2_go.rst_"
|
||||
"doc/manual/syntax/api2_rust.rst_"
|
||||
"doc/manual/syntax/api3.rst_"
|
||||
"doc/manual/syntax/intro.rst_"
|
||||
"doc/manual/syntax/syntax.rst_"
|
||||
"doc/manual/warnings/warnings_general.rst_"
|
||||
"doc/manual/warnings/warnings_list.rst_"
|
||||
"examples/c/01_basic.re"
|
||||
"examples/c/01_basic.c"
|
||||
"examples/c/conditions/parse_u32_blocks.re"
|
||||
"examples/c/conditions/parse_u32_conditions.re"
|
||||
"examples/c/encodings/unicode_identifier.re"
|
||||
"examples/c/eof/01_sentinel.re"
|
||||
@@ -277,17 +291,19 @@ set(re2c_docs_sources
|
||||
"examples/c/fill/01_fill.re"
|
||||
"examples/c/fill/02_fill.re"
|
||||
"examples/c/headers/header.re"
|
||||
"examples/c/headers/src/lexer/lexer.h"
|
||||
"examples/c/headers/lexer/state.h"
|
||||
"examples/c/includes/include.re"
|
||||
"examples/c/includes/definitions.h"
|
||||
"examples/c/reuse/reuse.re"
|
||||
"examples/c/reuse/usedir.re"
|
||||
"examples/c/state/push.re"
|
||||
"examples/c/submatch/01_stags.re"
|
||||
"examples/c/submatch/01_stags_fill.re"
|
||||
"examples/c/submatch/01_stags.re"
|
||||
"examples/c/submatch/02_mtags.re"
|
||||
"examples/c/submatch/03_posix.re"
|
||||
"examples/go/01_basic.re"
|
||||
"examples/go/01_basic.go"
|
||||
"examples/go/conditions/parse_u32_blocks.re"
|
||||
"examples/go/conditions/parse_u32_conditions.re"
|
||||
"examples/go/encodings/unicode_identifier.re"
|
||||
"examples/go/eof/01_sentinel.re"
|
||||
@@ -297,15 +313,38 @@ set(re2c_docs_sources
|
||||
"examples/go/fill/01_fill.re"
|
||||
"examples/go/fill/02_fill.re"
|
||||
"examples/go/headers/header.re"
|
||||
"examples/go/headers/src/lexer/lexer.go"
|
||||
"examples/go/headers/lexer/state.go"
|
||||
"examples/go/includes/include.re"
|
||||
"examples/go/includes/definitions.go"
|
||||
"examples/go/reuse/reuse.re"
|
||||
"examples/go/reuse/usedir.re"
|
||||
"examples/go/state/push.re"
|
||||
"examples/go/submatch/01_stags_fill.re"
|
||||
"examples/go/submatch/01_stags.re"
|
||||
"examples/go/submatch/02_mtags.re"
|
||||
"examples/go/submatch/03_posix.re"
|
||||
"examples/rust/01_basic.re"
|
||||
"examples/rust/01_basic.rs"
|
||||
"examples/rust/conditions/parse_u32_blocks.re"
|
||||
"examples/rust/conditions/parse_u32_conditions.re"
|
||||
"examples/rust/encodings/unicode_identifier.re"
|
||||
"examples/rust/eof/01_sentinel.re"
|
||||
"examples/rust/eof/02_bounds_checking.re"
|
||||
"examples/rust/eof/03_eof_rule.re"
|
||||
"examples/rust/eof/05_generic_api_eof_rule.re"
|
||||
"examples/rust/fill/01_fill.re"
|
||||
"examples/rust/fill/02_fill.re"
|
||||
"examples/rust/headers/header.re"
|
||||
"examples/rust/headers/lexer/state.rs"
|
||||
"examples/rust/includes/include.re"
|
||||
"examples/rust/includes/definitions.rs"
|
||||
"examples/rust/reuse/reuse.re"
|
||||
"examples/rust/reuse/usedir.re"
|
||||
"examples/rust/state/push.re"
|
||||
"examples/rust/submatch/01_stags_fill.re"
|
||||
"examples/rust/submatch/01_stags.re"
|
||||
"examples/rust/submatch/02_mtags.re"
|
||||
"examples/rust/submatch/03_posix.re"
|
||||
)
|
||||
re2c_gen_manpage("${re2c_manpage_source}" "${re2c_manpage_c}" "${re2c_manpage_bootstrap_c}" "c")
|
||||
re2c_gen_manpage("${re2c_manpage_source}" "${re2c_manpage_go}" "${re2c_manpage_bootstrap_go}" "go")
|
||||
@@ -321,6 +360,10 @@ if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||
install(TARGETS re2go RUNTIME DESTINATION bin)
|
||||
install(FILES "${re2c_manpage_go}" DESTINATION "share/man/man1")
|
||||
endif()
|
||||
if(RE2C_BUILD_RE2RUST)
|
||||
install(TARGETS re2rust RUNTIME DESTINATION bin)
|
||||
# TODO: add docs for Rust.
|
||||
endif()
|
||||
install(FILES include/unicode_categories.re DESTINATION "${RE2C_STDLIB_DIR}")
|
||||
|
||||
# rebuild all re2c sources using newly built re2c
|
||||
|
||||
@@ -0,0 +1,483 @@
|
||||
{
|
||||
"version": 3,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 21,
|
||||
"patch": 1
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "default-full-configuration",
|
||||
"hidden": true,
|
||||
"installDir": "${sourceDir}/install-2",
|
||||
"cacheVariables": {
|
||||
"RE2C_BUILD_RE2GO": true,
|
||||
"RE2C_BUILD_RE2RUST": true,
|
||||
"RE2C_BUILD_LIBS": true,
|
||||
"RE2C_REBUILD_LEXERS": true,
|
||||
"RE2C_REBUILD_DOCS": true,
|
||||
"RE2C_FOR_BUILD": "${sourceDir}/install/bin/re2c"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "linux-config-base",
|
||||
"hidden": true,
|
||||
"generator": "Unix Makefiles",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
},
|
||||
"architecture": {
|
||||
"value": "x64",
|
||||
"strategy": "external"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "gcc",
|
||||
"CMAKE_CXX_COMPILER": "g++"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-ubsan-ootree-fast",
|
||||
"displayName": "Linux x86_64: GCC / Ubsan / Out of tree (fast)",
|
||||
"inherits": "linux-config-base",
|
||||
"binaryDir": "${sourceDir}/.build/${presetName}",
|
||||
"installDir": "${sourceDir}/install",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Ubsan",
|
||||
"CMAKE_C_FLAGS": "-O2",
|
||||
"CMAKE_CXX_FLAGS": "-O2",
|
||||
"RE2C_BUILD_RE2GO": false,
|
||||
"RE2C_BUILD_RE2RUST": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-ubsan-ootree-full",
|
||||
"displayName": "Linux x86_64: GCC / Ubsan / Out of tree (full)",
|
||||
"inherits": ["default-full-configuration", "linux-gcc-ubsan-ootree-fast"]
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-asan-ootree-fast",
|
||||
"displayName": "Linux x86_64: GCC / Asan / Out of tree (fast)",
|
||||
"inherits": "linux-config-base",
|
||||
"binaryDir": "${sourceDir}/.build/${presetName}",
|
||||
"installDir": "${sourceDir}/install",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Asan",
|
||||
"CMAKE_C_FLAGS": "-O2",
|
||||
"CMAKE_CXX_FLAGS": "-O2",
|
||||
"RE2C_BUILD_RE2GO": false,
|
||||
"RE2C_BUILD_RE2RUST": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-asan-ootree-full",
|
||||
"displayName": "Linux x86_64: GCC / Asan / Out of tree (full)",
|
||||
"inherits": ["default-full-configuration", "linux-gcc-asan-ootree-fast"]
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-debug-ootree-skeleton-fast",
|
||||
"displayName": "Linux x86_64: GCC / Debug / Skeleton / Out of tree (fast)",
|
||||
"inherits": "linux-config-base",
|
||||
"binaryDir": "${sourceDir}/.build/${presetName}",
|
||||
"installDir": "${sourceDir}/install",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_C_FLAGS": "-O2",
|
||||
"CMAKE_CXX_FLAGS": "-O2",
|
||||
"RE2C_BUILD_RE2GO": false,
|
||||
"RE2C_BUILD_RE2RUST": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-debug-ootree-skeleton-full",
|
||||
"displayName": "Linux x86_64: GCC / Debug / Skeleton / Out of tree (full)",
|
||||
"inherits": ["default-full-configuration", "linux-gcc-debug-ootree-skeleton-fast"]
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-debug-intree-m32-skeleton-fast",
|
||||
"displayName": "Linux x86: GCC / Debug / Skeleton / In tree (fast)",
|
||||
"inherits": "linux-config-base",
|
||||
"binaryDir": "${sourceDir}",
|
||||
"installDir": "${sourceDir}/install",
|
||||
"architecture": {
|
||||
"value": "x86",
|
||||
"strategy": "external"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_C_FLAGS": "-O2 -m32",
|
||||
"CMAKE_CXX_FLAGS": "-O2 -m32",
|
||||
"CMAKE_EXE_LINKER_FLAGS": "-m32",
|
||||
"CMAKE_SHARED_LINKER_FLAGS": "-m32",
|
||||
"RE2C_BUILD_RE2GO": false,
|
||||
"RE2C_BUILD_RE2RUST": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-debug-intree-m32-skeleton-full",
|
||||
"displayName": "Linux x86: GCC / Debug / Skeleton / In tree (full)",
|
||||
"inherits": ["default-full-configuration", "linux-gcc-debug-intree-m32-skeleton-fast"]
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-release-ootree-skeleton-fast",
|
||||
"displayName": "Linux x86_64: GCC / Release / Skeleton / Out of tree (fast)",
|
||||
"inherits": "linux-config-base",
|
||||
"binaryDir": "${sourceDir}/.build/${presetName}",
|
||||
"installDir": "${sourceDir}/install",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"RE2C_BUILD_RE2GO": false,
|
||||
"RE2C_BUILD_RE2RUST": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-release-ootree-skeleton-full",
|
||||
"displayName": "Linux x86_64: GCC / Release / Skeleton / Out of tree (full)",
|
||||
"inherits": ["default-full-configuration", "linux-gcc-release-ootree-skeleton-fast"]
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"name": "macos-config-base",
|
||||
"hidden": true,
|
||||
"generator": "Unix Makefiles",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
},
|
||||
"architecture": {
|
||||
"value": "x64",
|
||||
"strategy": "external"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-clang-debug-ootree-skeleton-fast",
|
||||
"displayName": "macOS x86_64: Clang / Debug / Skeleton / Out of tree (fast)",
|
||||
"inherits": "macos-config-base",
|
||||
"binaryDir": "${sourceDir}/.build/${presetName}",
|
||||
"installDir": "${sourceDir}/install",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_C_FLAGS": "-O2",
|
||||
"CMAKE_CXX_FLAGS": "-O2",
|
||||
"RE2C_BUILD_RE2GO": false,
|
||||
"RE2C_BUILD_RE2RUST": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-clang-debug-ootree-skeleton-full",
|
||||
"displayName": "macOS x86_64: Clang / Debug / Skeleton / Out of tree (full)",
|
||||
"inherits": ["default-full-configuration", "macos-clang-debug-ootree-skeleton-fast"]
|
||||
},
|
||||
{
|
||||
"name": "macos-clang-debug-intree-skeleton-fast",
|
||||
"displayName": "macOS x86_64: Clang / Debug / Skeleton / In tree (fast)",
|
||||
"inherits": "macos-config-base",
|
||||
"binaryDir": "${sourceDir}",
|
||||
"installDir": "${sourceDir}/install",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_C_FLAGS": "-O2",
|
||||
"CMAKE_CXX_FLAGS": "-O2",
|
||||
"RE2C_BUILD_RE2GO": false,
|
||||
"RE2C_BUILD_RE2RUST": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-clang-debug-intree-skeleton-full",
|
||||
"displayName": "macOS x86_64: Clang / Debug / Skeleton / In tree (full)",
|
||||
"inherits": ["default-full-configuration", "macos-clang-debug-intree-skeleton-fast"]
|
||||
},
|
||||
{
|
||||
"name": "macos-clang-release-ootree-skeleton-fast",
|
||||
"displayName": "macOS x86_64: CLang / Release / Skeleton / Out of tree (fast)",
|
||||
"inherits": "macos-config-base",
|
||||
"binaryDir": "${sourceDir}/.build/${presetName}",
|
||||
"installDir": "${sourceDir}/install",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"RE2C_BUILD_RE2GO": false,
|
||||
"RE2C_BUILD_RE2RUST": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-clang-release-ootree-skeleton-full",
|
||||
"displayName": "macOS x86_64: CLang / Release / Skeleton / Out of tree (full)",
|
||||
"inherits": ["default-full-configuration", "macos-clang-release-ootree-skeleton-fast"]
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"name": "windows-config-base",
|
||||
"hidden": true,
|
||||
"generator": "Visual Studio 16 2019",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"architecture": {
|
||||
"value": "x64",
|
||||
"strategy": "external"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "cl",
|
||||
"CMAKE_CXX_COMPILER": "cl"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc-debug-ootree-fast",
|
||||
"displayName": "Windows x86_64: MSVC / Debug / Out of tree (fast)",
|
||||
"inherits": "windows-config-base",
|
||||
"binaryDir": "${sourceDir}/.build/${presetName}",
|
||||
"installDir": "${sourceDir}/install",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"RE2C_BUILD_RE2GO": false,
|
||||
"RE2C_BUILD_RE2RUST": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc-debug-ootree-full",
|
||||
"displayName": "Windows x86_64: MSVC / Debug / Out of tree (full)",
|
||||
"inherits": ["default-full-configuration", "windows-msvc-debug-ootree-fast"],
|
||||
"cacheVariables": {
|
||||
"RE2C_REBUILD_DOCS": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc-debug-intree-fast",
|
||||
"displayName": "Windows x86_64: MSVC / Debug / In tree (fast)",
|
||||
"inherits": "windows-config-base",
|
||||
"binaryDir": "${sourceDir}",
|
||||
"installDir": "${sourceDir}/install",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"RE2C_BUILD_RE2GO": false,
|
||||
"RE2C_BUILD_RE2RUST": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc-debug-intree-full",
|
||||
"displayName": "Windows x86_64: MSVC / Debug / In tree (full)",
|
||||
"inherits": ["default-full-configuration", "windows-msvc-debug-intree-fast"],
|
||||
"cacheVariables": {
|
||||
"RE2C_REBUILD_DOCS": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc-release-ootree-fast",
|
||||
"displayName": "Windows x86_64: MSVC / Release / Out of tree (fast)",
|
||||
"inherits": "windows-config-base",
|
||||
"binaryDir": "${sourceDir}/.build/${presetName}",
|
||||
"installDir": "${sourceDir}/install",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"RE2C_BUILD_RE2GO": false,
|
||||
"RE2C_BUILD_RE2RUST": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc-release-ootree-full",
|
||||
"displayName": "Windows x86_64: MSVC / Release / Out of tree (full)",
|
||||
"inherits": ["default-full-configuration", "windows-msvc-release-ootree-fast"],
|
||||
"cacheVariables": {
|
||||
"RE2C_REBUILD_DOCS": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "linux-build-base",
|
||||
"hidden": true,
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-ubsan-ootree-fast",
|
||||
"displayName": "Linux x86_64: GCC / Ubsan / Out of tree (fast)",
|
||||
"configurePreset": "linux-gcc-ubsan-ootree-fast",
|
||||
"inherits": "linux-build-base",
|
||||
"configuration": "Ubsan"
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-ubsan-ootree-full",
|
||||
"displayName": "Linux x86_64: GCC / Ubsan / Out of tree (full)",
|
||||
"configurePreset": "linux-gcc-ubsan-ootree-full",
|
||||
"inherits": "linux-build-base",
|
||||
"configuration": "Ubsan"
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-asan-ootree-fast",
|
||||
"displayName": "Linux x86_64: GCC / Asan / Out of tree (fast)",
|
||||
"configurePreset": "linux-gcc-asan-ootree-fast",
|
||||
"inherits": "linux-build-base",
|
||||
"configuration": "Asan"
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-asan-ootree-full",
|
||||
"displayName": "Linux x86_64: GCC / Asan / Out of tree (full)",
|
||||
"configurePreset": "linux-gcc-asan-ootree-full",
|
||||
"inherits": "linux-build-base",
|
||||
"configuration": "Asan"
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-debug-ootree-skeleton-fast",
|
||||
"displayName": "Linux x86_64: GCC / Debug / Skeleton / Out of tree (fast)",
|
||||
"configurePreset": "linux-gcc-debug-ootree-skeleton-fast",
|
||||
"inherits": "linux-build-base",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-debug-ootree-skeleton-full",
|
||||
"displayName": "Linux x86_64: GCC / Debug / Skeleton / Out of tree (full)",
|
||||
"configurePreset": "linux-gcc-debug-ootree-skeleton-full",
|
||||
"inherits": "linux-build-base",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-debug-intree-m32-skeleton-fast",
|
||||
"displayName": "Linux x86: GCC / Debug / Skeleton / In tree (fast)",
|
||||
"configurePreset": "linux-gcc-debug-intree-m32-skeleton-fast",
|
||||
"inherits": "linux-build-base",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-debug-intree-m32-skeleton-full",
|
||||
"displayName": "Linux x86: GCC / Debug / Skeleton / In tree (full)",
|
||||
"configurePreset": "linux-gcc-debug-intree-m32-skeleton-full",
|
||||
"inherits": "linux-build-base",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-release-ootree-skeleton-fast",
|
||||
"displayName": "Linux x86_64: GCC / Release / Skeleton / Out of tree (fast)",
|
||||
"configurePreset": "linux-gcc-release-ootree-skeleton-fast",
|
||||
"inherits": "linux-build-base",
|
||||
"configuration": "Release"
|
||||
},
|
||||
{
|
||||
"name": "linux-gcc-release-ootree-skeleton-full",
|
||||
"displayName": "Linux x86_64: GCC / Release / Skeleton / Out of tree (full)",
|
||||
"configurePreset": "linux-gcc-release-ootree-skeleton-full",
|
||||
"inherits": "linux-build-base",
|
||||
"configuration": "Release"
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"name": "macos-build-base",
|
||||
"hidden": true,
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-clang-debug-ootree-skeleton-fast",
|
||||
"displayName": "macOS x86_64: Clang / Debug / Skeleton / Out of tree (fast)",
|
||||
"configurePreset": "macos-clang-debug-ootree-skeleton-fast",
|
||||
"inherits": "macos-build-base",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "macos-clang-debug-ootree-skeleton-full",
|
||||
"displayName": "macOS x86_64: Clang / Debug / Skeleton / Out of tree (full)",
|
||||
"configurePreset": "macos-clang-debug-ootree-skeleton-full",
|
||||
"inherits": "macos-build-base",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "macos-clang-debug-intree-skeleton-fast",
|
||||
"displayName": "macOS x86_64: Clang / Debug / Skeleton / In tree (fast)",
|
||||
"configurePreset": "macos-clang-debug-intree-skeleton-fast",
|
||||
"inherits": "macos-build-base",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "macos-clang-debug-intree-skeleton-full",
|
||||
"displayName": "macOS x86_64: Clang / Debug / Skeleton / In tree (full)",
|
||||
"configurePreset": "macos-clang-debug-intree-skeleton-full",
|
||||
"inherits": "macos-build-base",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "macos-clang-release-ootree-skeleton-fast",
|
||||
"displayName": "macOS x86_64: CLang / Release / Skeleton / Out of tree (fast)",
|
||||
"configurePreset": "macos-clang-release-ootree-skeleton-fast",
|
||||
"inherits": "macos-build-base",
|
||||
"configuration": "Release"
|
||||
},
|
||||
{
|
||||
"name": "macos-clang-release-ootree-skeleton-full",
|
||||
"displayName": "macOS x86_64: CLang / Release / Skeleton / Out of tree (full)",
|
||||
"configurePreset": "macos-clang-release-ootree-skeleton-full",
|
||||
"inherits": "macos-build-base",
|
||||
"configuration": "Release"
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"name": "windows-build-base",
|
||||
"hidden": true,
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc-debug-ootree-fast",
|
||||
"displayName": "Windows x86_64: MSVC / Debug / Out of tree (fast)",
|
||||
"configurePreset": "windows-msvc-debug-ootree-fast",
|
||||
"inherits": "windows-build-base",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc-debug-ootree-full",
|
||||
"displayName": "Windows x86_64: MSVC / Debug / Out of tree (full)",
|
||||
"configurePreset": "windows-msvc-debug-ootree-full",
|
||||
"inherits": "windows-build-base",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc-debug-intree-fast",
|
||||
"displayName": "Windows x86_64: MSVC / Debug / In tree (fast)",
|
||||
"configurePreset": "windows-msvc-debug-intree-fast",
|
||||
"inherits": "windows-build-base",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc-debug-intree-full",
|
||||
"displayName": "Windows x86_64: MSVC / Debug / In tree (full)",
|
||||
"configurePreset": "windows-msvc-debug-intree-full",
|
||||
"inherits": "windows-build-base",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc-release-ootree-fast",
|
||||
"displayName": "Windows x86_64: MSVC / Release / Out of tree (fast)",
|
||||
"configurePreset": "windows-msvc-release-ootree-fast",
|
||||
"inherits": "windows-build-base",
|
||||
"configuration": "Release"
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc-release-ootree-full",
|
||||
"displayName": "Windows x86_64: MSVC / Release / Out of tree (full)",
|
||||
"configurePreset": "windows-msvc-release-ootree-full",
|
||||
"inherits": "windows-build-base",
|
||||
"configuration": "Release"
|
||||
}
|
||||
]
|
||||
}
|
||||
+67
-7
@@ -90,6 +90,7 @@ re2c_SRC = \
|
||||
src/codegen/gen_program.cc \
|
||||
src/codegen/gen_state.cc \
|
||||
src/codegen/helpers.cc \
|
||||
src/codegen/remove_empty.cc \
|
||||
src/codegen/render.cc \
|
||||
src/options/opt.cc \
|
||||
src/options/symtab.cc \
|
||||
@@ -188,10 +189,12 @@ re2c_BOOT_PARSER = bootstrap/src/parse/parser.cc
|
||||
re2c_BOOT_PARSER_HDR = bootstrap/src/parse/parser.h
|
||||
re2c_BOOT_DOC_C = bootstrap/doc/re2c.1
|
||||
re2c_BOOT_DOC_GO = bootstrap/doc/re2go.1
|
||||
re2c_BOOT_DOC_RUST = bootstrap/doc/re2rust.1
|
||||
re2c_BOOT_HELP = bootstrap/src/msg/help.cc
|
||||
re2c_BOOT = \
|
||||
$(re2c_BOOT_DOC_C) \
|
||||
$(re2c_BOOT_DOC_GO) \
|
||||
$(re2c_BOOT_DOC_RUST) \
|
||||
$(re2c_BOOT_HELP) \
|
||||
$(re2c_BOOT_PARSER) \
|
||||
$(re2c_BOOT_PARSER_HDR) \
|
||||
@@ -216,6 +219,7 @@ re2c_CUSTOM = \
|
||||
re2c_SRC_DOC = doc/manpage.rst
|
||||
re2c_SRC_DOC_EXT = \
|
||||
doc/manual/api/interface.rst_ \
|
||||
doc/manual/conditions/blocks.rst_ \
|
||||
doc/manual/conditions/conditions.rst_ \
|
||||
doc/manual/configurations/configurations.rst_ \
|
||||
doc/manual/directives/directives.rst_ \
|
||||
@@ -240,17 +244,22 @@ re2c_SRC_DOC_EXT = \
|
||||
doc/manual/state/state.rst_ \
|
||||
doc/manual/submatch/submatch_example_mtags.rst_ \
|
||||
doc/manual/submatch/submatch_example_posix.rst_ \
|
||||
doc/manual/submatch/submatch_example_stags.rst_ \
|
||||
doc/manual/submatch/submatch_example_stags_fill.rst_ \
|
||||
doc/manual/submatch/submatch_example_stags.rst_ \
|
||||
doc/manual/submatch/submatch.rst_ \
|
||||
doc/manual/syntax/syntax.rst_ \
|
||||
doc/manual/synopsis.rst_ \
|
||||
doc/manual/syntax/api1.rst_ \
|
||||
doc/manual/syntax/api2_c.rst_ \
|
||||
doc/manual/syntax/api2_go.rst_ \
|
||||
doc/manual/syntax/api2_rust.rst_ \
|
||||
doc/manual/syntax/api3.rst_ \
|
||||
doc/manual/syntax/intro.rst_ \
|
||||
doc/manual/syntax/syntax.rst_ \
|
||||
doc/manual/warnings/warnings_general.rst_ \
|
||||
doc/manual/warnings/warnings_list.rst_ \
|
||||
examples/c/01_basic.re \
|
||||
examples/c/01_basic.c \
|
||||
examples/c/conditions/parse_u32_blocks.re \
|
||||
examples/c/conditions/parse_u32_conditions.re \
|
||||
examples/c/encodings/unicode_identifier.re \
|
||||
examples/c/eof/01_sentinel.re \
|
||||
@@ -260,17 +269,19 @@ re2c_SRC_DOC_EXT = \
|
||||
examples/c/fill/01_fill.re \
|
||||
examples/c/fill/02_fill.re \
|
||||
examples/c/headers/header.re \
|
||||
examples/c/headers/src/lexer/lexer.h \
|
||||
examples/c/headers/lexer/state.h \
|
||||
examples/c/includes/include.re \
|
||||
examples/c/includes/definitions.h \
|
||||
examples/c/reuse/reuse.re \
|
||||
examples/c/reuse/usedir.re \
|
||||
examples/c/state/push.re \
|
||||
examples/c/submatch/01_stags.re \
|
||||
examples/c/submatch/01_stags_fill.re \
|
||||
examples/c/submatch/01_stags.re \
|
||||
examples/c/submatch/02_mtags.re \
|
||||
examples/c/submatch/03_posix.re \
|
||||
examples/go/01_basic.re \
|
||||
examples/go/01_basic.go \
|
||||
examples/go/conditions/parse_u32_blocks.re \
|
||||
examples/go/conditions/parse_u32_conditions.re \
|
||||
examples/go/encodings/unicode_identifier.re \
|
||||
examples/go/eof/01_sentinel.re \
|
||||
@@ -280,22 +291,52 @@ re2c_SRC_DOC_EXT = \
|
||||
examples/go/fill/01_fill.re \
|
||||
examples/go/fill/02_fill.re \
|
||||
examples/go/headers/header.re \
|
||||
examples/go/headers/src/lexer/lexer.go \
|
||||
examples/go/headers/lexer/state.go \
|
||||
examples/go/includes/include.re \
|
||||
examples/go/includes/definitions.go \
|
||||
examples/go/reuse/reuse.re \
|
||||
examples/go/reuse/usedir.re \
|
||||
examples/go/state/push.re \
|
||||
examples/go/submatch/01_stags_fill.re \
|
||||
examples/go/submatch/01_stags.re \
|
||||
examples/go/submatch/02_mtags.re \
|
||||
examples/go/submatch/03_posix.re
|
||||
examples/go/submatch/03_posix.re \
|
||||
examples/rust/01_basic.re \
|
||||
examples/rust/01_basic.rs \
|
||||
examples/rust/conditions/parse_u32_blocks.re \
|
||||
examples/rust/conditions/parse_u32_conditions.re \
|
||||
examples/rust/encodings/unicode_identifier.re \
|
||||
examples/rust/eof/01_sentinel.re \
|
||||
examples/rust/eof/02_bounds_checking.re \
|
||||
examples/rust/eof/03_eof_rule.re \
|
||||
examples/rust/eof/05_generic_api_eof_rule.re \
|
||||
examples/rust/fill/01_fill.re \
|
||||
examples/rust/fill/02_fill.re \
|
||||
examples/rust/headers/header.re \
|
||||
examples/rust/headers/lexer/state.rs \
|
||||
examples/rust/includes/include.re \
|
||||
examples/rust/includes/definitions.rs \
|
||||
examples/rust/reuse/reuse.re \
|
||||
examples/rust/reuse/usedir.re \
|
||||
examples/rust/state/push.re \
|
||||
examples/rust/submatch/01_stags_fill.re \
|
||||
examples/rust/submatch/01_stags.re \
|
||||
examples/rust/submatch/02_mtags.re \
|
||||
examples/rust/submatch/03_posix.re
|
||||
|
||||
DOC_C = doc/re2c.1
|
||||
DOCS = $(DOC_C)
|
||||
|
||||
if WITH_GOLANG
|
||||
DOC_GO = doc/re2go.1
|
||||
DOCS += $(DOC_GO)
|
||||
endif
|
||||
|
||||
if WITH_RUST
|
||||
DOC_RUST = doc/re2rust.1
|
||||
DOCS += $(DOC_RUST)
|
||||
endif
|
||||
|
||||
man_MANS = $(DOCS)
|
||||
|
||||
# include files (stdlib)
|
||||
@@ -384,8 +425,15 @@ $(DOC_GO): $(re2c_SRC_DOC) $(re2c_SRC_DOC_EXT) $(SPLITMAN)
|
||||
&& $(RST2MAN) --tab-width=4 $(top_builddir)/$(re2c_SRC_DOC).go > $@ \
|
||||
&& cp $@ $(top_srcdir)/$(re2c_BOOT_DOC_GO) \
|
||||
&& rm $(top_builddir)/$(re2c_SRC_DOC).go
|
||||
# generate manpage for Rust
|
||||
$(DOC_RUST): $(re2c_SRC_DOC) $(re2c_SRC_DOC_EXT) $(SPLITMAN)
|
||||
$(AM_V_at)$(MKDIR_P) $(@D)
|
||||
$(AM_V_GEN)$(SPLITMAN) $(top_builddir)/$(re2c_SRC_DOC) $(top_builddir)/$(re2c_SRC_DOC).rust rust \
|
||||
&& $(RST2MAN) --tab-width=4 $(top_builddir)/$(re2c_SRC_DOC).rust > $@ \
|
||||
&& cp $@ $(top_srcdir)/$(re2c_BOOT_DOC_RUST) \
|
||||
&& rm $(top_builddir)/$(re2c_SRC_DOC).rust
|
||||
# generate help
|
||||
$(re2c_GEN_HELP): $(re2c_CUSTOM_HELP) $(GENHELP)
|
||||
$(re2c_GEN_HELP): $(re2c_CUSTOM_HELP) $(re2c_SRC_DOC_EXT) $(GENHELP)
|
||||
$(AM_V_at)$(MKDIR_P) $(@D)
|
||||
$(AM_V_GEN)$(RST2MAN) $(top_builddir)/$(re2c_CUSTOM_HELP) > $@.1 \
|
||||
&& $(GENHELP) $@.1 $@ \
|
||||
@@ -402,6 +450,10 @@ $(DOC_C): $(re2c_BOOT_DOC_C)
|
||||
$(DOC_GO): $(re2c_BOOT_DOC_GO)
|
||||
$(AM_V_at)$(MKDIR_P) $(@D)
|
||||
$(AM_V_GEN)cp $(top_srcdir)/$(re2c_BOOT_DOC_GO) $@
|
||||
# copy bootstrap manpage for Rust
|
||||
$(DOC_RUST): $(re2c_BOOT_DOC_RUST)
|
||||
$(AM_V_at)$(MKDIR_P) $(@D)
|
||||
$(AM_V_GEN)cp $(top_srcdir)/$(re2c_BOOT_DOC_RUST) $@
|
||||
# copy bootstrap help
|
||||
$(re2c_GEN_HELP): $(re2c_BOOT_HELP)
|
||||
$(AM_V_at)$(MKDIR_P) $(@D)
|
||||
@@ -471,3 +523,11 @@ re2go_CXXFLAGS = $(AM_CXXFLAGS) -DRE2C_LANG=LANG_GO
|
||||
re2go_SOURCES = $(re2c_SOURCES)
|
||||
nodist_re2go_SOURCES = $(nodist_re2c_SOURCES)
|
||||
endif
|
||||
|
||||
# re2rust
|
||||
if WITH_RUST
|
||||
bin_PROGRAMS += re2rust
|
||||
re2rust_CXXFLAGS = $(AM_CXXFLAGS) -DRE2C_LANG=LANG_RUST
|
||||
re2rust_SOURCES = $(re2c_SOURCES)
|
||||
nodist_re2rust_SOURCES = $(nodist_re2c_SOURCES)
|
||||
endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
re2c is a free and open-source lexer generator for C, C++ and Go.
|
||||
re2c is a free and open-source lexer generator for C/C++, Go and Rust.
|
||||
|
||||
Its main goal is generating fast lexers: at least as fast as their reasonably
|
||||
optimized hand-coded counterparts. Instead of using traditional table-driven
|
||||
@@ -40,8 +40,8 @@ CONTRIBUTING
|
||||
------------
|
||||
|
||||
re2c is an Open Source, community-driven project. See
|
||||
[CONTRIBUTING.md](https://github.com/skvadrik/re2c/blob/master/CONTRIBUTING.md) for
|
||||
details about contributions to this repository.
|
||||
[CONTRIBUTING.md](https://github.com/skvadrik/re2c/blob/master/CONTRIBUTING.md)
|
||||
for details about contributions to this repository.
|
||||
|
||||
|
||||
BUILD
|
||||
@@ -73,6 +73,7 @@ You are welcome to ask for help or share your thoughts and ideas.
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
Re2c was originally written by Peter Bumbulis <peter@csg.uwaterloo.ca>.
|
||||
Since then many people contributed to the project. The current maintainer is
|
||||
|
||||
re2c was originally written by Peter Bumbulis <peter@csg.uwaterloo.ca>. Since
|
||||
then many volunteers have contributed to the project. The current maintainer is
|
||||
Ulya Trofimovich <skvadrik@gmail.com>.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
bench_submatch_dfa_jit_CXXFLAGS = $(AM_CXXFLAGS) -std=c++11 -O3 -I $(top_srcdir)
|
||||
bench_submatch_dfa_jit_LDFLAGS = $(LDFLAGS_RE2) -lbenchmark
|
||||
bench_submatch_dfa_jit_LDFLAGS = $(LDFLAGS_RE2) -lbenchmark -lpthread
|
||||
bench_submatch_dfa_jit_LDADD = $(top_builddir)/libre2c.la
|
||||
|
||||
noinst_PROGRAMS = bench_submatch_dfa_jit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
bench_submatch_nfa_CXXFLAGS = $(AM_CXXFLAGS) -std=c++11 -O3 -I $(top_srcdir)
|
||||
bench_submatch_nfa_LDFLAGS = $(LDFLAGS_RE2) -lbenchmark
|
||||
bench_submatch_nfa_LDFLAGS = $(LDFLAGS_RE2) -lbenchmark -lpthread
|
||||
bench_submatch_nfa_LDADD = $(top_builddir)/libre2c.la
|
||||
|
||||
noinst_PROGRAMS = bench_submatch_nfa
|
||||
|
||||
+2172
-1968
File diff suppressed because it is too large
Load Diff
+2278
-2313
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+109
-109
@@ -1,4 +1,4 @@
|
||||
/* Generated by re2c 2.1.1 on Fri Jul 16 09:07:43 2021 */
|
||||
/* Generated by re2c 3.0 on Thu Jan 27 08:39:52 2022 */
|
||||
#line 1 "../lib/lex.re"
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -76,38 +76,38 @@ const char *yyt1;const char *yyt2;
|
||||
yych = *cur;
|
||||
if (yych <= '>') {
|
||||
if (yych <= '\'') {
|
||||
if (yych <= 0x00) goto yy2;
|
||||
if (yych == '$') goto yy6;
|
||||
goto yy4;
|
||||
if (yych <= 0x00) goto yy1;
|
||||
if (yych == '$') goto yy4;
|
||||
goto yy2;
|
||||
} else {
|
||||
if (yych <= '+') goto yy8;
|
||||
if (yych == '.') goto yy10;
|
||||
goto yy4;
|
||||
if (yych <= '+') goto yy5;
|
||||
if (yych == '.') goto yy6;
|
||||
goto yy2;
|
||||
}
|
||||
} else {
|
||||
if (yych <= ']') {
|
||||
if (yych <= '?') goto yy8;
|
||||
if (yych == '[') goto yy12;
|
||||
goto yy4;
|
||||
if (yych <= '?') goto yy5;
|
||||
if (yych == '[') goto yy7;
|
||||
goto yy2;
|
||||
} else {
|
||||
if (yych <= 'z') {
|
||||
if (yych <= '^') goto yy6;
|
||||
goto yy4;
|
||||
if (yych <= '^') goto yy4;
|
||||
goto yy2;
|
||||
} else {
|
||||
if (yych <= '{') goto yy14;
|
||||
if (yych <= '|') goto yy8;
|
||||
goto yy4;
|
||||
if (yych <= '{') goto yy8;
|
||||
if (yych <= '|') goto yy5;
|
||||
goto yy2;
|
||||
}
|
||||
}
|
||||
}
|
||||
yy2:
|
||||
yy1:
|
||||
++cur;
|
||||
#line 43 "../lib/lex.re"
|
||||
{ return 0; }
|
||||
#line 108 "lib/lex.cc"
|
||||
yy4:
|
||||
yy2:
|
||||
++cur;
|
||||
yy5:
|
||||
yy3:
|
||||
#line 78 "../lib/lex.re"
|
||||
{
|
||||
ASTChar c = {static_cast<uint32_t>(cur[-1]), NOWHERE};
|
||||
@@ -117,7 +117,7 @@ yy5:
|
||||
return TOKEN_REGEXP;
|
||||
}
|
||||
#line 120 "lib/lex.cc"
|
||||
yy6:
|
||||
yy4:
|
||||
++cur;
|
||||
#line 47 "../lib/lex.re"
|
||||
{
|
||||
@@ -125,12 +125,12 @@ yy6:
|
||||
return TOKEN_ERROR;
|
||||
}
|
||||
#line 128 "lib/lex.cc"
|
||||
yy8:
|
||||
yy5:
|
||||
++cur;
|
||||
#line 45 "../lib/lex.re"
|
||||
{ return cur[-1]; }
|
||||
#line 133 "lib/lex.cc"
|
||||
yy10:
|
||||
yy6:
|
||||
++cur;
|
||||
#line 73 "../lib/lex.re"
|
||||
{
|
||||
@@ -138,45 +138,45 @@ yy10:
|
||||
return TOKEN_REGEXP;
|
||||
}
|
||||
#line 141 "lib/lex.cc"
|
||||
yy12:
|
||||
yy7:
|
||||
yych = *++cur;
|
||||
if (yych == '^') goto yy15;
|
||||
if (yych == '^') goto yy9;
|
||||
#line 53 "../lib/lex.re"
|
||||
{ goto cls; }
|
||||
#line 147 "lib/lex.cc"
|
||||
yy14:
|
||||
yy8:
|
||||
yych = *(mar = ++cur);
|
||||
if (yych <= '/') goto yy5;
|
||||
if (yych <= '/') goto yy3;
|
||||
if (yych <= '9') {
|
||||
yyt1 = cur;
|
||||
goto yy17;
|
||||
goto yy10;
|
||||
}
|
||||
goto yy5;
|
||||
yy15:
|
||||
goto yy3;
|
||||
yy9:
|
||||
++cur;
|
||||
#line 52 "../lib/lex.re"
|
||||
{ neg = true; goto cls; }
|
||||
#line 160 "lib/lex.cc"
|
||||
yy17:
|
||||
yy10:
|
||||
yych = *++cur;
|
||||
if (yybm[0+yych] & 128) {
|
||||
goto yy17;
|
||||
goto yy10;
|
||||
}
|
||||
if (yych == ',') goto yy20;
|
||||
if (yych == '}') goto yy21;
|
||||
yy19:
|
||||
if (yych == ',') goto yy12;
|
||||
if (yych == '}') goto yy13;
|
||||
yy11:
|
||||
cur = mar;
|
||||
goto yy5;
|
||||
yy20:
|
||||
goto yy3;
|
||||
yy12:
|
||||
yych = *++cur;
|
||||
if (yych <= '/') goto yy19;
|
||||
if (yych <= '/') goto yy11;
|
||||
if (yych <= '9') {
|
||||
yyt2 = cur;
|
||||
goto yy23;
|
||||
goto yy14;
|
||||
}
|
||||
if (yych == '}') goto yy25;
|
||||
goto yy19;
|
||||
yy21:
|
||||
if (yych == '}') goto yy15;
|
||||
goto yy11;
|
||||
yy13:
|
||||
++cur;
|
||||
x = yyt1;
|
||||
#line 55 "../lib/lex.re"
|
||||
@@ -186,13 +186,13 @@ yy21:
|
||||
return TOKEN_COUNT;
|
||||
}
|
||||
#line 189 "lib/lex.cc"
|
||||
yy23:
|
||||
yy14:
|
||||
yych = *++cur;
|
||||
if (yych <= '/') goto yy19;
|
||||
if (yych <= '9') goto yy23;
|
||||
if (yych == '}') goto yy27;
|
||||
goto yy19;
|
||||
yy25:
|
||||
if (yych <= '/') goto yy11;
|
||||
if (yych <= '9') goto yy14;
|
||||
if (yych == '}') goto yy16;
|
||||
goto yy11;
|
||||
yy15:
|
||||
++cur;
|
||||
x = yyt1;
|
||||
#line 67 "../lib/lex.re"
|
||||
@@ -202,7 +202,7 @@ yy25:
|
||||
return TOKEN_COUNT;
|
||||
}
|
||||
#line 205 "lib/lex.cc"
|
||||
yy27:
|
||||
yy16:
|
||||
++cur;
|
||||
x = yyt1;
|
||||
y = yyt2;
|
||||
@@ -224,17 +224,17 @@ cls:
|
||||
{
|
||||
char yych;
|
||||
yych = *(mar = cur);
|
||||
if (yych == '-') goto yy32;
|
||||
yy31:
|
||||
if (yych == '-') goto yy19;
|
||||
yy18:
|
||||
#line 90 "../lib/lex.re"
|
||||
{ u = l; goto add; }
|
||||
#line 232 "lib/lex.cc"
|
||||
yy32:
|
||||
yy19:
|
||||
yych = *++cur;
|
||||
if (yych != ']') goto yy34;
|
||||
if (yych != ']') goto yy20;
|
||||
cur = mar;
|
||||
goto yy31;
|
||||
yy34:
|
||||
goto yy18;
|
||||
yy20:
|
||||
++cur;
|
||||
cur -= 1;
|
||||
#line 91 "../lib/lex.re"
|
||||
@@ -251,11 +251,11 @@ add:
|
||||
{
|
||||
char yych;
|
||||
yych = *cur;
|
||||
if (yych == ']') goto yy39;
|
||||
if (yych == ']') goto yy22;
|
||||
#line 97 "../lib/lex.re"
|
||||
{ goto cls; }
|
||||
#line 258 "lib/lex.cc"
|
||||
yy39:
|
||||
yy22:
|
||||
++cur;
|
||||
#line 98 "../lib/lex.re"
|
||||
{
|
||||
@@ -286,135 +286,135 @@ int32_t lex_cls_chr(const char *&cur, uint32_t &c)
|
||||
{
|
||||
char yych;
|
||||
yych = *cur;
|
||||
if (yych <= 0x00) goto yy43;
|
||||
if (yych <= 'Z') goto yy45;
|
||||
if (yych <= '[') goto yy47;
|
||||
if (yych <= '\\') goto yy48;
|
||||
goto yy45;
|
||||
yy43:
|
||||
if (yych <= 0x00) goto yy24;
|
||||
if (yych <= 'Z') goto yy25;
|
||||
if (yych <= '[') goto yy27;
|
||||
if (yych <= '\\') goto yy28;
|
||||
goto yy25;
|
||||
yy24:
|
||||
++cur;
|
||||
#line 119 "../lib/lex.re"
|
||||
{ return 1; }
|
||||
#line 299 "lib/lex.cc"
|
||||
yy45:
|
||||
yy25:
|
||||
++cur;
|
||||
yy46:
|
||||
yy26:
|
||||
#line 137 "../lib/lex.re"
|
||||
{ c = static_cast<uint8_t>(cur[-1]); return 0; }
|
||||
#line 305 "lib/lex.cc"
|
||||
yy47:
|
||||
yy27:
|
||||
yych = *++cur;
|
||||
if (yych <= '9') {
|
||||
if (yych == '.') goto yy50;
|
||||
goto yy46;
|
||||
if (yych == '.') goto yy30;
|
||||
goto yy26;
|
||||
} else {
|
||||
if (yych <= ':') goto yy52;
|
||||
if (yych == '=') goto yy54;
|
||||
goto yy46;
|
||||
if (yych <= ':') goto yy31;
|
||||
if (yych == '=') goto yy32;
|
||||
goto yy26;
|
||||
}
|
||||
yy48:
|
||||
yy28:
|
||||
yych = *(mar = ++cur);
|
||||
switch (yych) {
|
||||
case '\\': goto yy56;
|
||||
case ']': goto yy58;
|
||||
case 'a': goto yy60;
|
||||
case 'b': goto yy62;
|
||||
case 'f': goto yy64;
|
||||
case 'n': goto yy66;
|
||||
case 'r': goto yy68;
|
||||
case 't': goto yy70;
|
||||
case 'v': goto yy72;
|
||||
case 'x': goto yy74;
|
||||
default: goto yy49;
|
||||
case '\\': goto yy33;
|
||||
case ']': goto yy34;
|
||||
case 'a': goto yy35;
|
||||
case 'b': goto yy36;
|
||||
case 'f': goto yy37;
|
||||
case 'n': goto yy38;
|
||||
case 'r': goto yy39;
|
||||
case 't': goto yy40;
|
||||
case 'v': goto yy41;
|
||||
case 'x': goto yy42;
|
||||
default: goto yy29;
|
||||
}
|
||||
yy49:
|
||||
yy29:
|
||||
#line 126 "../lib/lex.re"
|
||||
{ c = static_cast<uint8_t>('\\'); return 0; }
|
||||
#line 334 "lib/lex.cc"
|
||||
yy50:
|
||||
yy30:
|
||||
++cur;
|
||||
#line 120 "../lib/lex.re"
|
||||
{ error("collating characters not supported"); return 1; }
|
||||
#line 339 "lib/lex.cc"
|
||||
yy52:
|
||||
yy31:
|
||||
++cur;
|
||||
#line 121 "../lib/lex.re"
|
||||
{ error("character classes not supported"); return 1; }
|
||||
#line 344 "lib/lex.cc"
|
||||
yy54:
|
||||
yy32:
|
||||
++cur;
|
||||
#line 122 "../lib/lex.re"
|
||||
{ error("equivalence classes not supported"); return 1; }
|
||||
#line 349 "lib/lex.cc"
|
||||
yy56:
|
||||
yy33:
|
||||
++cur;
|
||||
#line 134 "../lib/lex.re"
|
||||
{ c = static_cast<uint8_t>('\\'); return 0; }
|
||||
#line 354 "lib/lex.cc"
|
||||
yy58:
|
||||
yy34:
|
||||
++cur;
|
||||
#line 135 "../lib/lex.re"
|
||||
{ c = static_cast<uint8_t>(']'); return 0; }
|
||||
#line 359 "lib/lex.cc"
|
||||
yy60:
|
||||
yy35:
|
||||
++cur;
|
||||
#line 127 "../lib/lex.re"
|
||||
{ c = static_cast<uint8_t>('\a'); return 0; }
|
||||
#line 364 "lib/lex.cc"
|
||||
yy62:
|
||||
yy36:
|
||||
++cur;
|
||||
#line 128 "../lib/lex.re"
|
||||
{ c = static_cast<uint8_t>('\b'); return 0; }
|
||||
#line 369 "lib/lex.cc"
|
||||
yy64:
|
||||
yy37:
|
||||
++cur;
|
||||
#line 129 "../lib/lex.re"
|
||||
{ c = static_cast<uint8_t>('\f'); return 0; }
|
||||
#line 374 "lib/lex.cc"
|
||||
yy66:
|
||||
yy38:
|
||||
++cur;
|
||||
#line 130 "../lib/lex.re"
|
||||
{ c = static_cast<uint8_t>('\n'); return 0; }
|
||||
#line 379 "lib/lex.cc"
|
||||
yy68:
|
||||
yy39:
|
||||
++cur;
|
||||
#line 131 "../lib/lex.re"
|
||||
{ c = static_cast<uint8_t>('\r'); return 0; }
|
||||
#line 384 "lib/lex.cc"
|
||||
yy70:
|
||||
yy40:
|
||||
++cur;
|
||||
#line 132 "../lib/lex.re"
|
||||
{ c = static_cast<uint8_t>('\t'); return 0; }
|
||||
#line 389 "lib/lex.cc"
|
||||
yy72:
|
||||
yy41:
|
||||
++cur;
|
||||
#line 133 "../lib/lex.re"
|
||||
{ c = static_cast<uint8_t>('\v'); return 0; }
|
||||
#line 394 "lib/lex.cc"
|
||||
yy74:
|
||||
yy42:
|
||||
yych = *++cur;
|
||||
if (yych <= '@') {
|
||||
if (yych <= '/') goto yy75;
|
||||
if (yych <= '9') goto yy76;
|
||||
if (yych <= '/') goto yy43;
|
||||
if (yych <= '9') goto yy44;
|
||||
} else {
|
||||
if (yych <= 'F') goto yy76;
|
||||
if (yych <= '`') goto yy75;
|
||||
if (yych <= 'f') goto yy76;
|
||||
if (yych <= 'F') goto yy44;
|
||||
if (yych <= '`') goto yy43;
|
||||
if (yych <= 'f') goto yy44;
|
||||
}
|
||||
yy75:
|
||||
yy43:
|
||||
cur = mar;
|
||||
goto yy49;
|
||||
yy76:
|
||||
goto yy29;
|
||||
yy44:
|
||||
yych = *++cur;
|
||||
if (yych <= '@') {
|
||||
if (yych <= '/') goto yy75;
|
||||
if (yych >= ':') goto yy75;
|
||||
if (yych <= '/') goto yy43;
|
||||
if (yych >= ':') goto yy43;
|
||||
} else {
|
||||
if (yych <= 'F') goto yy77;
|
||||
if (yych <= '`') goto yy75;
|
||||
if (yych >= 'g') goto yy75;
|
||||
if (yych <= 'F') goto yy45;
|
||||
if (yych <= '`') goto yy43;
|
||||
if (yych >= 'g') goto yy43;
|
||||
}
|
||||
yy77:
|
||||
yy45:
|
||||
++cur;
|
||||
#line 124 "../lib/lex.re"
|
||||
{ c = unesc_hex(p, cur); return 0; }
|
||||
|
||||
+54
-63
@@ -1,4 +1,4 @@
|
||||
/* A Bison parser, made by GNU Bison 3.7.6. */
|
||||
/* A Bison parser, made by GNU Bison 3.8.2. */
|
||||
|
||||
/* Bison implementation for Yacc-like parsers in C
|
||||
|
||||
@@ -46,10 +46,10 @@
|
||||
USER NAME SPACE" below. */
|
||||
|
||||
/* Identify Bison output, and Bison version. */
|
||||
#define YYBISON 30706
|
||||
#define YYBISON 30802
|
||||
|
||||
/* Bison version string. */
|
||||
#define YYBISON_VERSION "3.7.6"
|
||||
#define YYBISON_VERSION "3.8.2"
|
||||
|
||||
/* Skeleton name. */
|
||||
#define YYSKELETON_NAME "yacc.c"
|
||||
@@ -302,12 +302,18 @@ typedef int yy_state_fast_t;
|
||||
# define YY_USE(E) /* empty */
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
|
||||
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
|
||||
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
|
||||
#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__
|
||||
# if __GNUC__ * 100 + __GNUC_MINOR__ < 407
|
||||
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
|
||||
_Pragma ("GCC diagnostic push") \
|
||||
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")
|
||||
# else
|
||||
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
|
||||
_Pragma ("GCC diagnostic push") \
|
||||
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
|
||||
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
|
||||
# endif
|
||||
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
|
||||
_Pragma ("GCC diagnostic pop")
|
||||
#else
|
||||
@@ -522,7 +528,7 @@ static const yytype_int8 yytranslate[] =
|
||||
};
|
||||
|
||||
#if YYDEBUG
|
||||
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
|
||||
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
|
||||
static const yytype_int8 yyrline[] =
|
||||
{
|
||||
0, 52, 52, 55, 56, 60, 61, 65, 66, 67,
|
||||
@@ -554,16 +560,6 @@ yysymbol_name (yysymbol_kind_t yysymbol)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef YYPRINT
|
||||
/* YYTOKNUM[NUM] -- (External) token number corresponding to the
|
||||
(internal) symbol number NUM (which must be that of a token). */
|
||||
static const yytype_int16 yytoknum[] =
|
||||
{
|
||||
0, 256, 257, 258, 259, 260, 124, 42, 43, 63,
|
||||
40, 41
|
||||
};
|
||||
#endif
|
||||
|
||||
#define YYPACT_NINF (-5)
|
||||
|
||||
#define yypact_value_is_default(Yyn) \
|
||||
@@ -574,38 +570,38 @@ static const yytype_int16 yytoknum[] =
|
||||
#define yytable_value_is_error(Yyn) \
|
||||
0
|
||||
|
||||
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
|
||||
STATE-NUM. */
|
||||
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
|
||||
STATE-NUM. */
|
||||
static const yytype_int8 yypact[] =
|
||||
{
|
||||
2, -5, -2, 1, -4, -5, 2, -3, -5, 4,
|
||||
-5, 2, -5, -5, -5, -5, -5, -5, -5
|
||||
};
|
||||
|
||||
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
|
||||
Performed when YYTABLE does not specify something else to do. Zero
|
||||
means the default is an error. */
|
||||
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
|
||||
Performed when YYTABLE does not specify something else to do. Zero
|
||||
means the default is an error. */
|
||||
static const yytype_int8 yydefact[] =
|
||||
{
|
||||
0, 12, 0, 0, 2, 3, 5, 7, 13, 0,
|
||||
1, 0, 6, 11, 8, 9, 10, 14, 4
|
||||
};
|
||||
|
||||
/* YYPGOTO[NTERM-NUM]. */
|
||||
/* YYPGOTO[NTERM-NUM]. */
|
||||
static const yytype_int8 yypgoto[] =
|
||||
{
|
||||
-5, -5, 11, 5, -5, -5
|
||||
};
|
||||
|
||||
/* YYDEFGOTO[NTERM-NUM]. */
|
||||
/* YYDEFGOTO[NTERM-NUM]. */
|
||||
static const yytype_int8 yydefgoto[] =
|
||||
{
|
||||
0, 3, 4, 5, 6, 7
|
||||
};
|
||||
|
||||
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
|
||||
positive, shift that token. If negative, reduce the rule whose
|
||||
number is the opposite. If YYTABLE_NINF, syntax error. */
|
||||
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
|
||||
positive, shift that token. If negative, reduce the rule whose
|
||||
number is the opposite. If YYTABLE_NINF, syntax error. */
|
||||
static const yytype_int8 yytable[] =
|
||||
{
|
||||
13, 10, 11, 1, 14, 15, 16, 1, 2, 8,
|
||||
@@ -618,22 +614,22 @@ static const yytype_int8 yycheck[] =
|
||||
6, 6, 10, 2, -1, 11, 11
|
||||
};
|
||||
|
||||
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
|
||||
symbol of state STATE-NUM. */
|
||||
/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
|
||||
state STATE-NUM. */
|
||||
static const yytype_int8 yystos[] =
|
||||
{
|
||||
0, 5, 10, 13, 14, 15, 16, 17, 11, 14,
|
||||
0, 6, 15, 3, 7, 8, 9, 11, 15
|
||||
};
|
||||
|
||||
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
|
||||
/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */
|
||||
static const yytype_int8 yyr1[] =
|
||||
{
|
||||
0, 12, 13, 14, 14, 15, 15, 16, 16, 16,
|
||||
16, 16, 17, 17, 17
|
||||
};
|
||||
|
||||
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
|
||||
/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */
|
||||
static const yytype_int8 yyr2[] =
|
||||
{
|
||||
0, 2, 1, 1, 3, 1, 2, 1, 2, 2,
|
||||
@@ -649,6 +645,7 @@ enum { YYENOMEM = -2 };
|
||||
#define YYACCEPT goto yyacceptlab
|
||||
#define YYABORT goto yyabortlab
|
||||
#define YYERROR goto yyerrorlab
|
||||
#define YYNOMEM goto yyexhaustedlab
|
||||
|
||||
|
||||
#define YYRECOVERING() (!!yyerrstatus)
|
||||
@@ -689,10 +686,7 @@ do { \
|
||||
YYFPRINTF Args; \
|
||||
} while (0)
|
||||
|
||||
/* This macro is provided for backward compatibility. */
|
||||
# ifndef YY_LOCATION_PRINT
|
||||
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
|
||||
@@ -720,10 +714,6 @@ yy_symbol_value_print (FILE *yyo,
|
||||
YY_USE (pattern);
|
||||
if (!yyvaluep)
|
||||
return;
|
||||
# ifdef YYPRINT
|
||||
if (yykind < YYNTOKENS)
|
||||
YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
|
||||
# endif
|
||||
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
|
||||
YY_USE (yykind);
|
||||
YY_IGNORE_MAYBE_UNINITIALIZED_END
|
||||
@@ -909,6 +899,7 @@ yyparse (const char *&pattern)
|
||||
YYDPRINTF ((stderr, "Starting parse\n"));
|
||||
|
||||
yychar = YYEMPTY; /* Cause a token to be read. */
|
||||
|
||||
goto yysetstate;
|
||||
|
||||
|
||||
@@ -934,7 +925,7 @@ yysetstate:
|
||||
|
||||
if (yyss + yystacksize - 1 <= yyssp)
|
||||
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
|
||||
goto yyexhaustedlab;
|
||||
YYNOMEM;
|
||||
#else
|
||||
{
|
||||
/* Get the current used size of the three stacks, in elements. */
|
||||
@@ -962,7 +953,7 @@ yysetstate:
|
||||
# else /* defined YYSTACK_RELOCATE */
|
||||
/* Extend the stack our own way. */
|
||||
if (YYMAXDEPTH <= yystacksize)
|
||||
goto yyexhaustedlab;
|
||||
YYNOMEM;
|
||||
yystacksize *= 2;
|
||||
if (YYMAXDEPTH < yystacksize)
|
||||
yystacksize = YYMAXDEPTH;
|
||||
@@ -973,7 +964,7 @@ yysetstate:
|
||||
YY_CAST (union yyalloc *,
|
||||
YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
|
||||
if (! yyptr)
|
||||
goto yyexhaustedlab;
|
||||
YYNOMEM;
|
||||
YYSTACK_RELOCATE (yyss_alloc, yyss);
|
||||
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
|
||||
# undef YYSTACK_RELOCATE
|
||||
@@ -995,6 +986,7 @@ yysetstate:
|
||||
}
|
||||
#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
|
||||
|
||||
|
||||
if (yystate == YYFINAL)
|
||||
YYACCEPT;
|
||||
|
||||
@@ -1109,59 +1101,59 @@ yyreduce:
|
||||
case 2: /* regexp: expr */
|
||||
#line 52 "../lib/parse.ypp"
|
||||
{ regexp = (yyval.regexp); }
|
||||
#line 1113 "lib/parse.cc"
|
||||
#line 1105 "lib/parse.cc"
|
||||
break;
|
||||
|
||||
case 4: /* expr: expr '|' term */
|
||||
#line 56 "../lib/parse.ypp"
|
||||
{ (yyval.regexp) = ast_alt((yyvsp[-2].regexp), (yyvsp[0].regexp)); }
|
||||
#line 1119 "lib/parse.cc"
|
||||
#line 1111 "lib/parse.cc"
|
||||
break;
|
||||
|
||||
case 6: /* term: factor term */
|
||||
#line 61 "../lib/parse.ypp"
|
||||
{ (yyval.regexp) = ast_cat((yyvsp[-1].regexp), (yyvsp[0].regexp)); }
|
||||
#line 1125 "lib/parse.cc"
|
||||
#line 1117 "lib/parse.cc"
|
||||
break;
|
||||
|
||||
case 8: /* factor: primary '*' */
|
||||
#line 66 "../lib/parse.ypp"
|
||||
{ (yyval.regexp) = ast_iter((yyvsp[-1].regexp), 0, AST::MANY); }
|
||||
#line 1131 "lib/parse.cc"
|
||||
#line 1123 "lib/parse.cc"
|
||||
break;
|
||||
|
||||
case 9: /* factor: primary '+' */
|
||||
#line 67 "../lib/parse.ypp"
|
||||
{ (yyval.regexp) = ast_iter((yyvsp[-1].regexp), 1, AST::MANY); }
|
||||
#line 1137 "lib/parse.cc"
|
||||
#line 1129 "lib/parse.cc"
|
||||
break;
|
||||
|
||||
case 10: /* factor: primary '?' */
|
||||
#line 68 "../lib/parse.ypp"
|
||||
{ (yyval.regexp) = ast_iter((yyvsp[-1].regexp), 0, 1); }
|
||||
#line 1143 "lib/parse.cc"
|
||||
#line 1135 "lib/parse.cc"
|
||||
break;
|
||||
|
||||
case 11: /* factor: primary TOKEN_COUNT */
|
||||
#line 69 "../lib/parse.ypp"
|
||||
{ (yyval.regexp) = ast_iter((yyvsp[-1].regexp), (yyvsp[0].bounds).min, (yyvsp[0].bounds).max); }
|
||||
#line 1149 "lib/parse.cc"
|
||||
#line 1141 "lib/parse.cc"
|
||||
break;
|
||||
|
||||
case 13: /* primary: '(' ')' */
|
||||
#line 74 "../lib/parse.ypp"
|
||||
{ (yyval.regexp) = ast_cap(ast_nil(NOWHERE)); }
|
||||
#line 1155 "lib/parse.cc"
|
||||
#line 1147 "lib/parse.cc"
|
||||
break;
|
||||
|
||||
case 14: /* primary: '(' expr ')' */
|
||||
#line 75 "../lib/parse.ypp"
|
||||
{ (yyval.regexp) = ast_cap((yyvsp[-1].regexp)); }
|
||||
#line 1161 "lib/parse.cc"
|
||||
#line 1153 "lib/parse.cc"
|
||||
break;
|
||||
|
||||
|
||||
#line 1165 "lib/parse.cc"
|
||||
#line 1157 "lib/parse.cc"
|
||||
|
||||
default: break;
|
||||
}
|
||||
@@ -1243,6 +1235,7 @@ yyerrorlab:
|
||||
label yyerrorlab therefore never appears in user code. */
|
||||
if (0)
|
||||
YYERROR;
|
||||
++yynerrs;
|
||||
|
||||
/* Do not reclaim the symbols of the rule whose action triggered
|
||||
this YYERROR. */
|
||||
@@ -1303,7 +1296,7 @@ yyerrlab1:
|
||||
`-------------------------------------*/
|
||||
yyacceptlab:
|
||||
yyresult = 0;
|
||||
goto yyreturn;
|
||||
goto yyreturnlab;
|
||||
|
||||
|
||||
/*-----------------------------------.
|
||||
@@ -1311,24 +1304,22 @@ yyacceptlab:
|
||||
`-----------------------------------*/
|
||||
yyabortlab:
|
||||
yyresult = 1;
|
||||
goto yyreturn;
|
||||
goto yyreturnlab;
|
||||
|
||||
|
||||
#if !defined yyoverflow
|
||||
/*-------------------------------------------------.
|
||||
| yyexhaustedlab -- memory exhaustion comes here. |
|
||||
`-------------------------------------------------*/
|
||||
/*-----------------------------------------------------------.
|
||||
| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. |
|
||||
`-----------------------------------------------------------*/
|
||||
yyexhaustedlab:
|
||||
yyerror (pattern, YY_("memory exhausted"));
|
||||
yyresult = 2;
|
||||
goto yyreturn;
|
||||
#endif
|
||||
goto yyreturnlab;
|
||||
|
||||
|
||||
/*-------------------------------------------------------.
|
||||
| yyreturn -- parsing is finished, clean up and return. |
|
||||
`-------------------------------------------------------*/
|
||||
yyreturn:
|
||||
/*----------------------------------------------------------.
|
||||
| yyreturnlab -- parsing is finished, clean up and return. |
|
||||
`----------------------------------------------------------*/
|
||||
yyreturnlab:
|
||||
if (yychar != YYEMPTY)
|
||||
{
|
||||
/* Make sure we have latest lookahead translation. See comments at
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* A Bison parser, made by GNU Bison 3.7.6. */
|
||||
/* A Bison parser, made by GNU Bison 3.8.2. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
@@ -81,6 +81,8 @@ typedef union YYSTYPE YYSTYPE;
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
|
||||
int yyparse (const char *&pattern);
|
||||
|
||||
|
||||
#endif /* !YY_YY_LIB_PARSE_H_INCLUDED */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Generated by re2c 2.1.1 on Fri Jul 16 09:07:43 2021 */
|
||||
/* Generated by re2c 3.0 on Thu Jan 27 08:39:52 2022 */
|
||||
#line 1 "../lib/test_helper.re"
|
||||
#include "lib/test_helper.h"
|
||||
|
||||
@@ -70,74 +70,74 @@ loop:
|
||||
};
|
||||
yych = *YYCURSOR;
|
||||
if (yych <= '(') {
|
||||
if (yych <= 0x00) goto yy2;
|
||||
if (yych <= '\'') goto yy4;
|
||||
goto yy6;
|
||||
} else {
|
||||
if (yych == ',') goto yy7;
|
||||
if (yych <= 0x00) goto yy1;
|
||||
if (yych <= '\'') goto yy2;
|
||||
goto yy4;
|
||||
} else {
|
||||
if (yych == ',') goto yy5;
|
||||
goto yy2;
|
||||
}
|
||||
yy2:
|
||||
yy1:
|
||||
++YYCURSOR;
|
||||
#line 33 "../lib/test_helper.re"
|
||||
{ return true; }
|
||||
#line 85 "lib/test_helper.cc"
|
||||
yy4:
|
||||
yy2:
|
||||
++YYCURSOR;
|
||||
yy5:
|
||||
yy3:
|
||||
#line 32 "../lib/test_helper.re"
|
||||
{ return false; }
|
||||
#line 91 "lib/test_helper.cc"
|
||||
yy6:
|
||||
yy4:
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if (yych <= '/') goto yy5;
|
||||
if (yych <= '/') goto yy3;
|
||||
if (yych <= '9') {
|
||||
yyt1 = YYCURSOR;
|
||||
goto yy9;
|
||||
goto yy6;
|
||||
}
|
||||
if (yych == '?') goto yy12;
|
||||
goto yy5;
|
||||
yy7:
|
||||
if (yych == '?') goto yy8;
|
||||
goto yy3;
|
||||
yy5:
|
||||
++YYCURSOR;
|
||||
#line 34 "../lib/test_helper.re"
|
||||
{ goto next; }
|
||||
#line 105 "lib/test_helper.cc"
|
||||
yy9:
|
||||
yy6:
|
||||
yych = *++YYCURSOR;
|
||||
if (yybm[0+yych] & 128) {
|
||||
goto yy9;
|
||||
goto yy6;
|
||||
}
|
||||
if (yych == ',') goto yy13;
|
||||
yy11:
|
||||
if (yych == ',') goto yy9;
|
||||
yy7:
|
||||
YYCURSOR = YYMARKER;
|
||||
goto yy5;
|
||||
yy12:
|
||||
goto yy3;
|
||||
yy8:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych == ',') goto yy14;
|
||||
goto yy11;
|
||||
yy13:
|
||||
if (yych == ',') goto yy10;
|
||||
goto yy7;
|
||||
yy9:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= '/') goto yy11;
|
||||
if (yych <= '/') goto yy7;
|
||||
if (yych <= '9') {
|
||||
yyt2 = YYCURSOR;
|
||||
goto yy15;
|
||||
goto yy11;
|
||||
}
|
||||
goto yy11;
|
||||
yy14:
|
||||
goto yy7;
|
||||
yy10:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych == '?') goto yy17;
|
||||
goto yy11;
|
||||
yy15:
|
||||
if (yych == '?') goto yy12;
|
||||
goto yy7;
|
||||
yy11:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych == ')') goto yy18;
|
||||
if (yych <= '/') goto yy11;
|
||||
if (yych <= '9') goto yy15;
|
||||
goto yy11;
|
||||
yy17:
|
||||
if (yych == ')') goto yy13;
|
||||
if (yych <= '/') goto yy7;
|
||||
if (yych <= '9') goto yy11;
|
||||
goto yy7;
|
||||
yy12:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych == ')') goto yy20;
|
||||
goto yy11;
|
||||
yy18:
|
||||
if (yych == ')') goto yy14;
|
||||
goto yy7;
|
||||
yy13:
|
||||
++YYCURSOR;
|
||||
n1 = yyt1;
|
||||
m1 = yyt2;
|
||||
@@ -150,7 +150,7 @@ yy18:
|
||||
goto loop;
|
||||
}
|
||||
#line 153 "lib/test_helper.cc"
|
||||
yy20:
|
||||
yy14:
|
||||
++YYCURSOR;
|
||||
#line 36 "../lib/test_helper.re"
|
||||
{
|
||||
|
||||
+198
-173
@@ -1,29 +1,25 @@
|
||||
extern const char *help;
|
||||
const char *help =
|
||||
"USAGE\n"
|
||||
" re2c [OPTION...] INPUT [-o OUTPUT]\n"
|
||||
" re2c [ OPTIONS ] [ WARNINGS ] INPUT\n"
|
||||
" re2go [ OPTIONS ] [ WARNINGS ] INPUT\n"
|
||||
" re2rust [ OPTIONS ] [ WARNINGS ] INPUT\n"
|
||||
"\n"
|
||||
" re2go [OPTION...] INPUT [-o OUTPUT]\n"
|
||||
" Input can be either a file or - for stdin.\n"
|
||||
"\n"
|
||||
"OPTIONS\n"
|
||||
" -? -h --help\n"
|
||||
" -? --help -h\n"
|
||||
" Show help message.\n"
|
||||
"\n"
|
||||
" -1 --single-pass\n"
|
||||
" Deprecated. Does nothing (single pass is the default now).\n"
|
||||
" --api --input <default | custom>\n"
|
||||
" Specify the API used by the generated code to interface with\n"
|
||||
" used-defined code: default is the API based on pointer arith‐\n"
|
||||
" metic (the default for C), and custom is the generic API (the\n"
|
||||
" default for Go and Rust).\n"
|
||||
"\n"
|
||||
" -8 --utf-8\n"
|
||||
" Generate a lexer that reads input in UTF-8 encoding. re2c as‐\n"
|
||||
" sumes that character range is 0 -- 0x10FFFF and character size\n"
|
||||
" is 1 byte.\n"
|
||||
"\n"
|
||||
" -b --bit-vectors\n"
|
||||
" Optimize conditional jumps using bit masks. Implies -s.\n"
|
||||
"\n"
|
||||
" -c --conditions --start-conditions\n"
|
||||
" Enable support of Flex-like \"conditions\": multiple interrelated\n"
|
||||
" lexers within one block. Option --start-conditions is a legacy\n"
|
||||
" alias; use --conditions instead.\n"
|
||||
" --bit-vectors -b\n"
|
||||
" Optimize conditional jumps using bit masks. This option implies\n"
|
||||
" --nested-ifs.\n"
|
||||
"\n"
|
||||
" --case-insensitive\n"
|
||||
" Treat single-quoted and double-quoted strings as case-insensi‐\n"
|
||||
@@ -36,25 +32,39 @@ const char *help =
|
||||
"\n"
|
||||
" --case-ranges\n"
|
||||
" Collapse consecutive cases in a switch statements into a range\n"
|
||||
" of the form case low ... high:. This syntax is an extension of\n"
|
||||
" the C/C++ language, supported by compilers like GCC, Clang and\n"
|
||||
" Tcc. The main advantage over using single cases is smaller gen‐\n"
|
||||
" erated C code and faster generation time, although for some com‐\n"
|
||||
" pilers like Tcc it also results in smaller binary size. This\n"
|
||||
" option doesn't work for the Go backend.\n"
|
||||
" of the form low ... high. This syntax is a C/C++ language exten‐\n"
|
||||
" sion that is supported by compilers like GCC, Clang and Tcc. The\n"
|
||||
" main advantage over using single cases is smaller generated code\n"
|
||||
" and faster generation time, although for some compilers like Tcc\n"
|
||||
" it also results in smaller binary size. This option is sup‐\n"
|
||||
" ported only for C.\n"
|
||||
"\n"
|
||||
" --computed-gotos -g\n"
|
||||
" Optimize conditional jumps using non-standard \"computed goto\"\n"
|
||||
" extension (which must be supported by the compiler). re2c gener‐\n"
|
||||
" ates jump tables only in complex cases with a lot of conditional\n"
|
||||
" branches. Complexity threshold can be configured with\n"
|
||||
" cgoto:threshold configuration. This option implies --bit-vec‐\n"
|
||||
" tors. It is supported only for C.\n"
|
||||
"\n"
|
||||
" --conditions --start-conditions -c\n"
|
||||
" Enable support of Flex-like \"conditions\": multiple interrelated\n"
|
||||
" lexers within one block. This is an alternative to manually\n"
|
||||
" specifying different re2c blocks connected with goto or function\n"
|
||||
" calls.\n"
|
||||
"\n"
|
||||
" --depfile FILE\n"
|
||||
" Write dependency information to FILE in the form of a Makefile\n"
|
||||
" rule <output-file> : <input-file> [include-file ...]. This al‐\n"
|
||||
" lows to track build dependencies in the presence of /*!in‐\n"
|
||||
" clude:re2c*/ directives, so that updating include files triggers\n"
|
||||
" regeneration of the output file. This option requires that -o\n"
|
||||
" --output option is specified.\n"
|
||||
" lows one to track build dependencies in the presence of in‐\n"
|
||||
" clude:re2c directives, so that updating include files triggers\n"
|
||||
" regeneration of the output file. This option depends on the\n"
|
||||
" --output option.\n"
|
||||
"\n"
|
||||
" -e --ecb\n"
|
||||
" Generate a lexer that reads input in EBCDIC encoding. re2c as‐\n"
|
||||
" sumes that character range is 0 -- 0xFF an character size is 1\n"
|
||||
" byte.\n"
|
||||
" --ebcdic --ecb -e\n"
|
||||
" Generate a lexer that reads input in EBCDIC encoding. re2c as‐\n"
|
||||
" sumes that the character range is 0 -- 0xFF and character size\n"
|
||||
" is 1 byte.\n"
|
||||
"\n"
|
||||
" --empty-class <match-empty | match-none | error>\n"
|
||||
" Define the way re2c treats empty character classes. With\n"
|
||||
@@ -72,44 +82,25 @@ const char *help =
|
||||
" surrogates are invalid, but real-world libraries and programs\n"
|
||||
" behave in different ways.\n"
|
||||
"\n"
|
||||
" -f --storable-state\n"
|
||||
" Generate a lexer which can store its inner state. This is use‐\n"
|
||||
" ful in push-model lexers which are stopped by an outer program\n"
|
||||
" when there is not enough input, and then resumed when more input\n"
|
||||
" becomes available. In this mode users should additionally define\n"
|
||||
" YYGETSTATE() and YYSETSTATE(state) macros and variables yych,\n"
|
||||
" yyaccept and state as part of the lexer state.\n"
|
||||
" --flex-syntax -F\n"
|
||||
" Partial support for Flex syntax: in this mode named definitions\n"
|
||||
" don't need the equal sign and the terminating semicolon, and\n"
|
||||
" when used they must be surrounded with curly braces. Names with‐\n"
|
||||
" out curly braces are treated as double-quoted strings.\n"
|
||||
"\n"
|
||||
" -F --flex-syntax\n"
|
||||
" Partial support for Flex syntax: in this mode named definitions\n"
|
||||
" don't need the equal sign and the terminating semicolon, and\n"
|
||||
" when used they must be surrounded by curly braces. Names without\n"
|
||||
" curly braces are treated as double-quoted strings.\n"
|
||||
"\n"
|
||||
" -g --computed-gotos\n"
|
||||
" Optimize conditional jumps using non-standard \"computed goto\"\n"
|
||||
" extension (which must be supported by the compiler). re2c gener‐\n"
|
||||
" ates jump tables only in complex cases with a lot of conditional\n"
|
||||
" branches. Complexity threshold can be configured with\n"
|
||||
" cgoto:threshold configuration. This option implies -b. This op‐\n"
|
||||
" tion doesn't work for the Go backend.\n"
|
||||
" --header --type-header -t HEADER\n"
|
||||
" Generate a HEADER file. The contents of the file can be speci‐\n"
|
||||
" fied with directives header:re2c:on and header:re2c:off. If\n"
|
||||
" conditions are used the header will have a condition enum auto‐\n"
|
||||
" matically appended to it (unless there is an explicit condi‐\n"
|
||||
" tions:re2c directive).\n"
|
||||
"\n"
|
||||
" -I PATH\n"
|
||||
" Add PATH to the list of locations which are used when searching\n"
|
||||
" for include files. This option is useful in combination with\n"
|
||||
" /*!include:re2c ... */ directive. Re2c looks for FILE in the di‐\n"
|
||||
" rectory of including file and in the list of include paths spec‐\n"
|
||||
" ified by -I option.\n"
|
||||
"\n"
|
||||
" -i --no-debug-info\n"
|
||||
" Do not output #line information. This is useful when the gener‐\n"
|
||||
" ated code is tracked by some version control system or IDE.\n"
|
||||
"\n"
|
||||
" --input <default | custom>\n"
|
||||
" Specify the API used by the generated code to interface with\n"
|
||||
" used-defined code. Option default is the C API based on pointer\n"
|
||||
" arithmetic (it is the default for the C backend). Option custom\n"
|
||||
" is the generic API (it is the default for the Go backend).\n"
|
||||
" for include files. This option is useful in combination with in‐\n"
|
||||
" clude:re2c directive. re2c looks for FILE in the directory of\n"
|
||||
" the parent file and in the include locations specified with -I\n"
|
||||
" option.\n"
|
||||
"\n"
|
||||
" --input-encoding <ascii | utf8>\n"
|
||||
" Specify the way re2c parses regular expressions. With ascii\n"
|
||||
@@ -118,14 +109,35 @@ const char *help =
|
||||
" With utf8 re2c handles input as UTF8-encoded and recognizes\n"
|
||||
" multibyte characters.\n"
|
||||
"\n"
|
||||
" --lang <c | go>\n"
|
||||
" Specify the output language. Supported languages are C and Go\n"
|
||||
" (the default is C).\n"
|
||||
" --lang <c | go | rust>\n"
|
||||
" Specify the output language. Supported languages are C, Go and\n"
|
||||
" Rust. The default is C for re2c, Go for re2go and Rust for\n"
|
||||
" re2rust.\n"
|
||||
"\n"
|
||||
" --location-format <gnu | msvc>\n"
|
||||
" Specify location format in messages. With gnu locations are\n"
|
||||
" Specify location format in messages. With gnu locations are\n"
|
||||
" printed as 'filename:line:column: ...'. With msvc locations are\n"
|
||||
" printed as 'filename(line,column) ...'. Default is gnu.\n"
|
||||
" printed as 'filename(line,column) ...'. The default is gnu.\n"
|
||||
"\n"
|
||||
" --loop-switch\n"
|
||||
" Encode DFA in a form of a loop over a switch statement. Individ‐\n"
|
||||
" ual states are switch cases. The current state is stored in a\n"
|
||||
" variable yystate. Transitions between states update yystate to\n"
|
||||
" the case label of the destination state and continue to the head\n"
|
||||
" of the loop. This option is always enabled for Rust, as it has\n"
|
||||
" no goto statement and cannot use the goto/label approach which\n"
|
||||
" is the default for C and Go backends.\n"
|
||||
"\n"
|
||||
" --nested-ifs -s\n"
|
||||
" Use nested if statements instead of switch statements in condi‐\n"
|
||||
" tional jumps. This usually results in more efficient code with\n"
|
||||
" non-optimizing compilers.\n"
|
||||
"\n"
|
||||
" --no-debug-info -i\n"
|
||||
" Do not output line directives. This may be useful when the gen‐\n"
|
||||
" erated code is stored in a version control system (to avoid huge\n"
|
||||
" autogenerated diffs on small changes). This option is on by de‐\n"
|
||||
" fault for Rust, as it does not have line directives.\n"
|
||||
"\n"
|
||||
" --no-generation-date\n"
|
||||
" Suppress date output in the generated file.\n"
|
||||
@@ -133,96 +145,104 @@ const char *help =
|
||||
" --no-version\n"
|
||||
" Suppress version output in the generated file.\n"
|
||||
"\n"
|
||||
" -o OUTPUT --output=OUTPUT\n"
|
||||
" --no-unsafe\n"
|
||||
" Do not generate unsafe wrapper over YYPEEK (this option is spe‐\n"
|
||||
" cific to Rust). For performance reasons YYPEEK should avoid\n"
|
||||
" bounds-checking, as the lexer already performs end-of-input\n"
|
||||
" checks in a more efficient way. The user may choose to provide\n"
|
||||
" a safe YYPEEK definition, or a definition that is unsafe only in\n"
|
||||
" release builds, in which case the --no-unsafe option helps to\n"
|
||||
" avoid warnings about redundant unsafe blocks.\n"
|
||||
"\n"
|
||||
" --output -o OUTPUT\n"
|
||||
" Specify the OUTPUT file.\n"
|
||||
"\n"
|
||||
" -P --posix-captures\n"
|
||||
" --posix-captures -P\n"
|
||||
" Enable submatch extraction with POSIX-style capturing groups.\n"
|
||||
"\n"
|
||||
" -r --reusable\n"
|
||||
" Deprecated since re2c version 2.2 (reusable blocks are allowed\n"
|
||||
" by default now).\n"
|
||||
" --reusable -r\n"
|
||||
" Deprecated since version 2.2 (reusable blocks are allowed by de‐\n"
|
||||
" fault now).\n"
|
||||
"\n"
|
||||
" -S --skeleton\n"
|
||||
" --skeleton -S\n"
|
||||
" Ignore user-defined interface code and generate a self-contained\n"
|
||||
" \"skeleton\" program. Additionally, generate input files with\n"
|
||||
" strings derived from the regular grammar and compressed match\n"
|
||||
" results that are used to verify \"skeleton\" behavior on all in‐\n"
|
||||
" puts. This option is useful for finding bugs in optimizations\n"
|
||||
" and code generation. This option doesn't work for the Go back‐\n"
|
||||
" end.\n"
|
||||
" and code generation. This option is supported only for C.\n"
|
||||
"\n"
|
||||
" -s --nested-ifs\n"
|
||||
" Use nested if statements instead of switch statements in condi‐\n"
|
||||
" tional jumps. This usually results in more efficient code with\n"
|
||||
" non-optimizing compilers.\n"
|
||||
" --storable-state -f\n"
|
||||
" Generate a lexer which can store its inner state. This is use‐\n"
|
||||
" ful in push-model lexers which are stopped by an outer program\n"
|
||||
" when there is not enough input, and then resumed when more input\n"
|
||||
" becomes available. In this mode users should additionally define\n"
|
||||
" YYGETSTATE and YYSETSTATE primitives, and variables yych, yyac‐\n"
|
||||
" cept and state should be part of the stored lexer state.\n"
|
||||
"\n"
|
||||
" -T --tags\n"
|
||||
" --tags -T\n"
|
||||
" Enable submatch extraction with tags.\n"
|
||||
"\n"
|
||||
" -t HEADER --type-header=HEADER\n"
|
||||
" Generate a HEADER file that contains enum with condition names.\n"
|
||||
" Requires -c option.\n"
|
||||
" --ucs2 --wide-chars -w\n"
|
||||
" Generate a lexer that reads UCS2-encoded input. re2c assumes\n"
|
||||
" that the character range is 0 -- 0xFFFF and character size is 2\n"
|
||||
" bytes. This option implies --nested-ifs.\n"
|
||||
"\n"
|
||||
" -u --unicode\n"
|
||||
" Generate a lexer that reads UTF32-encoded input. Re2c assumes\n"
|
||||
" that character range is 0 -- 0x10FFFF and character size is 4\n"
|
||||
" bytes. This option implies -s.\n"
|
||||
" --utf8 --utf-8 -8\n"
|
||||
" Generate a lexer that reads input in UTF-8 encoding. re2c as‐\n"
|
||||
" sumes that the character range is 0 -- 0x10FFFF and character\n"
|
||||
" size is 1 byte.\n"
|
||||
"\n"
|
||||
" -V --vernum\n"
|
||||
" Show version information in MMmmpp format (major, minor, patch).\n"
|
||||
" --utf16 --utf-16 -x\n"
|
||||
" Generate a lexer that reads UTF16-encoded input. re2c assumes\n"
|
||||
" that the character range is 0 -- 0x10FFFF and character size is\n"
|
||||
" 2 bytes. This option implies --nested-ifs.\n"
|
||||
"\n"
|
||||
" --utf32 --unicode -u\n"
|
||||
" Generate a lexer that reads UTF32-encoded input. re2c assumes\n"
|
||||
" that the character range is 0 -- 0x10FFFF and character size is\n"
|
||||
" 4 bytes. This option implies --nested-ifs.\n"
|
||||
"\n"
|
||||
" --verbose\n"
|
||||
" Output a short message in case of success.\n"
|
||||
"\n"
|
||||
" -v --version\n"
|
||||
" --vernum -V\n"
|
||||
" Show version information in MMmmpp format (major, minor, patch).\n"
|
||||
"\n"
|
||||
" --version -v\n"
|
||||
" Show version information.\n"
|
||||
"\n"
|
||||
" -w --wide-chars\n"
|
||||
" Generate a lexer that reads UCS2-encoded input. Re2c assumes\n"
|
||||
" that character range is 0 -- 0xFFFF and character size is 2\n"
|
||||
" bytes. This option implies -s.\n"
|
||||
" --single-pass -1\n"
|
||||
" Deprecated. Does nothing (single pass is the default now).\n"
|
||||
"\n"
|
||||
" -x --utf-16\n"
|
||||
" Generate a lexer that reads UTF16-encoded input. Re2c assumes\n"
|
||||
" that character range is 0 -- 0x10FFFF and character size is 2\n"
|
||||
" bytes. This option implies -s.\n"
|
||||
"\n"
|
||||
" -D --emit-dot\n"
|
||||
" Instead of normal output generate lexer graph in .dot format.\n"
|
||||
" The output can be converted to an image with the help of\n"
|
||||
" Graphviz (e.g. something like dot -Tpng -odfa.png dfa.dot).\n"
|
||||
"\n"
|
||||
" -d --debug-output\n"
|
||||
" Emit YYDEBUG in the generated code. YYDEBUG should be defined\n"
|
||||
" by the user in the form of a void function with two parameters:\n"
|
||||
" state (lexer state or -1) and symbol (current input symbol of\n"
|
||||
" type YYCTYPE).\n"
|
||||
" --debug-output -d\n"
|
||||
" Emit YYDEBUG invocations in the generated code. This is useful\n"
|
||||
" to trace lexer execution.\n"
|
||||
"\n"
|
||||
" --dump-adfa\n"
|
||||
" Debug option: output DFA after tunneling (in .dot format).\n"
|
||||
"\n"
|
||||
" --dump-cfg\n"
|
||||
" Debug option: output control flow graph of tag variables (in\n"
|
||||
" Debug option: output control flow graph of tag variables (in\n"
|
||||
" .dot format).\n"
|
||||
"\n"
|
||||
" --dump-closure-stats\n"
|
||||
" Debug option: output statistics on the number of states in clo‐\n"
|
||||
" Debug option: output statistics on the number of states in clo‐\n"
|
||||
" sure.\n"
|
||||
"\n"
|
||||
" --dump-dfa-det\n"
|
||||
" Debug option: output DFA immediately after determinization (in\n"
|
||||
" Debug option: output DFA immediately after determinization (in\n"
|
||||
" .dot format).\n"
|
||||
"\n"
|
||||
" --dump-dfa-min\n"
|
||||
" Debug option: output DFA after minimization (in .dot format).\n"
|
||||
"\n"
|
||||
" --dump-dfa-tagopt\n"
|
||||
" Debug option: output DFA after tag optimizations (in .dot for‐\n"
|
||||
" Debug option: output DFA after tag optimizations (in .dot for‐\n"
|
||||
" mat).\n"
|
||||
"\n"
|
||||
" --dump-dfa-tree\n"
|
||||
" Debug option: output DFA under construction with states repre‐\n"
|
||||
" Debug option: output DFA under construction with states repre‐\n"
|
||||
" sented as tag history trees (in .dot format).\n"
|
||||
"\n"
|
||||
" --dump-dfa-raw\n"
|
||||
@@ -230,75 +250,80 @@ const char *help =
|
||||
" state-sets (in .dot format).\n"
|
||||
"\n"
|
||||
" --dump-interf\n"
|
||||
" Debug option: output interference table produced by liveness\n"
|
||||
" Debug option: output interference table produced by liveness\n"
|
||||
" analysis of tag variables.\n"
|
||||
"\n"
|
||||
" --dump-nfa\n"
|
||||
" Debug option: output NFA (in .dot format).\n"
|
||||
"\n"
|
||||
" --emit-dot -D\n"
|
||||
" Instead of normal output generate lexer graph in .dot format.\n"
|
||||
" The output can be converted to an image with the help of\n"
|
||||
" Graphviz (e.g. something like dot -Tpng -odfa.png dfa.dot).\n"
|
||||
"\n"
|
||||
" --dfa-minimization <moore | table>\n"
|
||||
" Internal option: DFA minimization algorithm used by re2c. The\n"
|
||||
" Internal option: DFA minimization algorithm used by re2c. The\n"
|
||||
" moore option is the Moore algorithm (it is the default). The ta‐\n"
|
||||
" ble option is the \"table filling\" algorithm. Both algorithms\n"
|
||||
" ble option is the \"table filling\" algorithm. Both algorithms\n"
|
||||
" should produce the same DFA up to states relabeling; table fill‐\n"
|
||||
" ing is simpler and much slower and serves as a reference imple‐\n"
|
||||
" ing is simpler and much slower and serves as a reference imple‐\n"
|
||||
" mentation.\n"
|
||||
"\n"
|
||||
" --eager-skip\n"
|
||||
" Internal option: make the generated lexer advance the input po‐\n"
|
||||
" sition eagerly -- immediately after reading the input symbol.\n"
|
||||
" Internal option: make the generated lexer advance the input po‐\n"
|
||||
" sition eagerly -- immediately after reading the input symbol.\n"
|
||||
" This changes the default behavior when the input position is ad‐\n"
|
||||
" vanced lazily -- after transition to the next state. This option\n"
|
||||
" is implied by --no-lookahead.\n"
|
||||
"\n"
|
||||
" --no-lookahead\n"
|
||||
" Internal option: use TDFA(0) instead of TDFA(1). This option\n"
|
||||
" Internal option: use TDFA(0) instead of TDFA(1). This option\n"
|
||||
" has effect only with --tags or --posix-captures options.\n"
|
||||
"\n"
|
||||
" --no-optimize-tags\n"
|
||||
" Internal optionL: suppress optimization of tag variables (useful\n"
|
||||
" Internal option: suppress optimization of tag variables (useful\n"
|
||||
" for debugging).\n"
|
||||
"\n"
|
||||
" --posix-closure <gor1 | gtop>\n"
|
||||
" Internal option: specify shortest-path algorithm used for the\n"
|
||||
" Internal option: specify shortest-path algorithm used for the\n"
|
||||
" construction of epsilon-closure with POSIX disambiguation seman‐\n"
|
||||
" tics: gor1 (the default) stands for Goldberg-Radzik algorithm,\n"
|
||||
" tics: gor1 (the default) stands for Goldberg-Radzik algorithm,\n"
|
||||
" and gtop stands for \"global topological order\" algorithm.\n"
|
||||
"\n"
|
||||
" --posix-prectable <complex | naive>\n"
|
||||
" Internal option: specify the algorithm used to compute POSIX\n"
|
||||
" precedence table. The complex algorithm computes precedence ta‐\n"
|
||||
" ble in one traversal of tag history tree and has quadratic com‐\n"
|
||||
" plexity in the number of TNFA states; it is the default. The\n"
|
||||
" Internal option: specify the algorithm used to compute POSIX\n"
|
||||
" precedence table. The complex algorithm computes precedence ta‐\n"
|
||||
" ble in one traversal of tag history tree and has quadratic com‐\n"
|
||||
" plexity in the number of TNFA states; it is the default. The\n"
|
||||
" naive algorithm has worst-case cubic complexity in the number of\n"
|
||||
" TNFA states, but it is much simpler than complex and may be\n"
|
||||
" TNFA states, but it is much simpler than complex and may be\n"
|
||||
" slightly faster in non-pathological cases.\n"
|
||||
"\n"
|
||||
" --stadfa\n"
|
||||
" Internal option: use staDFA algorithm for submatch extraction.\n"
|
||||
" The main difference with TDFA is that tag operations in staDFA\n"
|
||||
" Internal option: use staDFA algorithm for submatch extraction.\n"
|
||||
" The main difference with TDFA is that tag operations in staDFA\n"
|
||||
" are placed in states, not on transitions.\n"
|
||||
"\n"
|
||||
" --fixed-tags <none | toplevel | all>\n"
|
||||
" Internal option: specify whether the fixed-tag optimization\n"
|
||||
" should be applied to all tags (all), none of them (none), or\n"
|
||||
" only those in toplevel concatenation (toplevel). The default is\n"
|
||||
" all. \"Fixed\" tags are those that are located within a fixed\n"
|
||||
" distance to some other tag (called \"base\"). In such cases only\n"
|
||||
" tha base tag needs to be tracked, and the value of the fixed tag\n"
|
||||
" can be computed as the value of the base tag plus a static off‐\n"
|
||||
" set. For tags that are under alternative or repetition it is\n"
|
||||
" Internal option: specify whether the fixed-tag optimization\n"
|
||||
" should be applied to all tags (all), none of them (none), or\n"
|
||||
" only those in toplevel concatenation (toplevel). The default is\n"
|
||||
" all. \"Fixed\" tags are those that are located within a fixed\n"
|
||||
" distance to some other tag (called \"base\"). In such cases only\n"
|
||||
" the base tag needs to be tracked, and the value of the fixed tag\n"
|
||||
" can be computed as the value of the base tag plus a static off‐\n"
|
||||
" set. For tags that are under alternative or repetition it is\n"
|
||||
" also necessary to check if the base tag has a no-match value (in\n"
|
||||
" that case fixed tag should also be set to no-match, disregarding\n"
|
||||
" the offset). For tags in top-level concatenation the check is\n"
|
||||
" the offset). For tags in top-level concatenation the check is\n"
|
||||
" not needed, because they always match.\n"
|
||||
"\n"
|
||||
"WARNINGS\n"
|
||||
" -W Turn on all warnings.\n"
|
||||
"\n"
|
||||
" -Werror\n"
|
||||
" Turn warnings into errors. Note that this option alone doesn't\n"
|
||||
" turn on any warnings; it only affects those warnings that have\n"
|
||||
" Turn warnings into errors. Note that this option alone doesn't\n"
|
||||
" turn on any warnings; it only affects those warnings that have\n"
|
||||
" been turned on so far or will be turned on later.\n"
|
||||
"\n"
|
||||
" -W<warning>\n"
|
||||
@@ -308,63 +333,63 @@ const char *help =
|
||||
" Turn off warning.\n"
|
||||
"\n"
|
||||
" -Werror-<warning>\n"
|
||||
" Turn on warning and treat it as an error (this implies -W<warn‐\n"
|
||||
" Turn on warning and treat it as an error (this implies -W<warn‐\n"
|
||||
" ing>).\n"
|
||||
"\n"
|
||||
" -Wno-error-<warning>\n"
|
||||
" Don't treat this particular warning as an error. This doesn't\n"
|
||||
" Don't treat this particular warning as an error. This doesn't\n"
|
||||
" turn off the warning itself.\n"
|
||||
"\n"
|
||||
" -Wcondition-order\n"
|
||||
" Warn if the generated program makes implicit assumptions about\n"
|
||||
" condition numbering. One should use either the -t, --type-header\n"
|
||||
" option or the /*!types:re2c*/ directive to generate a mapping of\n"
|
||||
" condition names to numbers and then use the autogenerated condi‐\n"
|
||||
" tion names.\n"
|
||||
" Warn if the generated program makes implicit assumptions about\n"
|
||||
" condition numbering. One should use either the ---header option\n"
|
||||
" or the conditions:re2c directive to generate a mapping of condi‐\n"
|
||||
" tion names to numbers and then use the autogenerated condition\n"
|
||||
" names.\n"
|
||||
"\n"
|
||||
" -Wempty-character-class\n"
|
||||
" Warn if a regular expression contains an empty character class.\n"
|
||||
" Trying to match an empty character class makes no sense: it\n"
|
||||
" should always fail. However, for backwards compatibility rea‐\n"
|
||||
" sons re2c allows empty character classes and treats them as\n"
|
||||
" empty strings. Use the --empty-class option to change the de‐\n"
|
||||
" Warn if a regular expression contains an empty character class.\n"
|
||||
" Trying to match an empty character class makes no sense: it\n"
|
||||
" should always fail. However, for backwards compatibility rea‐\n"
|
||||
" sons re2c permits empty character classes and treats them as\n"
|
||||
" empty strings. Use the --empty-class option to change the de‐\n"
|
||||
" fault behavior.\n"
|
||||
"\n"
|
||||
" -Wmatch-empty-string\n"
|
||||
" Warn if a rule is nullable (matches an empty string). If the\n"
|
||||
" lexer runs in a loop and the empty match is unintentional, the\n"
|
||||
" Warn if a rule is nullable (matches an empty string). If the\n"
|
||||
" lexer runs in a loop and the empty match is unintentional, the\n"
|
||||
" lexer may unexpectedly hang in an infinite loop.\n"
|
||||
"\n"
|
||||
" -Wswapped-range\n"
|
||||
" Warn if the lower bound of a range is greater than its upper\n"
|
||||
" bound. The default behavior is to silently swap the range\n"
|
||||
" Warn if the lower bound of a range is greater than its upper\n"
|
||||
" bound. The default behavior is to silently swap the range\n"
|
||||
" bounds.\n"
|
||||
"\n"
|
||||
" -Wundefined-control-flow\n"
|
||||
" Warn if some input strings cause undefined control flow in the\n"
|
||||
" lexer (the faulty patterns are reported). This is the most dan‐\n"
|
||||
" gerous and most common mistake. It can be easily fixed by adding\n"
|
||||
" the default rule * which has the lowest priority, matches any\n"
|
||||
" code unit, and consumes exactly one code unit.\n"
|
||||
" Warn if some input strings cause undefined control flow in the\n"
|
||||
" lexer (the faulty patterns are reported). This is a dangerous\n"
|
||||
" and common mistake. It can be easily fixed by adding the default\n"
|
||||
" rule * which has the lowest priority, matches any code unit, and\n"
|
||||
" always consumes a single code unit.\n"
|
||||
"\n"
|
||||
" -Wunreachable-rules\n"
|
||||
" Warn about rules that are shadowed by other rules and will never\n"
|
||||
" match.\n"
|
||||
"\n"
|
||||
" -Wuseless-escape\n"
|
||||
" Warn if a symbol is escaped when it shouldn't be. By default,\n"
|
||||
" re2c silently ignores such escapes, but this may as well indi‐\n"
|
||||
" Warn if a symbol is escaped when it shouldn't be. By default,\n"
|
||||
" re2c silently ignores such escapes, but this may as well indi‐\n"
|
||||
" cate a typo or an error in the escape sequence.\n"
|
||||
"\n"
|
||||
" -Wnondeterministic-tags\n"
|
||||
" Warn if a tag has n-th degree of nondeterminism, where n is\n"
|
||||
" Warn if a tag has n-th degree of nondeterminism, where n is\n"
|
||||
" greater than 1.\n"
|
||||
"\n"
|
||||
" -Wsentinel-in-midrule\n"
|
||||
" Warn if the sentinel symbol occurs in the middle of a rule ---\n"
|
||||
" this may cause reads past the end of buffer, crashes or memory\n"
|
||||
" Warn if the sentinel symbol occurs in the middle of a rule ---\n"
|
||||
" this may cause reads past the end of buffer, crashes or memory\n"
|
||||
" corruption in the generated lexer. This warning is only applica‐\n"
|
||||
" ble if the sentinel method of checking for the end of input is\n"
|
||||
" used. It is set to an error if re2c:sentinel configuration is\n"
|
||||
" ble if the sentinel method of checking for the end of input is\n"
|
||||
" used. It is set to an error if re2c:sentinel configuration is\n"
|
||||
" used.\n"
|
||||
;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Generated by re2c 2.1.1 on Fri Jul 16 08:56:28 2021 */
|
||||
/* Generated by re2c 3.0 on Thu Jan 27 08:39:55 2022 */
|
||||
#line 1 "../src/msg/ver_to_vernum.re"
|
||||
#include <stddef.h>
|
||||
#include "src/util/c99_stdint.h"
|
||||
@@ -66,35 +66,35 @@ const char *yyt6;
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
yych = *YYCURSOR;
|
||||
if (yych <= '/') goto yy2;
|
||||
if (yych <= '/') goto yy1;
|
||||
if (yych <= '9') {
|
||||
yyt1 = YYCURSOR;
|
||||
goto yy4;
|
||||
goto yy3;
|
||||
}
|
||||
yy2:
|
||||
yy1:
|
||||
++YYCURSOR;
|
||||
yy3:
|
||||
yy2:
|
||||
#line 51 "../src/msg/ver_to_vernum.re"
|
||||
{ return std::string(); }
|
||||
#line 80 "src/msg/ver_to_vernum.cc"
|
||||
yy4:
|
||||
yy3:
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if (yych <= '.') {
|
||||
if (yych <= 0x00) {
|
||||
yyt3 = yyt4 = yyt5 = yyt6 = NULL;
|
||||
yyt2 = YYCURSOR;
|
||||
goto yy5;
|
||||
goto yy4;
|
||||
}
|
||||
if (yych <= '-') goto yy3;
|
||||
if (yych <= '-') goto yy2;
|
||||
yyt3 = yyt4 = yyt5 = yyt6 = NULL;
|
||||
yyt2 = YYCURSOR;
|
||||
goto yy7;
|
||||
goto yy5;
|
||||
} else {
|
||||
if (yych <= '/') goto yy3;
|
||||
if (yych <= '9') goto yy9;
|
||||
goto yy3;
|
||||
if (yych <= '/') goto yy2;
|
||||
if (yych <= '9') goto yy7;
|
||||
goto yy2;
|
||||
}
|
||||
yy5:
|
||||
yy4:
|
||||
++YYCURSOR;
|
||||
p1 = yyt1;
|
||||
e1 = yyt2;
|
||||
@@ -121,125 +121,125 @@ yy5:
|
||||
return std::string(buffer, SIZE);
|
||||
}
|
||||
#line 124 "src/msg/ver_to_vernum.cc"
|
||||
yy7:
|
||||
yy5:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= 0x00) goto yy8;
|
||||
if (yych <= '/') goto yy12;
|
||||
if (yych <= 0x00) goto yy6;
|
||||
if (yych <= '/') goto yy10;
|
||||
if (yych <= '9') {
|
||||
yyt3 = YYCURSOR;
|
||||
goto yy10;
|
||||
goto yy8;
|
||||
}
|
||||
goto yy12;
|
||||
yy8:
|
||||
goto yy10;
|
||||
yy6:
|
||||
YYCURSOR = YYMARKER;
|
||||
goto yy3;
|
||||
yy9:
|
||||
goto yy2;
|
||||
yy7:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= 0x00) {
|
||||
yyt3 = yyt4 = yyt5 = yyt6 = NULL;
|
||||
yyt2 = YYCURSOR;
|
||||
goto yy5;
|
||||
goto yy4;
|
||||
}
|
||||
if (yych == '.') {
|
||||
yyt3 = yyt4 = yyt5 = yyt6 = NULL;
|
||||
yyt2 = YYCURSOR;
|
||||
goto yy7;
|
||||
goto yy5;
|
||||
}
|
||||
goto yy8;
|
||||
yy10:
|
||||
goto yy6;
|
||||
yy8:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= '.') {
|
||||
if (yych <= 0x00) {
|
||||
yyt5 = yyt6 = NULL;
|
||||
yyt4 = YYCURSOR;
|
||||
goto yy5;
|
||||
goto yy4;
|
||||
}
|
||||
if (yych <= '-') goto yy8;
|
||||
if (yych <= '-') goto yy6;
|
||||
yyt5 = yyt6 = NULL;
|
||||
yyt4 = YYCURSOR;
|
||||
goto yy13;
|
||||
goto yy11;
|
||||
} else {
|
||||
if (yych <= '/') goto yy8;
|
||||
if (yych <= '9') goto yy14;
|
||||
goto yy8;
|
||||
if (yych <= '/') goto yy6;
|
||||
if (yych <= '9') goto yy12;
|
||||
goto yy6;
|
||||
}
|
||||
yy9:
|
||||
yych = *++YYCURSOR;
|
||||
yy10:
|
||||
if (yybm[0+yych] & 128) {
|
||||
goto yy9;
|
||||
}
|
||||
if (yych <= 0x00) goto yy4;
|
||||
goto yy6;
|
||||
yy11:
|
||||
yych = *++YYCURSOR;
|
||||
yy12:
|
||||
if (yybm[0+yych] & 128) {
|
||||
goto yy11;
|
||||
}
|
||||
if (yych <= 0x00) goto yy5;
|
||||
goto yy8;
|
||||
yy13:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= 0x00) goto yy8;
|
||||
if (yych <= '/') goto yy12;
|
||||
if (yych <= 0x00) goto yy6;
|
||||
if (yych <= '/') goto yy10;
|
||||
if (yych <= '9') {
|
||||
yyt5 = YYCURSOR;
|
||||
goto yy15;
|
||||
goto yy13;
|
||||
}
|
||||
goto yy12;
|
||||
yy14:
|
||||
goto yy10;
|
||||
yy12:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= 0x00) {
|
||||
yyt5 = yyt6 = NULL;
|
||||
yyt4 = YYCURSOR;
|
||||
goto yy5;
|
||||
goto yy4;
|
||||
}
|
||||
if (yych == '.') {
|
||||
yyt5 = yyt6 = NULL;
|
||||
yyt4 = YYCURSOR;
|
||||
goto yy13;
|
||||
goto yy11;
|
||||
}
|
||||
goto yy8;
|
||||
yy15:
|
||||
goto yy6;
|
||||
yy13:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= '.') {
|
||||
if (yych <= 0x00) {
|
||||
yyt6 = YYCURSOR;
|
||||
goto yy5;
|
||||
goto yy4;
|
||||
}
|
||||
if (yych <= '-') goto yy8;
|
||||
if (yych <= '-') goto yy6;
|
||||
yyt6 = YYCURSOR;
|
||||
} else {
|
||||
if (yych <= '/') goto yy8;
|
||||
if (yych <= '9') goto yy17;
|
||||
goto yy8;
|
||||
if (yych <= '/') goto yy6;
|
||||
if (yych <= '9') goto yy15;
|
||||
goto yy6;
|
||||
}
|
||||
yy16:
|
||||
yy14:
|
||||
yych = *++YYCURSOR;
|
||||
if (yybm[0+yych] & 128) {
|
||||
goto yy11;
|
||||
goto yy9;
|
||||
}
|
||||
if (yych <= '/') goto yy8;
|
||||
if (yych <= '9') goto yy18;
|
||||
goto yy8;
|
||||
yy17:
|
||||
if (yych <= '/') goto yy6;
|
||||
if (yych <= '9') goto yy16;
|
||||
goto yy6;
|
||||
yy15:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= 0x00) {
|
||||
yyt6 = YYCURSOR;
|
||||
goto yy5;
|
||||
goto yy4;
|
||||
}
|
||||
if (yych == '.') {
|
||||
yyt6 = YYCURSOR;
|
||||
goto yy16;
|
||||
goto yy14;
|
||||
}
|
||||
goto yy8;
|
||||
yy18:
|
||||
goto yy6;
|
||||
yy16:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= '.') {
|
||||
if (yych <= 0x00) goto yy5;
|
||||
if (yych <= '-') goto yy8;
|
||||
goto yy16;
|
||||
if (yych <= 0x00) goto yy4;
|
||||
if (yych <= '-') goto yy6;
|
||||
goto yy14;
|
||||
} else {
|
||||
if (yych <= '/') goto yy8;
|
||||
if (yych >= ':') goto yy8;
|
||||
if (yych <= '/') goto yy6;
|
||||
if (yych >= ':') goto yy6;
|
||||
}
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= 0x00) goto yy5;
|
||||
if (yych == '.') goto yy16;
|
||||
goto yy8;
|
||||
if (yych <= 0x00) goto yy4;
|
||||
if (yych == '.') goto yy14;
|
||||
goto yy6;
|
||||
}
|
||||
#line 52 "../src/msg/ver_to_vernum.re"
|
||||
|
||||
|
||||
+2935
-2788
File diff suppressed because it is too large
Load Diff
+2592
-2302
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/* Generated by re2c 2.1.1 on Fri Jul 16 08:52:38 2021 */
|
||||
/* Generated by re2c 3.0 on Thu Jan 27 08:39:55 2022 */
|
||||
|
||||
#ifndef _RE2C_PARSE_LEX_
|
||||
#define _RE2C_PARSE_LEX_
|
||||
|
||||
+3268
-3020
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/* A Bison parser, made by GNU Bison 3.7.6. */
|
||||
/* A Bison parser, made by GNU Bison 3.8.2. */
|
||||
|
||||
/* Bison implementation for Yacc-like parsers in C
|
||||
|
||||
@@ -46,10 +46,10 @@
|
||||
USER NAME SPACE" below. */
|
||||
|
||||
/* Identify Bison output, and Bison version. */
|
||||
#define YYBISON 30706
|
||||
#define YYBISON 30802
|
||||
|
||||
/* Bison version string. */
|
||||
#define YYBISON_VERSION "3.7.6"
|
||||
#define YYBISON_VERSION "3.8.2"
|
||||
|
||||
/* Skeleton name. */
|
||||
#define YYSKELETON_NAME "yacc.c"
|
||||
@@ -324,12 +324,18 @@ typedef int yy_state_fast_t;
|
||||
# define YY_USE(E) /* empty */
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
|
||||
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
|
||||
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
|
||||
#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__
|
||||
# if __GNUC__ * 100 + __GNUC_MINOR__ < 407
|
||||
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
|
||||
_Pragma ("GCC diagnostic push") \
|
||||
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")
|
||||
# else
|
||||
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
|
||||
_Pragma ("GCC diagnostic push") \
|
||||
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
|
||||
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
|
||||
# endif
|
||||
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
|
||||
_Pragma ("GCC diagnostic pop")
|
||||
#else
|
||||
@@ -545,7 +551,7 @@ static const yytype_int8 yytranslate[] =
|
||||
};
|
||||
|
||||
#if YYDEBUG
|
||||
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
|
||||
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
|
||||
static const yytype_uint8 yyrline[] =
|
||||
{
|
||||
0, 69, 69, 70, 74, 77, 78, 79, 83, 89,
|
||||
@@ -584,17 +590,6 @@ yysymbol_name (yysymbol_kind_t yysymbol)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef YYPRINT
|
||||
/* YYTOKNUM[NUM] -- (External) token number corresponding to the
|
||||
(internal) symbol number NUM (which must be that of a token). */
|
||||
static const yytype_int16 yytoknum[] =
|
||||
{
|
||||
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
|
||||
265, 266, 267, 268, 269, 270, 271, 47, 61, 59,
|
||||
42, 36, 124, 92, 43, 63, 40, 41
|
||||
};
|
||||
#endif
|
||||
|
||||
#define YYPACT_NINF (-20)
|
||||
|
||||
#define yypact_value_is_default(Yyn) \
|
||||
@@ -605,8 +600,8 @@ static const yytype_int16 yytoknum[] =
|
||||
#define yytable_value_is_error(Yyn) \
|
||||
0
|
||||
|
||||
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
|
||||
STATE-NUM. */
|
||||
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
|
||||
STATE-NUM. */
|
||||
static const yytype_int8 yypact[] =
|
||||
{
|
||||
-20, 0, -20, 8, -1, 21, -20, -9, -20, -20,
|
||||
@@ -618,9 +613,9 @@ static const yytype_int8 yypact[] =
|
||||
-20, -20
|
||||
};
|
||||
|
||||
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
|
||||
Performed when YYTABLE does not specify something else to do. Zero
|
||||
means the default is an error. */
|
||||
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
|
||||
Performed when YYTABLE does not specify something else to do. Zero
|
||||
means the default is an error. */
|
||||
static const yytype_int8 yydefact[] =
|
||||
{
|
||||
2, 0, 1, 0, 0, 0, 4, 42, 11, 7,
|
||||
@@ -632,23 +627,23 @@ static const yytype_int8 yydefact[] =
|
||||
30, 37
|
||||
};
|
||||
|
||||
/* YYPGOTO[NTERM-NUM]. */
|
||||
/* YYPGOTO[NTERM-NUM]. */
|
||||
static const yytype_int8 yypgoto[] =
|
||||
{
|
||||
-20, -20, -20, -20, -20, -20, 24, 52, -12, 16,
|
||||
-19, -20, -20, 11, -20
|
||||
};
|
||||
|
||||
/* YYDEFGOTO[NTERM-NUM]. */
|
||||
/* YYDEFGOTO[NTERM-NUM]. */
|
||||
static const yytype_int8 yydefgoto[] =
|
||||
{
|
||||
0, 1, 15, 16, 57, 17, 32, 18, 19, 20,
|
||||
21, 22, 47, 48, 23
|
||||
};
|
||||
|
||||
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
|
||||
positive, shift that token. If negative, reduce the rule whose
|
||||
number is the opposite. If YYTABLE_NINF, syntax error. */
|
||||
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
|
||||
positive, shift that token. If negative, reduce the rule whose
|
||||
number is the opposite. If YYTABLE_NINF, syntax error. */
|
||||
static const yytype_int8 yytable[] =
|
||||
{
|
||||
2, 43, 36, 42, 37, 3, 4, 5, 28, 33,
|
||||
@@ -669,8 +664,8 @@ static const yytype_int8 yycheck[] =
|
||||
26, 27, 9, 9, 22, 3, 40, -1, 47
|
||||
};
|
||||
|
||||
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
|
||||
symbol of state STATE-NUM. */
|
||||
/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
|
||||
state STATE-NUM. */
|
||||
static const yytype_int8 yystos[] =
|
||||
{
|
||||
0, 29, 0, 5, 6, 7, 10, 11, 12, 14,
|
||||
@@ -682,7 +677,7 @@ static const yytype_int8 yystos[] =
|
||||
38, 41
|
||||
};
|
||||
|
||||
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
|
||||
/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */
|
||||
static const yytype_int8 yyr1[] =
|
||||
{
|
||||
0, 28, 29, 29, 29, 29, 29, 29, 30, 30,
|
||||
@@ -692,7 +687,7 @@ static const yytype_int8 yyr1[] =
|
||||
41, 42, 42, 42
|
||||
};
|
||||
|
||||
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
|
||||
/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */
|
||||
static const yytype_int8 yyr2[] =
|
||||
{
|
||||
0, 2, 0, 2, 2, 2, 2, 2, 3, 3,
|
||||
@@ -711,6 +706,7 @@ enum { YYENOMEM = -2 };
|
||||
#define YYACCEPT goto yyacceptlab
|
||||
#define YYABORT goto yyabortlab
|
||||
#define YYERROR goto yyerrorlab
|
||||
#define YYNOMEM goto yyexhaustedlab
|
||||
|
||||
|
||||
#define YYRECOVERING() (!!yyerrstatus)
|
||||
@@ -751,10 +747,7 @@ do { \
|
||||
YYFPRINTF Args; \
|
||||
} while (0)
|
||||
|
||||
/* This macro is provided for backward compatibility. */
|
||||
# ifndef YY_LOCATION_PRINT
|
||||
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
|
||||
@@ -782,10 +775,6 @@ yy_symbol_value_print (FILE *yyo,
|
||||
YY_USE (context);
|
||||
if (!yyvaluep)
|
||||
return;
|
||||
# ifdef YYPRINT
|
||||
if (yykind < YYNTOKENS)
|
||||
YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
|
||||
# endif
|
||||
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
|
||||
YY_USE (yykind);
|
||||
YY_IGNORE_MAYBE_UNINITIALIZED_END
|
||||
@@ -971,6 +960,7 @@ yyparse (re2c::context_t &context)
|
||||
YYDPRINTF ((stderr, "Starting parse\n"));
|
||||
|
||||
yychar = YYEMPTY; /* Cause a token to be read. */
|
||||
|
||||
goto yysetstate;
|
||||
|
||||
|
||||
@@ -996,7 +986,7 @@ yysetstate:
|
||||
|
||||
if (yyss + yystacksize - 1 <= yyssp)
|
||||
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
|
||||
goto yyexhaustedlab;
|
||||
YYNOMEM;
|
||||
#else
|
||||
{
|
||||
/* Get the current used size of the three stacks, in elements. */
|
||||
@@ -1024,7 +1014,7 @@ yysetstate:
|
||||
# else /* defined YYSTACK_RELOCATE */
|
||||
/* Extend the stack our own way. */
|
||||
if (YYMAXDEPTH <= yystacksize)
|
||||
goto yyexhaustedlab;
|
||||
YYNOMEM;
|
||||
yystacksize *= 2;
|
||||
if (YYMAXDEPTH < yystacksize)
|
||||
yystacksize = YYMAXDEPTH;
|
||||
@@ -1035,7 +1025,7 @@ yysetstate:
|
||||
YY_CAST (union yyalloc *,
|
||||
YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
|
||||
if (! yyptr)
|
||||
goto yyexhaustedlab;
|
||||
YYNOMEM;
|
||||
YYSTACK_RELOCATE (yyss_alloc, yyss);
|
||||
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
|
||||
# undef YYSTACK_RELOCATE
|
||||
@@ -1057,6 +1047,7 @@ yysetstate:
|
||||
}
|
||||
#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
|
||||
|
||||
|
||||
if (yystate == YYFINAL)
|
||||
YYACCEPT;
|
||||
|
||||
@@ -1171,10 +1162,10 @@ yyreduce:
|
||||
case 3: /* spec: spec TOKEN_BLOCK */
|
||||
#line 70 "../src/parse/parser.ypp"
|
||||
{
|
||||
use_block(context, *(yyvsp[0].str), context.input.tok_loc(), context.input.msg);
|
||||
use_block(context, *(yyvsp[0].str), context.input.tok_loc());
|
||||
delete (yyvsp[0].str);
|
||||
}
|
||||
#line 1178 "src/parse/parser.cc"
|
||||
#line 1169 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 4: /* spec: spec TOKEN_CONF */
|
||||
@@ -1182,7 +1173,7 @@ yyreduce:
|
||||
{
|
||||
context.input.lex_conf(context.opts);
|
||||
}
|
||||
#line 1186 "src/parse/parser.cc"
|
||||
#line 1177 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 8: /* def: name expr enddef */
|
||||
@@ -1192,7 +1183,7 @@ yyreduce:
|
||||
context.input.msg);
|
||||
delete (yyvsp[-2].str);
|
||||
}
|
||||
#line 1196 "src/parse/parser.cc"
|
||||
#line 1187 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 9: /* def: name expr '/' */
|
||||
@@ -1202,13 +1193,13 @@ yyreduce:
|
||||
, "trailing contexts are not allowed in named definitions");
|
||||
exit(1);
|
||||
}
|
||||
#line 1206 "src/parse/parser.cc"
|
||||
#line 1197 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 10: /* name: TOKEN_ID '=' */
|
||||
#line 96 "../src/parse/parser.ypp"
|
||||
{ (yyval.str) = (yyvsp[-1].str); }
|
||||
#line 1212 "src/parse/parser.cc"
|
||||
#line 1203 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 14: /* rule: trailexpr TOKEN_CODE */
|
||||
@@ -1216,7 +1207,7 @@ yyreduce:
|
||||
{
|
||||
find_or_add_spec(context.specs, "").rules.push_back(ASTRule((yyvsp[-1].regexp), (yyvsp[0].semact)));
|
||||
}
|
||||
#line 1220 "src/parse/parser.cc"
|
||||
#line 1211 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 15: /* rule: '*' TOKEN_CODE */
|
||||
@@ -1224,7 +1215,7 @@ yyreduce:
|
||||
{
|
||||
find_or_add_spec(context.specs, "").defs.push_back((yyvsp[0].semact));
|
||||
}
|
||||
#line 1228 "src/parse/parser.cc"
|
||||
#line 1219 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 16: /* rule: '$' TOKEN_CODE */
|
||||
@@ -1232,7 +1223,7 @@ yyreduce:
|
||||
{
|
||||
find_or_add_spec(context.specs, "").eofs.push_back((yyvsp[0].semact));
|
||||
}
|
||||
#line 1236 "src/parse/parser.cc"
|
||||
#line 1227 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 17: /* rule: TOKEN_CLIST trailexpr ccode */
|
||||
@@ -1243,7 +1234,7 @@ yyreduce:
|
||||
}
|
||||
delete (yyvsp[-2].clist);
|
||||
}
|
||||
#line 1247 "src/parse/parser.cc"
|
||||
#line 1238 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 18: /* rule: TOKEN_CLIST '*' ccode */
|
||||
@@ -1254,7 +1245,7 @@ yyreduce:
|
||||
}
|
||||
delete (yyvsp[-2].clist);
|
||||
}
|
||||
#line 1258 "src/parse/parser.cc"
|
||||
#line 1249 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 19: /* rule: TOKEN_CLIST '$' ccode */
|
||||
@@ -1265,7 +1256,7 @@ yyreduce:
|
||||
}
|
||||
delete (yyvsp[-2].clist);
|
||||
}
|
||||
#line 1269 "src/parse/parser.cc"
|
||||
#line 1260 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 20: /* rule: TOKEN_CSETUP TOKEN_CODE */
|
||||
@@ -1276,7 +1267,7 @@ yyreduce:
|
||||
}
|
||||
delete (yyvsp[-1].clist);
|
||||
}
|
||||
#line 1280 "src/parse/parser.cc"
|
||||
#line 1271 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 21: /* rule: TOKEN_CZERO ccode */
|
||||
@@ -1286,7 +1277,7 @@ yyreduce:
|
||||
find_or_add_spec(context.specs, "0").rules.push_back(ASTRule(r, (yyvsp[0].semact)));
|
||||
delete (yyvsp[-1].clist);
|
||||
}
|
||||
#line 1290 "src/parse/parser.cc"
|
||||
#line 1281 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 23: /* ccode: TOKEN_CNEXT TOKEN_CODE */
|
||||
@@ -1296,7 +1287,7 @@ yyreduce:
|
||||
(yyval.semact)->cond = *(yyvsp[-1].str);
|
||||
delete (yyvsp[-1].str);
|
||||
}
|
||||
#line 1300 "src/parse/parser.cc"
|
||||
#line 1291 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 24: /* ccode: TOKEN_CJUMP */
|
||||
@@ -1306,13 +1297,13 @@ yyreduce:
|
||||
(yyval.semact)->cond = *(yyvsp[0].str);
|
||||
delete (yyvsp[0].str);
|
||||
}
|
||||
#line 1310 "src/parse/parser.cc"
|
||||
#line 1301 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 25: /* trailexpr: expr */
|
||||
#line 156 "../src/parse/parser.ypp"
|
||||
{ (yyval.regexp) = ast_cap((yyvsp[0].regexp)); }
|
||||
#line 1316 "src/parse/parser.cc"
|
||||
#line 1307 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 26: /* trailexpr: expr '/' expr */
|
||||
@@ -1321,25 +1312,25 @@ yyreduce:
|
||||
(yyval.regexp) = ast_cat(ast_cap((yyvsp[-2].regexp)),
|
||||
ast_cat(ast_tag(context.input.tok_loc(), NULL, false), (yyvsp[0].regexp)));
|
||||
}
|
||||
#line 1325 "src/parse/parser.cc"
|
||||
#line 1316 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 28: /* expr: expr '|' diff */
|
||||
#line 164 "../src/parse/parser.ypp"
|
||||
{ (yyval.regexp) = ast_alt((yyvsp[-2].regexp), (yyvsp[0].regexp)); }
|
||||
#line 1331 "src/parse/parser.cc"
|
||||
#line 1322 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 30: /* diff: diff '\\' term */
|
||||
#line 169 "../src/parse/parser.ypp"
|
||||
{ (yyval.regexp) = ast_diff((yyvsp[-2].regexp), (yyvsp[0].regexp)); }
|
||||
#line 1337 "src/parse/parser.cc"
|
||||
#line 1328 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 32: /* term: factor term */
|
||||
#line 175 "../src/parse/parser.ypp"
|
||||
{ (yyval.regexp) = ast_cat((yyvsp[-1].regexp), (yyvsp[0].regexp)); }
|
||||
#line 1343 "src/parse/parser.cc"
|
||||
#line 1334 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 34: /* factor: primary closes */
|
||||
@@ -1351,7 +1342,7 @@ yyreduce:
|
||||
case '?': (yyval.regexp) = ast_iter((yyvsp[-1].regexp), 0, 1); break;
|
||||
}
|
||||
}
|
||||
#line 1355 "src/parse/parser.cc"
|
||||
#line 1346 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 35: /* factor: primary TOKEN_CLOSESIZE */
|
||||
@@ -1359,31 +1350,31 @@ yyreduce:
|
||||
{
|
||||
(yyval.regexp) = ast_iter((yyvsp[-1].regexp), (yyvsp[0].bounds).min, (yyvsp[0].bounds).max);
|
||||
}
|
||||
#line 1363 "src/parse/parser.cc"
|
||||
#line 1354 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 37: /* closes: closes close */
|
||||
#line 194 "../src/parse/parser.ypp"
|
||||
{ (yyval.op) = ((yyvsp[-1].op) == (yyvsp[0].op)) ? (yyvsp[-1].op) : '*'; }
|
||||
#line 1369 "src/parse/parser.cc"
|
||||
#line 1360 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 38: /* close: '*' */
|
||||
#line 198 "../src/parse/parser.ypp"
|
||||
{ (yyval.op) = '*'; }
|
||||
#line 1375 "src/parse/parser.cc"
|
||||
#line 1366 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 39: /* close: '+' */
|
||||
#line 199 "../src/parse/parser.ypp"
|
||||
{ (yyval.op) = '+'; }
|
||||
#line 1381 "src/parse/parser.cc"
|
||||
#line 1372 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 40: /* close: '?' */
|
||||
#line 200 "../src/parse/parser.ypp"
|
||||
{ (yyval.op) = '?'; }
|
||||
#line 1387 "src/parse/parser.cc"
|
||||
#line 1378 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 42: /* primary: TOKEN_ID */
|
||||
@@ -1395,17 +1386,17 @@ yyreduce:
|
||||
}
|
||||
delete (yyvsp[0].str);
|
||||
}
|
||||
#line 1399 "src/parse/parser.cc"
|
||||
#line 1390 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
case 43: /* primary: '(' expr ')' */
|
||||
#line 212 "../src/parse/parser.ypp"
|
||||
{ (yyval.regexp) = ast_cap((yyvsp[-1].regexp)); }
|
||||
#line 1405 "src/parse/parser.cc"
|
||||
#line 1396 "src/parse/parser.cc"
|
||||
break;
|
||||
|
||||
|
||||
#line 1409 "src/parse/parser.cc"
|
||||
#line 1400 "src/parse/parser.cc"
|
||||
|
||||
default: break;
|
||||
}
|
||||
@@ -1487,6 +1478,7 @@ yyerrorlab:
|
||||
label yyerrorlab therefore never appears in user code. */
|
||||
if (0)
|
||||
YYERROR;
|
||||
++yynerrs;
|
||||
|
||||
/* Do not reclaim the symbols of the rule whose action triggered
|
||||
this YYERROR. */
|
||||
@@ -1547,7 +1539,7 @@ yyerrlab1:
|
||||
`-------------------------------------*/
|
||||
yyacceptlab:
|
||||
yyresult = 0;
|
||||
goto yyreturn;
|
||||
goto yyreturnlab;
|
||||
|
||||
|
||||
/*-----------------------------------.
|
||||
@@ -1555,24 +1547,22 @@ yyacceptlab:
|
||||
`-----------------------------------*/
|
||||
yyabortlab:
|
||||
yyresult = 1;
|
||||
goto yyreturn;
|
||||
goto yyreturnlab;
|
||||
|
||||
|
||||
#if !defined yyoverflow
|
||||
/*-------------------------------------------------.
|
||||
| yyexhaustedlab -- memory exhaustion comes here. |
|
||||
`-------------------------------------------------*/
|
||||
/*-----------------------------------------------------------.
|
||||
| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. |
|
||||
`-----------------------------------------------------------*/
|
||||
yyexhaustedlab:
|
||||
yyerror (context, YY_("memory exhausted"));
|
||||
yyresult = 2;
|
||||
goto yyreturn;
|
||||
#endif
|
||||
goto yyreturnlab;
|
||||
|
||||
|
||||
/*-------------------------------------------------------.
|
||||
| yyreturn -- parsing is finished, clean up and return. |
|
||||
`-------------------------------------------------------*/
|
||||
yyreturn:
|
||||
/*----------------------------------------------------------.
|
||||
| yyreturnlab -- parsing is finished, clean up and return. |
|
||||
`----------------------------------------------------------*/
|
||||
yyreturnlab:
|
||||
if (yychar != YYEMPTY)
|
||||
{
|
||||
/* Make sure we have latest lookahead translation. See comments at
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* A Bison parser, made by GNU Bison 3.7.6. */
|
||||
/* A Bison parser, made by GNU Bison 3.8.2. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
@@ -96,6 +96,8 @@ typedef union YYSTYPE YYSTYPE;
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
|
||||
int yyparse (re2c::context_t &context);
|
||||
|
||||
|
||||
#endif /* !YY_YY_SRC_PARSE_PARSER_H_INCLUDED */
|
||||
|
||||
@@ -4,11 +4,13 @@ builddir=__build_m32
|
||||
rm -rf $builddir
|
||||
mkdir $builddir
|
||||
|
||||
toolchain="i686-unknown-linux-gnu"
|
||||
|
||||
cd $builddir
|
||||
../configure \
|
||||
--enable-debug \
|
||||
--enable-libs \
|
||||
CXXFLAGS="-m32" \
|
||||
LDFLAGS="-m32" \
|
||||
CXX="${toolchain}-g++" \
|
||||
LD="${toolchain}-ld" \
|
||||
&& make -j$(nproc)
|
||||
cd ..
|
||||
|
||||
+21
-10
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
@@ -14,22 +14,33 @@ autoreconf -i -W all
|
||||
# try to be portable on various MAKEs
|
||||
for make_prog in make bmake
|
||||
do
|
||||
rm -rf $builddir
|
||||
mkdir $builddir
|
||||
cd $builddir
|
||||
rm -rf "$builddir"
|
||||
mkdir "$builddir"
|
||||
cd "$builddir"
|
||||
|
||||
# stage 1
|
||||
mkdir stage1
|
||||
../configure --prefix "$(pwd)/stage1" \
|
||||
&& $make_prog \
|
||||
&& $make_prog install
|
||||
|
||||
# stage 2
|
||||
# 'make' implies 'make docs'; running both in parallel may cause data races
|
||||
# configure without --enable-debug, this is the release binary
|
||||
../configure --enable-docs --enable-libs \
|
||||
&& $make_prog bootstrap -j$(nproc) \
|
||||
&& $make_prog distcheck -j$(nproc)
|
||||
../configure \
|
||||
--enable-docs \
|
||||
--enable-libs \
|
||||
--enable-lexers RE2C_FOR_BUILD="$(pwd)/stage1/bin/re2c" \
|
||||
&& $make_prog bootstrap -j"$(nproc)" \
|
||||
&& $make_prog distcheck -j"$(nproc)"
|
||||
cd ..
|
||||
done
|
||||
|
||||
# test that the release tarball builds with CMake
|
||||
cd $builddir
|
||||
cd "$builddir"
|
||||
tarball=$(find . -name 're2c-*.tar.xz')
|
||||
test -f "$tarball" && tar -xf "$tarball" \
|
||||
|| { echo "*** failed to find tarball ***" && exit 1; }
|
||||
cd "${tarball%.tar.xz}" && cmake . && make -j$(nproc) && cd .. \
|
||||
|| { echo "*** failed to extract tarball ***" && exit 1; }
|
||||
cd "${tarball%.tar.xz}" && cmake . && make -j"$(nproc)" && cd .. \
|
||||
|| { echo "*** failed to build with cmake ***" && exit 1; }
|
||||
cd ..
|
||||
|
||||
+18
-6
@@ -8,15 +8,26 @@ output="$2"
|
||||
lang="$3"
|
||||
|
||||
case $lang in
|
||||
c) ext=h
|
||||
c)
|
||||
src_ext=c
|
||||
hdr_ext=h
|
||||
lang_name=C
|
||||
disclaimer=
|
||||
disclaimer="Note: examples are in C++ (but can be easily adapted to C)."
|
||||
;;
|
||||
go) ext=go
|
||||
go)
|
||||
src_ext=go
|
||||
hdr_ext=go
|
||||
lang_name=Go
|
||||
disclaimer="Note: This manual includes examples for Go, but it refers to re2c (rather than re2go) as the name of the program in general."
|
||||
disclaimer="Note: This manual is for Go, but it refers to re2c as the general program."
|
||||
;;
|
||||
*) echo "*** $0: unknown lang: $lang"
|
||||
rust)
|
||||
src_ext=rs
|
||||
hdr_ext=rs
|
||||
lang_name=Rust
|
||||
disclaimer="Note: This manual is for Rust, but it refers to re2c as the general program."
|
||||
;;
|
||||
*)
|
||||
echo "*** $0: unknown lang: $lang"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -24,6 +35,7 @@ esac
|
||||
LANG=C sed \
|
||||
-e "s/RE2C_LANG_NAME/$lang_name/g" \
|
||||
-e "s/RE2C_LANG/$lang/g" \
|
||||
-e "s/RE2C_HEADER_EXT/$ext/g" \
|
||||
-e "s/RE2C_SOURCE_EXT/$src_ext/g" \
|
||||
-e "s/RE2C_HEADER_EXT/$hdr_ext/g" \
|
||||
-e "s/RE2C_DISCLAIMER/$disclaimer/g" \
|
||||
"$input" > "$output"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
function(re2c_gen_manpage source target bootstrap lang)
|
||||
if(RE2C_REBUILD_DOCS)
|
||||
get_filename_component(targetdir "${target}" DIRECTORY)
|
||||
set(source_l "${source}.${lang}")
|
||||
add_custom_command(
|
||||
OUTPUT "${target}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E make_directory ${targetdir}
|
||||
COMMAND "${re2c_splitman}" "${source}" "${source_l}" "${lang}"
|
||||
COMMAND "${RST2MAN}" --tab-width=4 "${source_l}" "${target}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${target}" "${bootstrap}"
|
||||
@@ -23,8 +25,10 @@ endfunction()
|
||||
|
||||
function(re2c_gen_help source target bootstrap)
|
||||
if(RE2C_REBUILD_DOCS)
|
||||
get_filename_component(targetdir "${target}" DIRECTORY)
|
||||
add_custom_command(
|
||||
OUTPUT "${target}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E make_directory ${targetdir}
|
||||
COMMAND "${RST2MAN}" "${source}" "${target}.1"
|
||||
COMMAND "${re2c_genhelp}" "${target}.1" "${target}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${target}" "${bootstrap}"
|
||||
|
||||
+6
-1
@@ -1,4 +1,4 @@
|
||||
AC_INIT([re2c],[2.2],[re2c-general@lists.sourceforge.net])
|
||||
AC_INIT([re2c],[3.0],[re2c-general@lists.sourceforge.net])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects dist-xz dist-lzip no-dist-gzip])
|
||||
AM_SILENT_RULES([yes])
|
||||
@@ -62,6 +62,11 @@ AC_ARG_ENABLE([golang], [AS_HELP_STRING([--enable-golang], [build re2go executab
|
||||
AM_CONDITIONAL([WITH_GOLANG], [test "x$enable_golang" != "xno"])
|
||||
|
||||
|
||||
# --enable-rust
|
||||
AC_ARG_ENABLE([rust], [AS_HELP_STRING([--enable-rust], [build re2rust executable])])
|
||||
AM_CONDITIONAL([WITH_RUST], [test "x$enable_rust" != "xno"])
|
||||
|
||||
|
||||
# --enable-benchmarks
|
||||
AC_ARG_ENABLE([benchmarks], [AS_HELP_STRING([--enable-benchmarks],
|
||||
[build benchmarks])])
|
||||
|
||||
+3
-5
@@ -1,18 +1,16 @@
|
||||
Usage
|
||||
=====
|
||||
|
||||
``re2c [OPTION...] INPUT [-o OUTPUT]``
|
||||
.. include:: @top_srcdir@/doc/manual/synopsis.rst_
|
||||
|
||||
``re2go [OPTION...] INPUT [-o OUTPUT]``
|
||||
|
||||
Options
|
||||
OPTIONS
|
||||
=======
|
||||
|
||||
.. include:: @top_srcdir@/doc/manual/options/options.rst_
|
||||
.. include:: @top_srcdir@/doc/manual/options/debug.rst_
|
||||
.. include:: @top_srcdir@/doc/manual/options/internal.rst_
|
||||
|
||||
Warnings
|
||||
WARNINGS
|
||||
========
|
||||
|
||||
.. include:: @top_srcdir@/doc/manual/warnings/warnings_general.rst_
|
||||
|
||||
+100
-87
@@ -2,55 +2,67 @@
|
||||
re2c
|
||||
++++
|
||||
|
||||
================================================
|
||||
generate fast lexical analyzers for C/C++ and Go
|
||||
================================================
|
||||
======================================================
|
||||
generate fast lexical analyzers for C/C++, Go and Rust
|
||||
======================================================
|
||||
|
||||
:Manual section: 1
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
|
||||
``re2c [OPTIONS] INPUT [-o OUTPUT]``
|
||||
|
||||
``re2go [OPTIONS] INPUT [-o OUTPUT]``
|
||||
|
||||
RE2C_DISCLAIMER
|
||||
|
||||
.. include:: @top_srcdir@/doc/manual/synopsis.rst_
|
||||
|
||||
Introduction
|
||||
============
|
||||
.. include:: @top_srcdir@/doc/manual/syntax/syntax.rst_
|
||||
.. include:: @top_srcdir@/doc/manual/syntax/api1.rst_
|
||||
.. include:: @top_srcdir@/doc/manual/syntax/api2_RE2C_LANG.rst_
|
||||
.. include:: @top_srcdir@/doc/manual/syntax/api3.rst_
|
||||
|
||||
Example
|
||||
=======
|
||||
.. include:: @top_srcdir@/doc/manual/syntax/intro.rst_
|
||||
|
||||
Here is a simple re2c program:
|
||||
Here is an example of a small program that checks if a given string contains a
|
||||
decimal number:
|
||||
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/01_basic.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
The generated code looks like this:
|
||||
In the output everything between ``/*!re2c`` and ``*/`` has been replaced with
|
||||
the generated code:
|
||||
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/01_basic.RE2C_LANG
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/01_basic.RE2C_SOURCE_EXT
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Command-line options
|
||||
====================
|
||||
Command-line interface consists of options and warnings.
|
||||
Syntax
|
||||
======
|
||||
|
||||
.. include:: @top_srcdir@/doc/manual/syntax/syntax.rst_
|
||||
|
||||
Program interface
|
||||
=================
|
||||
|
||||
.. include:: @top_srcdir@/doc/manual/syntax/api1.rst_
|
||||
.. include:: @top_srcdir@/doc/manual/syntax/api2_RE2C_LANG.rst_
|
||||
.. include:: @top_srcdir@/doc/manual/syntax/api3.rst_
|
||||
|
||||
Options
|
||||
=======
|
||||
|
||||
Some of the options have corresponding `configurations`_,
|
||||
others are global and cannot be changed after re2c starts reading the input file.
|
||||
Debug options generally require building re2c in debug configuration.
|
||||
Internal options are useful for experimenting with the algorithms used in re2c.
|
||||
Warnings can be invividually enabled, disabled and turned into an error.
|
||||
|
||||
.. include:: @top_srcdir@/doc/manual/options/options.rst_
|
||||
.. include:: @top_srcdir@/doc/manual/options/debug.rst_
|
||||
.. include:: @top_srcdir@/doc/manual/options/internal.rst_
|
||||
|
||||
Warnings
|
||||
========
|
||||
|
||||
Warnings can be invividually enabled, disabled and turned into an error.
|
||||
|
||||
.. include:: @top_srcdir@/doc/manual/warnings/warnings_general.rst_
|
||||
.. include:: @top_srcdir@/doc/manual/warnings/warnings_list.rst_
|
||||
|
||||
@@ -58,8 +70,8 @@ Blocks and directives
|
||||
=====================
|
||||
.. include:: @top_srcdir@/doc/manual/directives/directives.rst_
|
||||
|
||||
Interface primitives
|
||||
====================
|
||||
API primitives
|
||||
==============
|
||||
.. include:: @top_srcdir@/doc/manual/api/interface.rst_
|
||||
|
||||
Configurations
|
||||
@@ -102,6 +114,70 @@ Buffer refilling
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Multiple blocks
|
||||
===============
|
||||
.. include:: @top_srcdir@/doc/manual/conditions/blocks.rst_
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/conditions/parse_u32_blocks.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Start conditions
|
||||
================
|
||||
.. include:: @top_srcdir@/doc/manual/conditions/conditions.rst_
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/conditions/parse_u32_conditions.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Storable state
|
||||
==============
|
||||
.. include:: @top_srcdir@/doc/manual/state/state.rst_
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/state/push.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Reusable blocks
|
||||
===============
|
||||
.. include:: @top_srcdir@/doc/manual/reuse/reuse.rst_
|
||||
|
||||
Example of a ``!use`` directive
|
||||
-------------------------------
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/reuse/usedir.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Example of a ``/*!use:re2c ... */`` block
|
||||
-----------------------------------------
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/reuse/reuse.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Submatch extraction
|
||||
===================
|
||||
.. include:: @top_srcdir@/doc/manual/submatch/submatch.rst_
|
||||
.. include:: @top_srcdir@/doc/manual/submatch/submatch_example_stags.rst_
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/submatch/01_stags.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
.. include:: @top_srcdir@/doc/manual/submatch/submatch_example_stags_fill.rst_
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/submatch/01_stags_fill.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
.. include:: @top_srcdir@/doc/manual/submatch/submatch_example_posix.rst_
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/submatch/03_posix.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
.. include:: @top_srcdir@/doc/manual/submatch/submatch_example_mtags.rst_
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/submatch/02_mtags.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Encoding support
|
||||
================
|
||||
.. include:: @top_srcdir@/doc/manual/encodings/encodings.rst_
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/encodings/unicode_identifier.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Include files
|
||||
=============
|
||||
.. include:: @top_srcdir@/doc/manual/includes/includes.rst_
|
||||
@@ -136,70 +212,7 @@ Input file
|
||||
|
||||
Header file
|
||||
-----------
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/headers/src/lexer/lexer.RE2C_HEADER_EXT
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Submatch extraction
|
||||
===================
|
||||
.. include:: @top_srcdir@/doc/manual/submatch/submatch.rst_
|
||||
.. include:: @top_srcdir@/doc/manual/submatch/submatch_example_stags.rst_
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/submatch/01_stags.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
.. include:: @top_srcdir@/doc/manual/submatch/submatch_example_stags_fill.rst_
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/submatch/01_stags_fill.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
.. include:: @top_srcdir@/doc/manual/submatch/submatch_example_posix.rst_
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/submatch/03_posix.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
.. include:: @top_srcdir@/doc/manual/submatch/submatch_example_mtags.rst_
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/submatch/02_mtags.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Storable state
|
||||
==============
|
||||
.. include:: @top_srcdir@/doc/manual/state/state.rst_
|
||||
Example
|
||||
-------
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/state/push.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Reusable blocks
|
||||
===============
|
||||
.. include:: @top_srcdir@/doc/manual/reuse/reuse.rst_
|
||||
|
||||
Example of a ``!use`` directive
|
||||
-------------------------------
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/reuse/usedir.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Example of a ``/*!use:re2c ... */`` block
|
||||
-----------------------------------------
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/reuse/reuse.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Encoding support
|
||||
================
|
||||
.. include:: @top_srcdir@/doc/manual/encodings/encodings.rst_
|
||||
Example
|
||||
-------
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/encodings/unicode_identifier.re
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
Start conditions
|
||||
================
|
||||
.. include:: @top_srcdir@/doc/manual/conditions/conditions.rst_
|
||||
Example
|
||||
-------
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/conditions/parse_u32_conditions.re
|
||||
.. include:: @top_srcdir@/examples/RE2C_LANG/headers/lexer/state.RE2C_HEADER_EXT
|
||||
:literal:
|
||||
:code: RE2C_LANG
|
||||
|
||||
@@ -218,6 +231,6 @@ Similar programs are flex(1), lex(1), quex(http://quex.sourceforge.net).
|
||||
|
||||
AUTHORS
|
||||
=======
|
||||
Re2c was originaly written by Peter Bumbulis in 1993.
|
||||
re2c was originaly written by Peter Bumbulis in 1993.
|
||||
Since then it has been developed and maintained by multiple volunteers;
|
||||
mots notably, Brain Young, Marcus Boerger, Dan Nuffer and Ulya Trofimovich.
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
Here is a list of API primitives that may be used by the generated code in order to interface with the outer program.
|
||||
Here is a list of API primitives that may be used by the generated
|
||||
code in order to interface with the outer program.
|
||||
Which primitives are needed depends on multiple factors, including
|
||||
the complexity of regular expressions, input representation, buffering, the use of various features and so on.
|
||||
All the necessary primitives should be defined by the user in the form of macros, functions, variables, free-form pieces of code or any other suitable form.
|
||||
Re2c does not (and cannot) check the definitions, so if anything is missing or defined incorrectly the generated code will not compile.
|
||||
the complexity of regular expressions, input representation,
|
||||
buffering, the use of various features and so on.
|
||||
All the necessary primitives should be defined by the user in the form
|
||||
of macros, functions, variables, free-form pieces of code, or any other
|
||||
suitable form.
|
||||
re2c does not (and cannot) check the definitions, so if anything is
|
||||
missing or defined incorrectly the generated code will not compile.
|
||||
|
||||
``YYCTYPE``
|
||||
The type of the input characters (code units).
|
||||
@@ -14,48 +19,49 @@ Re2c does not (and cannot) check the definitions, so if anything is missing or d
|
||||
A pointer-like l-value that stores the current input position (usually a
|
||||
pointer of type ``YYCTYPE*``). Initially ``YYCURSOR`` should point to the
|
||||
first input character. It is advanced by the generated code.
|
||||
When a rule matches, ``YYCURSOR`` points to the one after the last matched
|
||||
character. It is used only in the default C API.
|
||||
When a rule matches, ``YYCURSOR`` points to the position after the
|
||||
last matched character. It is used only in C pointer API.
|
||||
|
||||
``YYLIMIT``
|
||||
A pointer-like r-value that stores the end of input position (usually a
|
||||
pointer of type ``YYCTYPE*``). Initially ``YYLIMIT`` should point to the
|
||||
one after the last available input character. It is not changed by the
|
||||
generated code. Lexer compares ``YYCURSOR`` to ``YYLIMIT``
|
||||
in order to determine if there is enough input characters left.
|
||||
``YYLIMIT`` is used only in the default C API.
|
||||
position after the last available input character. It is not changed by the
|
||||
generated code. The lexer compares ``YYCURSOR`` to ``YYLIMIT``
|
||||
in order to determine if there are enough input characters left.
|
||||
``YYLIMIT`` is used only in C pointer API.
|
||||
|
||||
``YYMARKER``
|
||||
A pointer-like l-value (usually a pointer of type ``YYCTYPE*``) that stores
|
||||
the position of the latest matched rule. It is used to restores ``YYCURSOR``
|
||||
position if the longer match fails and lexer needs to rollback.
|
||||
Initialization is not needed. ``YYMARKER`` is used only in the default C API.
|
||||
A pointer-like l-value (usually a pointer of type ``YYCTYPE*``)
|
||||
that stores the position of the latest matched rule. It is used to
|
||||
restore the ``YYCURSOR`` position if the longer match fails and
|
||||
the lexer needs to rollback. Initialization is not
|
||||
needed. ``YYMARKER`` is used only in C pointer API.
|
||||
|
||||
``YYCTXMARKER``
|
||||
A pointer-like l-value that stores the position of the trailing context
|
||||
(usually a pointer of type ``YYCTYPE*``). No initialization is needed.
|
||||
It is used only in the default C API, and only with the lookahead operator
|
||||
It is used only in C pointer API, and only with the lookahead operator
|
||||
``/``.
|
||||
|
||||
``YYFILL``
|
||||
API primitive with one argument ``len``.
|
||||
The meaning of ``YYFILL`` is to provide at least ``len`` more input
|
||||
characters or fail. If EOF rule is used, ``YYFILL`` should always return to
|
||||
the calling function; the return value should be zero on success and non-zero
|
||||
on failure. If EOF rule is not used, ``YYFILL`` return value is ignored and
|
||||
it should not return on failure. Maximal value of ``len`` is ``YYMAXFILL``,
|
||||
which can be generated with ``/*!max:re2c*/`` directive. The definition of
|
||||
``YYFILL`` can be either function-like or free-form depending on the API
|
||||
style (see ``re2c:api:style`` and ``re2c:define:YYFILL:naked``).
|
||||
A generic API primitive with one argument ``len``.
|
||||
``YYFILL`` should provide at least ``len`` more input characters or fail.
|
||||
If ``re2c:eof`` is used, then ``len`` is always ``1`` and ``YYFILL`` should
|
||||
always return to the calling function; zero return value indicates success.
|
||||
If ``re2c:eof`` is not used, then ``YYFILL`` return value is ignored and it
|
||||
should not return on failure. The maximum value of ``len`` is ``YYMAXFILL``.
|
||||
The definition of ``YYFILL`` can be either function-like or free-form
|
||||
depending on the API style (see ``re2c:api:style`` and
|
||||
``re2c:define:YYFILL:naked``).
|
||||
|
||||
``YYMAXFILL``
|
||||
An integral constant equal to the maximal value of ``YYFILL`` argument.
|
||||
It can be generated with ``/*!max:re2c*/`` directive.
|
||||
An integral constant equal to the maximum value of the argument to
|
||||
``YYFILL``. It can be generated with ``/*!max:re2c*/`` directive.
|
||||
|
||||
``YYLESSTHAN``
|
||||
A generic API primitive with one argument ``len``.
|
||||
It should be defined as an r-value of boolean type that equals ``true`` if
|
||||
and only if there is less than ``len`` input characters left.
|
||||
and only if there are less than ``len`` input characters left.
|
||||
The definition can be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style``).
|
||||
|
||||
@@ -63,93 +69,98 @@ Re2c does not (and cannot) check the definitions, so if anything is missing or d
|
||||
A generic API primitive with no arguments.
|
||||
It should be defined as an r-value of type ``YYCTYPE`` that is equal to the
|
||||
character at the current input position. The definition can be either
|
||||
function-like or free-form depending on the API style (see ``re2c:api:style``).
|
||||
function-like or free-form depending on the API style (see
|
||||
``re2c:api:style``).
|
||||
|
||||
``YYSKIP``
|
||||
A generic API primitive with no arguments.
|
||||
The meaning of ``YYSKIP`` is to advance the current input position by one
|
||||
``YYSKIP`` should advance the current input position by one
|
||||
character. The definition can be either function-like or free-form
|
||||
depending on the API style (see ``re2c:api:style``).
|
||||
|
||||
``YYBACKUP``
|
||||
A generic API primitive with no arguments.
|
||||
The meaning of ``YYBACKUP`` is to save the current input position, which is
|
||||
``YYBACKUP`` should save the current input position, which is
|
||||
later restored with ``YYRESTORE``.
|
||||
The definition should be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style``).
|
||||
|
||||
``YYRESTORE``
|
||||
A generic API primitive with no arguments.
|
||||
The meaning of ``YYRESTORE`` is to restore the current input position to the
|
||||
``YYRESTORE`` should restore the current input position to the
|
||||
value saved by ``YYBACKUP``.
|
||||
The definition should be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style``).
|
||||
|
||||
``YYBACKUPCTX``
|
||||
A generic API primitive with zero arguments.
|
||||
The meaning of ``YYBACKUPCTX`` is to save the current input position as the
|
||||
position of the trailing context, which is later restored by ``YYRESTORECTX``.
|
||||
``YYBACKUPCTX`` should save the current input position as the
|
||||
position of the trailing context, which is later restored by
|
||||
``YYRESTORECTX``.
|
||||
The definition should be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style``).
|
||||
|
||||
``YYRESTORECTX``
|
||||
A generic API primitive with no arguments.
|
||||
The meaning of ``YYRESTORECTX`` is to restore the trailing context position
|
||||
``YYRESTORECTX`` should restore the trailing context position
|
||||
saved with ``YYBACKUPCTX``.
|
||||
The definition should be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style``).
|
||||
|
||||
``YYRESTORETAG``
|
||||
A generic API primitive with one argument ``tag``.
|
||||
The meaning of ``YYRESTORETAG`` is to restore the trailing context position
|
||||
``YYRESTORETAG`` should restore the trailing context position
|
||||
to the value of ``tag``.
|
||||
The definition should be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style``).
|
||||
|
||||
``YYSTAGP``
|
||||
A generic API primitive with one argument ``tag``.
|
||||
The meaning of ``YYSTAGP`` is to set ``tag`` value to the current input
|
||||
position.
|
||||
A generic API primitive with one argument ``tag``, where ``tag`` can be a
|
||||
pointer or an offset (see submatch extraction section for details).
|
||||
``YYSTAGP`` should set ``tag`` to the current input position.
|
||||
The definition should be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style``).
|
||||
|
||||
``YYSTAGN``
|
||||
A generic API primitive with one argument ``tag``.
|
||||
The meaning of ``YYSTAGN`` is to set ``tag`` value to null (or some default
|
||||
value). The definition should be either function-like or free-form depending
|
||||
on the API style (see ``re2c:api:style``).
|
||||
A generic API primitive with one argument ``tag``, where ``tag`` can be a
|
||||
pointer or an offset (see submatch extraction section for details).
|
||||
``YYSTAGN`` should to set ``tag`` to a value that represents non-existent
|
||||
input position.
|
||||
The definition should be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style``).
|
||||
|
||||
``YYMTAGP``
|
||||
A generic API primitive with one argument ``tag``.
|
||||
The meaning of ``YYMTAGP`` is to append the current position to the history
|
||||
of ``tag``.
|
||||
``YYMTAGP`` should append the current position to the submatch history of
|
||||
``tag`` (see the submatch extraction section for details.)
|
||||
The definition should be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style``).
|
||||
|
||||
``YYMTAGN``
|
||||
A generic API primitive with one argument ``tag``.
|
||||
The meaning of ``YYMTAGN`` is to append null (or some other default) value
|
||||
to the history of ``tag``.
|
||||
``YYMTAGN`` should append a value that represents non-existent input
|
||||
position position to the submatch history of ``tag`` (see the submatch
|
||||
extraction section for details.)
|
||||
The definition can be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style``).
|
||||
|
||||
``YYSHIFT``
|
||||
A generic API primitive with one argument ``shift``.
|
||||
The meaning of ``YYSHIFT`` is to shift the current input position by
|
||||
``YYSHIFT`` should shift the current input position by
|
||||
``shift`` characters (the shift value may be negative). The definition
|
||||
can be either function-like or free-form depending on the API style
|
||||
(see ``re2c:api:style``).
|
||||
|
||||
``YYSHIFTSTAG``
|
||||
A generic API primitive with two arguments, ``tag`` and ``shift``.
|
||||
The meaning of ``YYSHIFTSTAG`` is to shift ``tag`` by ``shift`` characters
|
||||
``YYSHIFTSTAG`` should shift ``tag`` by ``shift`` characters
|
||||
(the shift value may be negative).
|
||||
The definition can be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style``).
|
||||
|
||||
``YYSHIFTMTAG``
|
||||
A generic API primitive with two arguments, ``tag`` and ``shift``.
|
||||
The meaning of ``YYSHIFTMTAG`` is to shift the latest value in the history
|
||||
``YYSHIFTMTAG`` should shift the latest value in the history
|
||||
of ``tag`` by ``shift`` characters (the shift value may be negative).
|
||||
The definition should be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style``).
|
||||
@@ -160,8 +171,8 @@ Re2c does not (and cannot) check the definitions, so if anything is missing or d
|
||||
|
||||
``YYCONDTYPE``
|
||||
The type of the condition enum.
|
||||
It should be generated either with ``/*!types:re2c*/`` directive or ``-t``
|
||||
``--type-header`` option.
|
||||
It should be generated either with the ``/*!types:re2c*/``
|
||||
directive or the ``-t`` ``--type-header`` option.
|
||||
|
||||
``YYGETCONDITION``
|
||||
An API primitive with zero arguments.
|
||||
@@ -172,8 +183,8 @@ Re2c does not (and cannot) check the definitions, so if anything is missing or d
|
||||
|
||||
``YYSETCONDITION``
|
||||
An API primitive with one argument ``cond``.
|
||||
The meaning of ``YYSETCONDITION`` is to set the current condition identifier
|
||||
to ``cond``.
|
||||
The meaning of ``YYSETCONDITION`` is to set the current condition
|
||||
identifier to ``cond``.
|
||||
The definition should be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style`` and ``re2c:define:YYSETCONDITION@cond``).
|
||||
|
||||
@@ -186,7 +197,8 @@ Re2c does not (and cannot) check the definitions, so if anything is missing or d
|
||||
|
||||
``YYSETSTATE``
|
||||
An API primitive with one argument ``state``.
|
||||
The meaning of ``YYSETSTATE`` is to set the current lexer state to ``state``.
|
||||
The meaning of ``YYSETSTATE`` is to set the current lexer state to
|
||||
``state``.
|
||||
The definition should be either function-like or free-form depending on the
|
||||
API style (see ``re2c:api:style`` and ``re2c:define:YYSETSTATE@state``).
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
Sometimes it is necessary to have multiple interrelated lexers (for example, if
|
||||
there is a high-level state machine that transitions between lexer modes). This
|
||||
can be implemented using multiple connected re2c blocks. Another option is to
|
||||
use `start conditions`_.
|
||||
|
||||
The implementation of connections between blocks depends on the target language.
|
||||
In languages that have ``goto`` statement (such as C/C++ and Go) one can have
|
||||
all blocks in one function, each of them prefixed with a label. Transition from
|
||||
one block to another is a simple ``goto``.
|
||||
In languages that do not have ``goto`` (such as Rust) it is necessary to use a
|
||||
loop with a switch on a state variable, similar to the ``yystate`` loop/switch
|
||||
generated by re2c, or else wrap each block in a function and use function calls.
|
||||
|
||||
The example below uses multiple blocks to parse binary, octal, decimal and
|
||||
hexadecimal numbers. Each base has its own block. The initial block determines
|
||||
base and dispatches to other blocks. Common configurations are defined in a
|
||||
separate block at the beginning of the program; they are inherited by the other
|
||||
blocks.
|
||||
@@ -1,52 +1,77 @@
|
||||
Conditions are enabled with ``-c`` ``--conditions``.
|
||||
This option allows one to encode multiple interrelated lexers within the same re2c block.
|
||||
Start conditions are enabled with ``--start-conditions`` option. They provide a
|
||||
way to encode multiple interrelated automata within the same re2c block.
|
||||
|
||||
Each lexer corresponds to a single condition.
|
||||
It starts with a label of the form ``yyc_name``,
|
||||
where ``name`` is condition name
|
||||
and ``yyc`` prefix can be adjusted with configuration ``re2c:condprefix``.
|
||||
Different lexers are separated with a comment ``/* *********************************** */``
|
||||
which can be adjusted with configuration ``re2c:cond:divider``.
|
||||
Each condition corresponds to a single automaton and has a unique name specified
|
||||
by the user and a unique internal number defined by re2c. The numbers are used
|
||||
to switch between conditions: the generated code uses ``YYGETCONDITION`` and
|
||||
``YYSETCONDITION`` primitives to get the current condition or set it to the
|
||||
given number. Use ``/*!conditions:re2c*/`` directive or the ``--header`` option
|
||||
to generate numeric condition identifiers. Configuration
|
||||
``re2c:cond:enumprefix`` specifies the generated identifier prefix.
|
||||
|
||||
Furthermore, each condition has a unique identifier of the form ``yycname``,
|
||||
where ``name`` is condition name
|
||||
and ``yyc`` prefix can be adjusted with configuration ``re2c:condenumprefix``.
|
||||
Identifiers have the type ``YYCONDTYPE`` and should be generated with ``/*!types:re2c*/`` directive or ``-t`` ``--type-header`` option.
|
||||
Users shouldn't define these identifiers manually, as the order of conditions is not specified.
|
||||
In condition mode every rule must be prefixed with a list of comma-separated
|
||||
condition names in angle brackets, or a wildcard ``<*>`` to denote all
|
||||
conditions. The rule syntax is extended as follows:
|
||||
|
||||
Before all conditions re2c generates entry code that checks the current condition identifier
|
||||
and transfers control flow to the start label of the active condition.
|
||||
After matching some rule of this condition,
|
||||
lexer may either transfer control flow back to the entry code (after executing the associated action and optionally setting another condition with ``=>``),
|
||||
or use ``:=>`` shortcut and transition directly to the start label of another condition (skipping the action and the entry code).
|
||||
Configuration ``re2c:cond:goto`` allows one to change the default behavior.
|
||||
``< cond-list > regexp action``
|
||||
A rule that is merged to every condition on the ``cond-list``.
|
||||
It matches ``regexp`` and executes the associated ``action``.
|
||||
|
||||
Syntactically each rule must be preceded with a list of comma-separated condition names or a wildcard ``*``
|
||||
enclosed in angle brackets ``<`` and ``>``.
|
||||
Wildcard means "any condition" and is semantically equivalent to listing all condition names.
|
||||
Here ``regexp`` is a regular expression, ``default`` refers to the default rule ``*``,
|
||||
and ``action`` is a block of code.
|
||||
``< cond-list > regexp => cond action``
|
||||
A rule that is merged to every condition on the ``cond-list``.
|
||||
It matches ``regexp``, sets the current condition to ``cond`` and
|
||||
executes the associated ``action``.
|
||||
|
||||
* ``<conditions-or-wildcard> regexp-or-default action``
|
||||
``< cond-list > regexp :=> cond``
|
||||
A rule that is merged to every condition on the ``cond-list``.
|
||||
It matches ``regexp`` and immediately transitions to ``cond`` (there is
|
||||
no semantic action).
|
||||
|
||||
* ``<conditions-or-wildcard> regexp-or-default => condition action``
|
||||
``<! cond-list > action``
|
||||
The ``action`` is prepended to semantic actions of all rules for every
|
||||
condition on the ``cond-list``. This may be used to deduplicate common
|
||||
code.
|
||||
|
||||
* ``<conditions-or-wildcard> regexp-or-default :=> condition``
|
||||
``< > action``
|
||||
A rule that is merged to a special entry condition with number zero
|
||||
and name ``"0"``. It matches empty string and executes the ``action``.
|
||||
|
||||
Rules with an exclamation mark ``!`` in front of condition list have a special meaning:
|
||||
they have no regular expression,
|
||||
and the associated action is merged as an entry code to actions of normal rules.
|
||||
This might be a convenient place to peform a routine task that is common to all rules.
|
||||
``< > => cond action``
|
||||
A rule that is merged to a special entry condition with number zero
|
||||
and name ``"0"``. It matches empty string, sets the current condition to
|
||||
``cond`` and executes the ``action``.
|
||||
|
||||
* ``<!conditions-or-wildcard> action``
|
||||
``< > :=> cond``
|
||||
A rule that is merged to a special entry condition with number zero
|
||||
and name ``"0"``. It matches empty string and immediately transitions to
|
||||
``cond``.
|
||||
|
||||
Another special form of rules with an empty condition list ``<>`` and no regular expression
|
||||
allows one to specify an "entry condition" that can be used to execute code before entering the lexer.
|
||||
It is semantically equivalent to a condition with number zero, name ``0`` and an empty regular expression.
|
||||
|
||||
* ``<> action``
|
||||
The code re2c generates for conditions depends on whether re2c uses goto/label
|
||||
approach or loop/switch approach to encode the automata.
|
||||
|
||||
* ``<> => condition action``
|
||||
In languages that have ``goto`` statement (such as C/C++ and Go) conditions are
|
||||
naturally implemented as blocks of code prefixed with labels of the form
|
||||
``yyc_<cond>``, where ``cond`` is a condition name (label prefix can be changed
|
||||
with ``re2c:cond:prefix``). Transitions between conditions are implemented using
|
||||
``goto`` and condition labels. Before all conditions re2c generates an initial
|
||||
switch on ``YYGETSTATE`` that jumps to the start state of the current condition.
|
||||
The shortcut rules ``:=>`` bypass the initial switch and jump directly to the
|
||||
specified condition (``re2c:cond:goto`` can be used to change the default
|
||||
behavior). The rules with semantic actions do not automatically jump to the next
|
||||
condition; this should be done by the user-defined action code.
|
||||
|
||||
* ``<> :=> condition``
|
||||
In languages that do not have ``goto`` (such as Rust) re2c reuses the
|
||||
``yystate`` variable to store condition numbers. Each condition gets a numeric
|
||||
identifier equal to the number of its start state, and a switch between
|
||||
conditions is no different than a switch between DFA states of a single
|
||||
condition. There is no need for a separate initial condition switch.
|
||||
(Since the same approach is used to implement storable states,
|
||||
``YYGETCONDITION``/``YYSETCONDITION`` are redundant if both storable states and
|
||||
conditions are used).
|
||||
|
||||
The program below uses start conditions to parse binary, octal, decimal and
|
||||
hexadecimal numbers. There is a single block where each base has its own
|
||||
condition, and the initial condition is connected to all of them. User-defined
|
||||
variable ``cond`` stores the current condition number; it is initialized to the
|
||||
number of the initial condition generated with ``/*!conditions:re2c*/``.
|
||||
|
||||
@@ -1,196 +1,61 @@
|
||||
``re2c:flags:t``, ``re2c:flags:type-header``
|
||||
Specify the name of the generated header file relative to the directory of
|
||||
the output file. (Same as ``-t``, ``--type-header`` command-line option
|
||||
except that the filepath is relative.)
|
||||
|
||||
``re2c:flags:input``
|
||||
Same as ``--input`` command-line option.
|
||||
|
||||
``re2c:api:style``
|
||||
Allows one to specify the style of generic API. Possible values are ``functions``
|
||||
and ``free-form``. With ``functions`` style (the default for the C backend)
|
||||
API primitives behave like functions, and re2c generates parentheses with an
|
||||
argument list after the name of each primitive.
|
||||
With ``free-form`` style (the default for the Go backend) re2c treats API
|
||||
definitions as interpolated strings and substitutes argument placeholders
|
||||
with the actual argument values.
|
||||
This option can be overridden by options for individual API primitives,
|
||||
e.g. ``re2c:define:YYFILL:naked`` for ``YYFILL``.
|
||||
``re2c:api``, ``re2c:flags:input``
|
||||
Same as the ``--api`` option.
|
||||
|
||||
``re2c:api:sigil``
|
||||
Allows one to specify the "sigil" symbol (or string) that is used to recognize
|
||||
argument placeholders in the definitions of generic API primitives.
|
||||
The default value is ``@@``.
|
||||
Placeholders start with sigil, followed by the argument name in curly braces.
|
||||
For example, if sigil is set to ``$``, then placeholders will have the form
|
||||
``${name}``. Single-argument APIs may use shorthand notation without the
|
||||
name in braces. This option can be overridden by options for individual API
|
||||
primitives, e.g. ``re2c:define:YYFILL@len`` for ``YYFILL``.
|
||||
Specify the marker ("sigil") that is used for argument placeholders in the
|
||||
API primitives. The default is ``@@``. A placeholder starts with sigil
|
||||
followed by the argument name in curly braces. For example, if sigil is set
|
||||
to ``$``, then placeholders will have the form ``${name}``. Single-argument
|
||||
APIs may use shorthand notation without the name in braces. This option can
|
||||
be overridden by options for individual API primitives, e.g.
|
||||
``re2c:define:YYFILL@len`` for ``YYFILL``.
|
||||
|
||||
``re2c:define:YYCTYPE``
|
||||
Defines ``YYCTYPE`` (see the user interface section).
|
||||
``re2c:api:style``
|
||||
Specify API style. Possible values are ``functions`` (the default for C) and
|
||||
``free-form`` (the default for Go and Rust).
|
||||
In ``functions`` style API primitives are generated with an argument list in
|
||||
parentheses following the name of the primitive. The arguments are provided
|
||||
only for autogenerated parameters (such as the number of characters passed
|
||||
to ``YYFILL``), but not for the general lexer context, so the primitives
|
||||
behave more like macros in C/C++ or closures in Go and Rust.
|
||||
In free-form style API primitives do not have a fixed form: they should be
|
||||
defined as strings containing free-form pieces of code with interpolated
|
||||
variables of the form ``@@{var}`` or ``@@`` (they correspond to arguments in
|
||||
function-like style).
|
||||
This configuration may be overridden for individual API primitives, see for
|
||||
example ``re2c:define:YYFILL:naked`` configuration for ``YYFILL``.
|
||||
|
||||
``re2c:define:YYCURSOR``
|
||||
Defines C API primitive ``YYCURSOR`` (see the user interface section).
|
||||
``re2c:bit-vectors``, ``re2c:flags:bit-vectors``, ``re2c:flags:b``
|
||||
Same as the ``--bit-vectors`` option, but can be configured on per-block
|
||||
basis.
|
||||
|
||||
``re2c:define:YYLIMIT``
|
||||
Defines C API primitive ``YYLIMIT`` (see the user interface section).
|
||||
``re2c:case-insensitive``, ``re2c:flags:case-insensitive``
|
||||
Same as the ``--case-insensitive`` option, but can be configured on
|
||||
per-block basis.
|
||||
|
||||
``re2c:define:YYMARKER``
|
||||
Defines C API primitive ``YYMARKER`` (see the user interface section).
|
||||
``re2c:case-inverted``, ``re2c:flags:case-inverted``
|
||||
Same as the ``--case-inverted`` option, but can be configured on per-block
|
||||
basis.
|
||||
|
||||
``re2c:define:YYCTXMARKER``
|
||||
Defines C API primitive ``YYCTXMARKER`` (see the user interface section).
|
||||
``re2c:case-ranges``, ``re2c:flags:case-ranges``
|
||||
Same as the ``--case-ranges`` option, but can be configured on per-block
|
||||
basis.
|
||||
|
||||
``re2c:define:YYFILL``
|
||||
Defines API primitive ``YYFILL`` (see the user interface section).
|
||||
``re2c:computed-gotos``, ``re2c:flags:computed-gotos``, ``re2c:flags:g``
|
||||
Same as the ``--computed-gotos`` option, but can be configured on per-block
|
||||
basis.
|
||||
|
||||
``re2c:define:YYFILL@len``
|
||||
Specifies the sigil used for argument substitution in ``YYFILL``
|
||||
definition. Defaults to ``@@``.
|
||||
Overrides the more generic ``re2c:api:sigil`` configuration.
|
||||
|
||||
``re2c:define:YYFILL:naked``
|
||||
Allows one to override ``re2c:api:style`` for ``YYFILL``.
|
||||
Value ``0`` corresponds to free-form API style.
|
||||
|
||||
``re2c:yyfill:enable``
|
||||
Defaults to ``1`` (``YYFILL`` is enabled). Set this to zero to suppress the
|
||||
generation of ``YYFILL``. Use warnings (``-W`` option) and ``re2c:sentinel``
|
||||
configuration to verify that the generated lexer cannot read past the end of
|
||||
input, as this might introduce severe security issues to your programs.
|
||||
|
||||
``re2c:yyfill:parameter``
|
||||
Controls the argument in the parentheses that follow ``YYFILL``. Defaults to
|
||||
``1``, which means that the argument is generated. If zero, the argument is
|
||||
omitted. Can be overridden with ``re2c:define:YYFILL:naked`` or
|
||||
``re2c:api:style``.
|
||||
|
||||
``re2c:eof``
|
||||
Specifies the sentinel symbol used with EOF rule ``$`` to check for the end
|
||||
of input in the generated lexer. The default value is ``-1`` (EOF rule is not
|
||||
used). Other possible values include all valid code units. Only decimal
|
||||
numbers are recognized.
|
||||
|
||||
``re2c:sentinel``
|
||||
Specifies the sentinel symbol used with the sentinel method of checking for
|
||||
the end of input in the generated lexer (the case when bounds checking
|
||||
is disabled with ``re2c:yyfill:enable = 0;`` and EOF rule ``$`` is not
|
||||
used). This configuration does not affect code generation. It is used by
|
||||
re2c to verify that the sentinel symbol is not allowed in the middle of the
|
||||
rule, and prevent possible reads past the end of buffer in the generated
|
||||
lexer. The default value is ``-1`` (re2c assumes that
|
||||
the sentinel symbol is ``0``, which is the most common case). Other
|
||||
possible values include all valid code units. Only decimal numbers are
|
||||
recognized.
|
||||
|
||||
``re2c:define:YYLESSTHAN``
|
||||
Defines generic API primitive ``YYLESSTHAN`` (see the user interface section).
|
||||
|
||||
``re2c:yyfill:check``
|
||||
Setting this to zero allows to suppress the generation of ``YYFILL`` check
|
||||
(``YYLESSTHAN`` in generic API of ``YYLIMIT``-based comparison in default C
|
||||
API). This configuration is useful when the necessary input is always
|
||||
available. it defaults to ``1`` (the check is generated).
|
||||
|
||||
``re2c:label:yyFillLabel``
|
||||
Allows one to change the prefix of ``YYFILL`` labels (used with EOF rule
|
||||
or with storable states).
|
||||
|
||||
``re2c:define:YYPEEK``
|
||||
Defines generic API primitive ``YYPEEK`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYSKIP``
|
||||
Defines generic API primitive ``YYSKIP`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYBACKUP``
|
||||
Defines generic API primitive ``YYBACKUP`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYBACKUPCTX``
|
||||
Defines generic API primitive ``YYBACKUPCTX`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYRESTORE``
|
||||
Defines generic API primitive ``YYRESTORE`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYRESTORECTX``
|
||||
Defines generic API primitive ``YYRESTORECTX`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYRESTORETAG``
|
||||
Defines generic API primitive ``YYRESTORETAG`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYSHIFT``
|
||||
Defines generic API primitive ``YYSHIFT`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYSHIFTMTAG``
|
||||
Defines generic API primitive ``YYSHIFTMTAG`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYSHIFTSTAG``
|
||||
Defines generic API primitive ``YYSHIFTSTAG`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYSTAGN``
|
||||
Defines generic API primitive ``YYSTAGN`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYSTAGP``
|
||||
Defines generic API primitive ``YYSTAGP`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYMTAGN``
|
||||
Defines generic API primitive ``YYMTAGN`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYMTAGP``
|
||||
Defines generic API primitive ``YYMTAGP`` (see the user interface section).
|
||||
|
||||
``re2c:flags:T``, ``re2c:flags:tags``
|
||||
Same as ``-T --tags`` command-line option.
|
||||
|
||||
``re2c:flags:P``, ``re2c:flags:posix-captures``
|
||||
Same as ``-P --posix-captures`` command-line option.
|
||||
|
||||
``re2c:tags:expression``
|
||||
Allows one to customize the way re2c addresses tag variables.
|
||||
By default re2c generates expressions of the form ``yyt<N>``. This might
|
||||
be inconvenient, for example if tag variables are defined as fields in a
|
||||
struct. Re2c recognizes placeholder of the form ``@@{tag}`` or ``@@`` and
|
||||
replaces it with the actual tag name.
|
||||
Sigil ``@@`` can be redefined with ``re2c:api:sigil`` configuration.
|
||||
For example, setting ``re2c:tags:expression = "p->@@";`` results in
|
||||
expressions of the form ``p->yyt<N>`` in the generated code.
|
||||
|
||||
``re2c:tags:prefix``
|
||||
Allows one to override the prefix of tag variables (defaults to ``yyt``).
|
||||
|
||||
``re2c:flags:lookahead``
|
||||
Same as inverted ``--no-lookahead`` command-line option.
|
||||
|
||||
``re2c:flags:optimize-tags``
|
||||
Same as inverted ``--no-optimize-tags`` command-line option.
|
||||
|
||||
``re2c:define:YYCONDTYPE``
|
||||
Defines ``YYCONDTYPE`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYGETCONDITION``
|
||||
Defines API primitive ``YYGETCONDITION`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYGETCONDITION:naked``
|
||||
Allows one to override ``re2c:api:style`` for ``YYGETCONDITION``.
|
||||
Value ``0`` corresponds to free-form API style.
|
||||
|
||||
``re2c:define:YYSETCONDITION``
|
||||
Defines API primitive ``YYSETCONDITION`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYSETCONDITION@cond``
|
||||
Specifies the sigil used for argument substitution in ``YYSETCONDITION``
|
||||
definition. The default value is ``@@``.
|
||||
Overrides the more generic ``re2c:api:sigil`` configuration.
|
||||
|
||||
``re2c:define:YYSETCONDITION:naked``
|
||||
Allows one to override ``re2c:api:style`` for ``YYSETCONDITION``.
|
||||
Value ``0`` corresponds to free-form API style.
|
||||
``re2c:computed-gotos:threshold``, ``re2c:cgoto:threshold``
|
||||
If computed ``goto`` is used, this configuration specifies the complexity
|
||||
threshold that triggers the generation of jump tables instead of nested
|
||||
``if`` statements and bitmaps. The default value is ``9``.
|
||||
|
||||
``re2c:cond:goto``
|
||||
Allows one to customize the goto statements used with the shortcut ``:=>``
|
||||
rules in conditions. The default value is ``goto @@;``.
|
||||
Placeholders are substituted with condition name (see ``re2c:api;sigil`` and
|
||||
``re2c:cond:goto@cond``).
|
||||
Specifies a piece of code used for the autogenerated shortcut rules ``:=>``
|
||||
in conditions. The default is ``goto @@;``.
|
||||
The ``@@`` placeholder is substituted with condition name (see
|
||||
configurations ``re2c:api:sigil`` and ``re2c:cond:goto@cond``).
|
||||
|
||||
``re2c:cond:goto@cond``
|
||||
Specifies the sigil used for argument substitution in ``re2c:cond:goto``
|
||||
@@ -205,26 +70,114 @@
|
||||
|
||||
``re2c:cond:divider@cond``
|
||||
Specifies the sigil used for argument substitution in ``re2c:cond:divider``
|
||||
definition. The default is ``@@``.
|
||||
Overrides the more generic ``re2c:api:sigil`` configuration.
|
||||
|
||||
``re2c:cond:prefix``, ``re2c:condprefix``
|
||||
Specifies the prefix used for condition labels.
|
||||
The default is ``yyc_``.
|
||||
|
||||
``re2c:cond:enumprefix``, ``re2c:condenumprefix``
|
||||
Specifies the prefix used for condition identifiers.
|
||||
The default is ``yyc``.
|
||||
|
||||
``re2c:debug-output``, ``re2c:flags:debug-output``, ``re2c:flags:d``
|
||||
Same as the ``--debug-output`` option, but can be configured on per-block
|
||||
basis.
|
||||
|
||||
``re2c:define:YYBACKUP``
|
||||
Defines generic API primitive ``YYBACKUP`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYBACKUPCTX``
|
||||
Defines generic API primitive ``YYBACKUPCTX`` (see the API primitives
|
||||
section).
|
||||
|
||||
``re2c:define:YYCONDTYPE``
|
||||
Defines ``YYCONDTYPE`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYCTYPE``
|
||||
Defines ``YYCTYPE`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYCTXMARKER``
|
||||
Defines API primitive ``YYCTXMARKER`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYCURSOR``
|
||||
Defines API primitive ``YYCURSOR`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYDEBUG``
|
||||
Defines API primitive ``YYDEBUG`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYFILL``
|
||||
Defines API primitive ``YYFILL`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYFILL@len``
|
||||
Specifies the sigil used for argument substitution in ``YYFILL``
|
||||
definition. Defaults to ``@@``.
|
||||
Overrides the more generic ``re2c:api:sigil`` configuration.
|
||||
|
||||
``re2c:define:YYFILL:naked``
|
||||
Overrides the more generic ``re2c:api:style`` configuration for ``YYFILL``.
|
||||
Zero value corresponds to free-form API style.
|
||||
|
||||
``re2c:define:YYGETCONDITION``
|
||||
Defines API primitive ``YYGETCONDITION`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYGETCONDITION:naked``
|
||||
Overrides the more generic ``re2c:api:style`` configuration for
|
||||
``YYGETCONDITION``. Zero value corresponds to free-form API style.
|
||||
|
||||
``re2c:define:YYGETSTATE``
|
||||
Defines API primitive ``YYGETSTATE`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYGETSTATE:naked``
|
||||
Overrides the more generic ``re2c:api:style`` configuration for
|
||||
``YYGETSTATE``. Zero value corresponds to free-form API style.
|
||||
|
||||
``re2c:define:YYLESSTHAN``
|
||||
Defines generic API primitive ``YYLESSTHAN`` (see the API primitives
|
||||
section).
|
||||
|
||||
``re2c:define:YYLIMIT``
|
||||
Defines API primitive ``YYLIMIT`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYMARKER``
|
||||
Defines API primitive ``YYMARKER`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYMTAGN``
|
||||
Defines generic API primitive ``YYMTAGN`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYMTAGP``
|
||||
Defines generic API primitive ``YYMTAGP`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYPEEK``
|
||||
Defines generic API primitive ``YYPEEK`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYRESTORE``
|
||||
Defines generic API primitive ``YYRESTORE`` (see the API primitives
|
||||
section).
|
||||
|
||||
``re2c:define:YYRESTORECTX``
|
||||
Defines generic API primitive ``YYRESTORECTX`` (see the API primitives
|
||||
section).
|
||||
|
||||
``re2c:define:YYRESTORETAG``
|
||||
Defines generic API primitive ``YYRESTORETAG`` (see the API primitives
|
||||
section).
|
||||
|
||||
``re2c:define:YYSETCONDITION``
|
||||
Defines API primitive ``YYSETCONDITION`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYSETCONDITION@cond``
|
||||
Specifies the sigil used for argument substitution in ``YYSETCONDITION``
|
||||
definition. The default value is ``@@``.
|
||||
Overrides the more generic ``re2c:api:sigil`` configuration.
|
||||
|
||||
``re2c:condprefix``
|
||||
Specifies the prefix used for condition labels.
|
||||
The default value is ``yyc_``.
|
||||
|
||||
``re2c:condenumprefix``
|
||||
Specifies the prefix used for condition identifiers.
|
||||
The default value is ``yyc``.
|
||||
|
||||
``re2c:define:YYGETSTATE``
|
||||
Defines API primitive ``YYGETSTATE`` (see the user interface section).
|
||||
|
||||
``re2c:define:YYGETSTATE:naked``
|
||||
Allows one to override ``re2c:api:style`` for ``YYGETSTATE``.
|
||||
Value ``0`` corresponds to free-form API style.
|
||||
``re2c:define:YYSETCONDITION:naked``
|
||||
Overrides the more generic ``re2c:api:style`` configuration for
|
||||
``YYSETCONDITION``. Zero value corresponds to free-form API style.
|
||||
|
||||
``re2c:define:YYSETSTATE``
|
||||
Defines API primitive ``YYSETSTATE`` (see the user interface section).
|
||||
Defines API primitive ``YYSETSTATE`` (see the API primitives section).
|
||||
|
||||
``re2c:define:YYSETSTATE@state``
|
||||
Specifies the sigil used for argument substitution in ``YYSETSTATE``
|
||||
@@ -232,134 +185,205 @@
|
||||
Overrides the more generic ``re2c:api:sigil`` configuration.
|
||||
|
||||
``re2c:define:YYSETSTATE:naked``
|
||||
Allows one to override ``re2c:api:style`` for ``YYSETSTATE``.
|
||||
Value ``0`` corresponds to free-form API style.
|
||||
Overrides the more generic ``re2c:api:style`` configuration for
|
||||
``YYSETSTATE``. Zero value corresponds to free-form API style.
|
||||
|
||||
``re2c:state:abort``
|
||||
If set to a positive integer value, changes the form of the ``YYGETSTATE``
|
||||
switch: instead of using default case to jump to the beginning of the lexer
|
||||
block, a ``-1`` case is used, and the default case aborts the program.
|
||||
``re2c:define:YYSKIP``
|
||||
Defines generic API primitive ``YYSKIP`` (see the API primitives section).
|
||||
|
||||
``re2c:state:nextlabel``
|
||||
With storable states, allows to control if the ``YYGETSTATE`` block is
|
||||
followed by a ``yyNext`` label (the default value is zero, which corresponds
|
||||
to no label). Instead of using ``yyNext`` it is possible to use
|
||||
``re2c:startlabel`` to force the generation of a specific start label.
|
||||
Instead of using labels it is often more convenient to generate
|
||||
``YYGETSTATE`` code using ``/*!getstate:re2c*/``.
|
||||
``re2c:define:YYSHIFT``
|
||||
Defines generic API primitive ``YYSHIFT`` (see the API primitives section).
|
||||
|
||||
``re2c:label:yyNext``
|
||||
Allows one to change the name of the ``yyNext`` label.
|
||||
``re2c:define:YYSHIFTMTAG``
|
||||
Defines generic API primitive ``YYSHIFTMTAG`` (see the API primitives
|
||||
section).
|
||||
|
||||
``re2c:startlabel``
|
||||
Controls the generation of start label for the next lexer block.
|
||||
The default value is zero, which means that the start label is generated
|
||||
only if it is used. An integer value greater than zero forces the generation
|
||||
of start label even if it is unused by the lexer. A string value also forces
|
||||
start label generation and sets the label name to the specified string.
|
||||
This configuration applies only to the current block (it is reset to default
|
||||
for the next block).
|
||||
``re2c:define:YYSHIFTSTAG``
|
||||
Defines generic API primitive ``YYSHIFTSTAG`` (see the API primitives
|
||||
section).
|
||||
|
||||
``re2c:flags:s``, ``re2c:flags:nested-ifs``
|
||||
Same as ``-s --nested-ifs`` command-line option.
|
||||
``re2c:define:YYSTAGN``
|
||||
Defines generic API primitive ``YYSTAGN`` (see the API primitives section).
|
||||
|
||||
``re2c:flags:b``, ``re2c:flags:bit-vectors``
|
||||
Same as ``-b --bit-vectors`` command-line option.
|
||||
``re2c:define:YYSTAGP``
|
||||
Defines generic API primitive ``YYSTAGP`` (see the API primitives section).
|
||||
|
||||
``re2c:variable:yybm``
|
||||
Overrides the name of the ``yybm`` variable.
|
||||
``re2c:empty-class``, ``re2c:flags:empty-class``
|
||||
Same as the ``--empty-class`` option, but can be configured on per-block
|
||||
basis.
|
||||
|
||||
``re2c:yybm:hex``
|
||||
Defaults to zero (a decimal bitmap table is generated). If set to nonzero,
|
||||
a hexadecimal table is generated.
|
||||
``re2c:encoding:ebcdic``, ``re2c:flags:ecb``, ``re2c:flags:e``
|
||||
Same as the ``--ebcdic`` option, but can be configured on per-block basis.
|
||||
|
||||
``re2c:flags:g``, ``re2c:flags:computed-gotos``
|
||||
Same as ``-g --computed-gotos`` command-line option.
|
||||
``re2c:encoding:ucs2``, ``re2c:flags:wide-chars``, ``re2c:flags:w``
|
||||
Same as the ``--ucs2`` option, but can be configured on per-block basis.
|
||||
|
||||
``re2c:cgoto:threshold``
|
||||
With ``-g`` ``--computed-gotos`` option this value specifies
|
||||
the complexity threshold that triggers the generation of jump tables instead
|
||||
of nested ``if`` statements and bitmaps. The default value is ``9``.
|
||||
``re2c:encoding:utf8``, ``re2c:flags:utf-8``, ``re2c:flags:8``
|
||||
Same as the ``--utf8`` option, but can be configured on per-block basis.
|
||||
|
||||
``re2c:flags:case-ranges``
|
||||
Same as ``--case-ranges`` command-line option.
|
||||
``re2c:encoding:utf16``, ``re2c:flags:utf-16``, ``re2c:flags:x``
|
||||
Same as the ``--utf16`` option, but can be configured on per-block basis.
|
||||
|
||||
``re2c:flags:e``, ``re2c:flags:ecb``
|
||||
Same as ``-e --ecb`` command-line option.
|
||||
``re2c:encoding:utf32``, ``re2c:flags:unicode``, ``re2c:flags:u``
|
||||
Same as the ``--utf32`` option, but can be configured on per-block basis.
|
||||
|
||||
``re2c:flags:8``, ``re2c:flags:utf-8``
|
||||
Same as ``-8 --utf-8`` command-line option.
|
||||
``re2c:encoding-policy``, ``re2c:flags:encoding-policy``
|
||||
Same as the ``--encoding-policy`` option, but can be configured on per-block
|
||||
basis.
|
||||
|
||||
``re2c:flags:w``, ``re2c:flags:wide-chars``
|
||||
Same as ``-w --wide-chars`` command-line option.
|
||||
``re2c:eof``
|
||||
Specifies the sentinel symbol used with the end-of-input rule ``$``. The
|
||||
default value is ``-1`` (``$`` rule is not used). Other possible values
|
||||
include all valid code units. Only decimal numbers are recognized.
|
||||
|
||||
``re2c:flags:x``, ``re2c:flags:utf-16``
|
||||
Same as ``-x --utf-16`` command-line option.
|
||||
|
||||
``re2c:flags:u``, ``re2c:flags:unicode``
|
||||
Same as ``-u --unicode`` command-line option.
|
||||
|
||||
``re2c:flags:encoding-policy``
|
||||
Same as ``--encoding-policy`` command-line option.
|
||||
|
||||
``re2c:flags:empty-class``
|
||||
Same as ``--empty-class`` command-line option.
|
||||
|
||||
``re2c:flags:case-insensitive``
|
||||
Same as ``--case-insensitive`` command-line option.
|
||||
|
||||
``re2c:flags:case-inverted``
|
||||
Same as ``--case-inverted`` command-line option.
|
||||
``re2c:header``, ``re2c:flags:type-header``, ``re2c:flags:t``
|
||||
Specifies the name of the generated header file relative to the directory of
|
||||
the output file. Same as the ``--header`` option except that the file path
|
||||
is relative.
|
||||
|
||||
``re2c:indent:string``
|
||||
Specifies the string to use for indentation.
|
||||
The default value is ``"\t"``.
|
||||
Indent string should contain only whitespace characters.
|
||||
To disable indentation entirely, set this configuration to empty
|
||||
string ``""``.
|
||||
Specifies the string used for indentation. The default is a single tab
|
||||
character ``"\t"``. Indent string should contain whitespace characters only.
|
||||
To disable indentation entirely, set this configuration to an empty string.
|
||||
|
||||
``re2c:indent:top``
|
||||
Specifies the minimum amount of indentation to use.
|
||||
The default value is zero.
|
||||
The value should be a non-negative integer number.
|
||||
Specifies the minimum amount of indentation to use. The default value is
|
||||
zero. The value should be a non-negative integer number.
|
||||
|
||||
``re2c:labelprefix``
|
||||
Allows one to change the prefix of DFA state labels.
|
||||
The default value is ``yy``.
|
||||
``re2c:label:prefix``, ``re2c:labelprefix``
|
||||
Specifies the prefix used for DFA state labels. The default is ``yy``.
|
||||
|
||||
``re2c:yych:emit``
|
||||
Set this to zero to suppress the generation of ``yych`` definition.
|
||||
Defaults to ``1`` (the definition is generated).
|
||||
``re2c:label:start``, ``re2c:startlabel``
|
||||
Controls the generation of a block start label. The default value is zero,
|
||||
which means that the start label is generated only if it is used. An integer
|
||||
value greater than zero forces the generation of start label even if it is
|
||||
unused by the lexer. A string value also forces start label generation and
|
||||
sets the label name to the specified string. This configuration applies only
|
||||
to the current block (it is reset to default for the next block).
|
||||
|
||||
``re2c:variable:yych``
|
||||
Overrides the name of the ``yych`` variable.
|
||||
``re2c:label:yyFillLabel``
|
||||
Specifies the prefix of ``YYFILL`` labels used with ``re2c:eof`` and in
|
||||
storable state mode.
|
||||
|
||||
``re2c:yych:conversion``
|
||||
If set to nonzero, re2c automatically generates a cast to ``YYCTYPE``
|
||||
every time ``yych`` is read. Defaults to zero (no cast).
|
||||
``re2c:label:yyloop``
|
||||
Specifies the name of the label marking the start of the lexer loop with
|
||||
``--loop-switch`` option. The default is ``yyloop``.
|
||||
|
||||
``re2c:label:yyNext``
|
||||
Specifies the name of the optional label that follows ``YYGETSTATE`` switch
|
||||
in storable state mode (enabled with ``re2c:state:nextlabel``). The default
|
||||
is ``yyNext``.
|
||||
|
||||
``re2c:lookahead``, ``re2c:flags:lookahead``
|
||||
Same as inverted ``--no-lookahead`` option, but can be configured on
|
||||
per-block basis.
|
||||
|
||||
``re2c:nested-ifs``, ``re2c:flags:nested-ifs``, ``re2c:flags:s``
|
||||
Same as the ``--nested-ifs`` option, but can be configured on per-block
|
||||
basis.
|
||||
|
||||
``re2c:posix-captures``, ``re2c:flags:posix-captures``, ``re2c:flags:P``
|
||||
Same as the ``--posix-captures`` option, but can be configured on per-block
|
||||
basis.
|
||||
|
||||
``re2c:tags``, ``re2c:flags:tags``, ``re2c:flags:T``
|
||||
Same as the ``--tags`` option, but can be configured on per-block basis.
|
||||
|
||||
``re2c:tags:expression``
|
||||
Specifies the expression used for tag variables.
|
||||
By default re2c generates expressions of the form ``yyt<N>``. This might
|
||||
be inconvenient, for example if tag variables are defined as fields in a
|
||||
struct. All occurrences of ``@@{tag}`` or ``@@`` are replaced with the
|
||||
actual tag name. For example, ``re2c:tags:expression = "s.@@";`` results
|
||||
in expressions of the form ``s.yyt<N>`` in the generated code.
|
||||
See also ``re2c:api:sigil`` configuration.
|
||||
|
||||
``re2c:tags:prefix``
|
||||
Specifies the prefix for tag variable names. The default is ``yyt``.
|
||||
|
||||
``re2c:sentinel``
|
||||
Specifies the sentinel symbol used for the end-of-input checks (when bounds
|
||||
checks are disabled with ``re2c:yyfill:enable = 0;`` and ``re2c:eof`` is not
|
||||
set). This configuration does not affect code generation: its purpose is to
|
||||
verify that the sentinel is not allowed in the middle of a rule, and ensure
|
||||
that the lexer won't read past the end of buffer. The default value is
|
||||
`-1`` (in that case re2c assumes that the sentinel is zero, which is the
|
||||
most common case). Only decimal numbers are recognized.
|
||||
|
||||
``re2c:state:abort``
|
||||
If set to a positive integer value, changes the default case in
|
||||
``YYGETSTATE`` switch: by default it aborts the program, and an explicit
|
||||
``-1`` case contains transition to the start of the block.
|
||||
|
||||
``re2c:state:nextlabel``
|
||||
Controls if the ``YYGETSTATE`` switch is followed by an ``yyNext`` label
|
||||
(the default value is zero, which corresponds to no label).
|
||||
Alternatively one can use ``re2c:label:start`` to generate a specific start
|
||||
label, or an explicit ``getstate:re2c`` directive to generate the
|
||||
``YYGETSTATE`` switch separately from the lexer block.
|
||||
|
||||
``re2c:unsafe``, ``re2c:flags:unsafe``
|
||||
Same as the ``--no-unsafe`` option, but can be configured on per-block
|
||||
basis.
|
||||
If set to zero, it suppresses the generation of ``unsafe`` wrappers around
|
||||
``YYPEEK``. The default is non-zero (wrappers are generated).
|
||||
This configuration is specific to Rust.
|
||||
|
||||
``re2c:variable:yyaccept``
|
||||
Overrides the name of the ``yyaccept`` variable.
|
||||
Specifies the name of the ``yyaccept`` variable (see the API primitives
|
||||
section).
|
||||
|
||||
``re2c:variable:yybm``
|
||||
Specifies the name of the ``yybm`` variable (used for bitmaps).
|
||||
|
||||
``re2c:variable:yybm:hex``, ``re2c:yybm:hex``
|
||||
If set to nonzero, bitmaps for the ``--bit-vectors`` option are generated
|
||||
in hexadecimal format. The default is zero (bitmaps are in decimal format).
|
||||
|
||||
``re2c:variable:yych``
|
||||
Specifies the name of the ``yych`` variable (see the API primitives
|
||||
section).
|
||||
|
||||
``re2c:variable:yych:emit``, ``re2c:yych:emit``
|
||||
If set to zero, ``yych`` definition is not generated.
|
||||
The default is non-zero.
|
||||
|
||||
``re2c:variable:yych:conversion``, ``re2c:yych:conversion``
|
||||
If set to non-zero, re2c automatically generates a conversion to ``YYCTYPE``
|
||||
every time ``yych`` is read. The default is to zero (no conversion).
|
||||
|
||||
``re2c:variable:yyctable``
|
||||
Specifies the name of the ``yyctable`` variable (the jump table generated
|
||||
for ``YYGETCONDITION`` switch with ``--computed-gotos`` option).
|
||||
|
||||
``re2c:variable:yytarget``
|
||||
Overrides the name of the ``yytarget`` variable.
|
||||
Specifies the name of the ``yytarget`` variable.
|
||||
|
||||
``re2c:variable:yystable``
|
||||
Deprecated.
|
||||
|
||||
``re2c:variable:yyctable``
|
||||
When both ``-c`` ``--conditions`` and ``-g`` ``--computed-gotos`` are active,
|
||||
re2c will use this variable to generate a static jump table
|
||||
for ``YYGETCONDITION``.
|
||||
``re2c:variable:yystate``
|
||||
Specifies the name of the ``yystate`` variable (used with the
|
||||
``--loop-switch`` option to store the current DFA state).
|
||||
|
||||
``re2c:define:YYDEBUG``
|
||||
Defines ``YYDEBUG`` (see the user interface section).
|
||||
``re2c:yyfill:check``
|
||||
If set to zero, suppresses the generation of pre-``YYFILL`` check for the
|
||||
number of input characters (the ``YYLESSTHAN`` definition in generic API and
|
||||
the ``YYLIMIT``-based comparison in C pointer API). The default is non-zero
|
||||
(generate the check).
|
||||
|
||||
``re2c:flags:d``, ``re2c:flags:debug-output``
|
||||
Same as ``-d --debug-output`` command-line option.
|
||||
``re2c:yyfill:enable``
|
||||
If set to zero, suppresses the generation of ``YYFILL`` (together
|
||||
with the check). This should be used when the whole input fits into one piece
|
||||
of memory (there is no need for buffering) and the end-of-input checks do not
|
||||
rely on the ``YYFILL`` checks (e.g. if a sentinel character is used).
|
||||
Use warnings (``-W`` option) and ``re2c:sentinel`` configuration to verify
|
||||
that the generated lexer cannot read past the end of input.
|
||||
The default is non-zero (``YYFILL`` is enabled).
|
||||
|
||||
``re2c:flags:dfa-minimization``
|
||||
Same as ``--dfa-minimization`` command-line option.
|
||||
|
||||
``re2c:flags:eager-skip``
|
||||
Same as ``--eager-skip`` command-line option.
|
||||
``re2c:yyfill:parameter``
|
||||
If set to zero, suppresses the generation of parameter passed to ``YYFILL``.
|
||||
The parameter is the minimum number of characters that must be supplied.
|
||||
Defaults to non-zero (the parameter is generated).
|
||||
This configuration can be overridden with ``re2c:define:YYFILL:naked`` or
|
||||
``re2c:api:style``.
|
||||
|
||||
@@ -82,16 +82,19 @@ sections.
|
||||
|
||||
``/*!getstate:re2c[:<name1>[:<name2>...]] ... */``
|
||||
A directive that generates conditional dispatch on the lexer state (it
|
||||
requires ``-f --storable-state`` option).
|
||||
requires ``--storable-state`` option).
|
||||
An optional list of block names specifies which blocks should be included in
|
||||
the state dispatch. The default transition goes to the start label of the
|
||||
first block on the list. If the list is empty, all blocks are included, and
|
||||
the default transition goes to the first block in the file that has a start
|
||||
label.
|
||||
This directive is incompatible with the ``--loop-switch`` option and Rust,
|
||||
as it requires cross-block transitions that are unsupported without the
|
||||
``goto`` statement.
|
||||
|
||||
``/*!types:re2c[:<name1>[:<name2>...]] ... */``
|
||||
``/*!conditions:re2c[:<name1>[:<name2>...]] ... */``, ``/*!types:re2c... */``
|
||||
A directive that generates condition enumeration (it requires
|
||||
``-c --conditions`` option).
|
||||
``--conditions`` option).
|
||||
An optional list of block names specifies which blocks should be included
|
||||
when computing the set of conditions (if the list is empty, all blocks are
|
||||
included).
|
||||
@@ -127,5 +130,5 @@ sections.
|
||||
A block which contents are ignored and removed from the output file.
|
||||
|
||||
``%{ ... %}``
|
||||
A global re2c block in ``-F --flex-support`` mode. This is deprecated and
|
||||
A global re2c block in the ``--flex-support`` mode. This is deprecated and
|
||||
exists for backward compatibility.
|
||||
|
||||
@@ -1,45 +1,51 @@
|
||||
Speaking of encodings, it is necessary to understand the difference between code points and code units.
|
||||
Code point is an abstract symbol.
|
||||
Code unit is the smallest atomic unit of storage in the encoded text.
|
||||
A single code point may be represented with one or more code units.
|
||||
In a fixed-length encoding all code points are represented with the same number of code units.
|
||||
In a variable-length encoding code points may be represented with a different number of code units.
|
||||
Note that the "any" rule ``[^]`` matches any code point, but not necessarily any code unit.
|
||||
The only way to match any code unit regardless of the encoding it the default rule ``*``.
|
||||
``YYCTYPE`` size should be equal to the size of code unit.
|
||||
It is necessary to understand the difference between **code points** and
|
||||
**code units**. A code point is a numeric identifier of a symbol. A code unit is
|
||||
the smallest unit of storage in the encoded text. A single code point may be
|
||||
represented with one or more code units. In a fixed-length encoding all code
|
||||
points are represented with the same number of code units. In a variable-length
|
||||
encoding code points may be represented with a different number of code units.
|
||||
Note that the "any" rule ``[^]`` matches any code point, but not necessarily
|
||||
any code unit (the only way to match any code unit regardless of the encoding
|
||||
is the default rule ``*``).
|
||||
The generated lexer works with a stream of code units: ``yych`` stores a code
|
||||
unit, and ``YYCTYPE`` is the code unit type. Regular expressions, on the other
|
||||
hand, are specified in terms of code points. When re2c compiles regular
|
||||
expressions to automata it translates code points to code units. This is
|
||||
generally not a simple mapping: in variable-length encodings a single code point
|
||||
range may get translated to a complex code unit graph.
|
||||
The following encodings are supported:
|
||||
|
||||
Re2c supports the following encodings: ASCII, EBCDIC, UCS2, UTF8, UTF16 and UTF32.
|
||||
- **ASCII** (enabled by default). It is a fixed-length encoding with code space
|
||||
``[0-255]`` and 1-byte code points and code units.
|
||||
|
||||
* ASCII is enabled by default.
|
||||
It is a fixed-length encoding with code space [0-255] and 1-byte code points
|
||||
- **EBCDIC** (enabled with ``--ebcdic`` or ``re2c:encoding:ebcdic``). It is a
|
||||
fixed-length encoding with code space ``[0-255]`` and 1-byte code points and
|
||||
code units.
|
||||
|
||||
- **UCS2** (enabled with ``--ucs2`` or ``re2c:encoding:ucs2``). It is a
|
||||
fixed-length encoding with code space ``[0-0xFFFF]`` and 2-byte code points
|
||||
and code units.
|
||||
|
||||
* EBCDIC is enabled with ``-e, --ecb`` option.
|
||||
It a fixed-length encoding with code space [0-255] and 1-byte code points
|
||||
and code units.
|
||||
- **UTF8** (enabled with ``--utf8`` or ``re2c:encoding:utf8``). It is a
|
||||
variable-length Unicode encoding. Code unit size is 1 byte. Code points are
|
||||
represented with 1 -- 4 code units.
|
||||
|
||||
* UCS2 is enabled with ``-w, --wide-chars`` option.
|
||||
It is a fixed-length encoding with code space [0-0xFFFF] and 2-byte code
|
||||
- **UTF16** (enabled with ``--utf16`` or ``re2c:encoding:utf16``). It is a
|
||||
variable-length Unicode encoding. Code unit size is 2 bytes. Code points are
|
||||
represented with 1 -- 2 code units.
|
||||
|
||||
- **UTF32** (enabled with ``--utf32`` or ``re2c:encoding:utf32``). It is a
|
||||
fixed-length Unicode encoding with code space ``[0-0x10FFFF]`` and 4-byte code
|
||||
points and code units.
|
||||
|
||||
* UTF8 is enabled with ``-8, --utf-8`` option.
|
||||
It is a variable-length Unicode encoding with code space [0-0x10FFFF].
|
||||
Code points are represented with one, two, three or four 1-byte code units.
|
||||
Include file ``include/unicode_categories.re`` provides re2c definitions for the
|
||||
standard Unicode categories.
|
||||
|
||||
* UTF16 is enabled with ``-x, --utf-16`` option.
|
||||
It is a variable-length Unicode encoding with code space [0-0x10FFFF].
|
||||
Code points are represented with one or two 2-byte code units.
|
||||
Option ``--input-encoding`` specifies source file encoding, which can be used to
|
||||
enable Unicode literals in regular expressions. For example
|
||||
``--input-encoding utf8`` tells re2c that the source file is in UTF8 (it differs
|
||||
from ``--utf8`` which sets input text encoding). Option ``--encoding-policy``
|
||||
specifies the way re2c handles Unicode surrogates (code points in range
|
||||
``[0xD800-0xDFFF]``).
|
||||
|
||||
* UTF32 is enabled with ``-u, --unicode`` option.
|
||||
It is a fixed-length Unicode encoding with code space [0-0x10FFFF] and 4-byte
|
||||
code points and code units.
|
||||
|
||||
Encodings can also be set or unset using ``re2c:flags`` configuration,
|
||||
for example ``re2c:flags:8 = 1;`` enables UTF8.
|
||||
|
||||
Include file ``include/unicode_categories.re`` provides re2c definitions for the standard Unicode categories.
|
||||
|
||||
Option ``--input-encoding utf8`` enables Unicode literals in regular expressions.
|
||||
|
||||
Option ``--encoding-policy <fail | substitute | ignore>``
|
||||
specifies the way re2c handles Unicode surrogates: code points in the range [0xD800-0xDFFF].
|
||||
Below is an example of a lexer for UTF8 encoded Unicode identifiers.
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
Sentinel character
|
||||
------------------
|
||||
Sentinel
|
||||
--------
|
||||
|
||||
In this example the lexer uses a sentinel character to handle the end of input.
|
||||
The program counts space-separated words in a null-terminated string.
|
||||
Configuration ``re2c:yyfill:enable = 0;`` suppresses the generation of bounds checks and ``YYFILL`` invocations.
|
||||
The sentinel character is null.
|
||||
It is the last character of each input string,
|
||||
and it is not allowed in the middle of a lexeme by any of the rules
|
||||
(in particular, it is not included in the character ranges, where it is easy to overlook).
|
||||
If a null occurs in the middle of a string, it is a syntax error and the lexer will match default rule ``*``, but it won't read past the end of input or crash.
|
||||
This example uses a sentinel character to handle the end of input. The program
|
||||
counts space-separated words in a null-terminated string. The sentinel is null:
|
||||
it is the last character of each input string, and it is not allowed in the
|
||||
middle of a lexeme by any of the rules (in particular, it is not included in
|
||||
character ranges where it is easy to overlook). If a null occurs in the middle
|
||||
of a string, it is a syntax error and the lexer will match default rule ``*``,
|
||||
but it won't read past the end of input or crash (use
|
||||
`-Wsentinel-in-midrule <https://re2c.org/manual/warnings/warnings.html#wsentinel-in-midrule>`_
|
||||
warning verifies that the rules do not allow sentinel in the middle
|
||||
(it is possible to tell re2c which character is used as a sentinel with ``re2c:sentinel`` configuration ---
|
||||
the default assumption is null, since this is the most common case).
|
||||
warning and ``re2c:sentinel`` configuration to verify this). Configuration
|
||||
``re2c:yyfill:enable = 0;`` suppresses the generation of bounds checks and
|
||||
``YYFILL`` invocations.
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
Bounds checks with padding
|
||||
--------------------------
|
||||
|
||||
In this example the lexer uses bounds checking with padding to handle the end of input (it is the default method).
|
||||
The program counts single-quoted strings separated with spaces.
|
||||
There is a padding of ``YYMAXFILL`` null characters appended at the end of input,
|
||||
where ``YYMAXFILL`` value is autogenerated with ``/*!max:re2c*/`` directive.
|
||||
It is not necessary to use null for padding --- any characters can be used, as long as they do not form a valid lexeme suffix
|
||||
(in this example padding should not contain single quotes, as they may be mistaken for a suffix of a single-quoted string).
|
||||
There is a "stop" rule that matches the first padding character (null) and terminates the lexer
|
||||
(it returns success only if it has matched at the beginning of padding, otherwise a stray null is syntax error).
|
||||
Bounds checks are generated only in some states that depend on the strongly connected components of the underlying automaton.
|
||||
They are of the form ``(YYLIMIT - YYCURSOR) < n`` or ``YYLESSTHAN(n)`` with generic API,
|
||||
where ``n`` is the minimum number of characters that are needed for the lexer to proceed
|
||||
(it also means that the next bounds check will occur in at most ``n`` characters).
|
||||
If a bounds check succeeds, the lexer will continue matching.
|
||||
If a bounds check fails, the lexer has reached the end of input and will invoke ``YYFILL(n)``,
|
||||
which should either supply at least ``n`` input characters, or it should not return.
|
||||
In this example ``YYFILL`` always fails and terminates the lexer with an error.
|
||||
This is fine, because in this example ``YYFILL`` can only be called when the lexer has advanced into the padding,
|
||||
which means that is has encountered an unterminated string and should return a syntax error.
|
||||
See the `YYFILL with padding`_ section for an example that refills the input buffer with ``YYFILL``.
|
||||
This example uses bounds checks with padding to handle the end of input (this
|
||||
method is enabled by default). The program counts space-separated single-quoted
|
||||
strings. There is a padding of ``YYMAXFILL`` null characters appended at the end
|
||||
of input, where ``YYMAXFILL`` value is autogenerated with ``/*!max:re2c*/``. It
|
||||
is not necessary to use null for padding --- any characters can be used as long
|
||||
as they do not form a valid lexeme suffix (in this example padding should not
|
||||
contain single quotes, as they may be mistaken for a suffix of a single-quoted
|
||||
string). There is a "stop" rule that matches the first padding character (null)
|
||||
and terminates the lexer (note that it checks if null is at the beginning of
|
||||
padding, otherwise it is a syntax error). Bounds checks are generated only in
|
||||
some states that are determined by the strongly connected components of the
|
||||
underlying automaton. Checks have the form ``(YYLIMIT - YYCURSOR) < n`` or
|
||||
``YYLESSTHAN(n)`` with generic API, where ``n`` is the minimum number of
|
||||
characters that are needed for the lexer to proceed (it also means that the next
|
||||
bounds check will occur in at most ``n`` characters). If the check condition is
|
||||
true, the lexer has reached the end of input and will invoke ``YYFILL(n)`` that
|
||||
should either supply at least ``n`` input characters or not return. In this
|
||||
example ``YYFILL`` always fails and terminates the lexer with an error (which is
|
||||
fine because the input fits into one buffer). See the `YYFILL with padding`_
|
||||
section for an example that refills the input buffer with ``YYFILL``.
|
||||
|
||||
@@ -1,27 +1,21 @@
|
||||
Sentinel character with bounds checks
|
||||
-------------------------------------
|
||||
Sentinel with bounds checks
|
||||
---------------------------
|
||||
|
||||
In this example the lexer uses sentinel character with bounds checks to handle the end of input
|
||||
(this method was added in version 1.2).
|
||||
The program counts single-quoted strings separated with spaces.
|
||||
The sentinel character is null, which is specified with ``re2c:eof = 0;`` configuration.
|
||||
Null is the last character of each input string --- this is essential to detect the end of input.
|
||||
Null, as well as any other character, is allowed in the middle of a rule
|
||||
(for example, ``'aaa\0aa'\0`` is valid input, but ``'aaa\0`` is a syntax error).
|
||||
Bounds checks are generated in each state that has a switch on an input character,
|
||||
in the conditional branch that corresponds to null
|
||||
(that branch may also cover other characters ---
|
||||
re2c does not split out a separate branch for sentinel,
|
||||
because increasing the number of branches degrades performance more than bounds checks do).
|
||||
Bounds checks are of the form ``YYLIMIT <= YYCURSOR`` or ``YYLESSTHAN(1)`` with generic API.
|
||||
If a bounds check succeeds, the lexer will continue matching.
|
||||
If a bounds check fails, the lexer has reached the end of input, and it should stop.
|
||||
In this example ``YYFILL`` is disabled with ``re2c:yyfill:enable = 0;``
|
||||
and the lexer does not attempt to get more input
|
||||
(see another example that uses ``YYFILL`` in the `YYFILL with sentinel character`_ section).
|
||||
When the end of input has been reached, there are three possibilities:
|
||||
if the lexer is in the initial state, it will match the end of input rule ``$``,
|
||||
otherwise it will either fallback to a previously matched rule (including default rule ``*``)
|
||||
or go to a default state, causing
|
||||
This example uses sentinel with bounds checks to handle the end of input (this
|
||||
method was added in version 1.2). The program counts space-separated
|
||||
single-quoted strings. The sentinel character is null, which is specified with
|
||||
``re2c:eof = 0;`` configuration. As in the `sentinel`_ method, null is the last
|
||||
character of each input string, but it is allowed in the middle of a rule (for
|
||||
example, ``'aaa\0aa'\0`` is valid input, but ``'aaa\0`` is a syntax error).
|
||||
Bounds checks are generated in each state that matches an input character, but
|
||||
they are scoped to the branch that handles null. Bounds checks are of the form
|
||||
``YYLIMIT <= YYCURSOR`` or ``YYLESSTHAN(1)`` with generic API. If the check
|
||||
condition is true, lexer has reached the end of input and should stop
|
||||
(``YYFILL`` is disabled with ``re2c:yyfill:enable = 0;`` as the input fits into
|
||||
one buffer, see the `YYFILL with sentinel`_ section for an example that uses
|
||||
``YYFILL``). Reaching the end of input opens three possibilities: if the lexer
|
||||
is in the initial state it will match the end-of-input rule ``$``, otherwise it
|
||||
may fallback to a previously matched rule (including default rule ``*``) or go
|
||||
to a default state, causing
|
||||
`-Wundefined-control-flow <https://re2c.org/manual/warnings/warnings.html#wundefined-control-flow>`_.
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
Custom methods with generic API
|
||||
-------------------------------
|
||||
Custom checks
|
||||
-------------
|
||||
|
||||
In this example the lexer uses a custom end of input handling method based on generic API.
|
||||
The program counts single-quoted strings separated with spaces.
|
||||
It is the same as the `sentinel character with bounds checks`_ example,
|
||||
except that the input is not null-terminated
|
||||
(so this method can be used if it's not possible to have any padding at all, not even a single sentinel character).
|
||||
To cover up for the absence of sentinel character at the end of input,
|
||||
``YYPEEK`` is redefined to perform a bounds check before it reads the next input character.
|
||||
This is inefficient, because checks are done very often.
|
||||
If the check succeeds, ``YYPEEK`` returns the real character,
|
||||
otherwise it returns a fake sentinel character.
|
||||
This example uses a custom end-of-input handling method based on generic API.
|
||||
The program counts space-separated single-quoted strings. It is the same as the
|
||||
`sentinel with bounds checks`_ example, except that the input is not
|
||||
null-terminated (this method can be used if padding is not an option, not even a
|
||||
single character). To cover up for the absence of sentinel character at the end
|
||||
of input, ``YYPEEK`` is redefined to perform a bounds check before it reads the
|
||||
next input character. This is inefficient because checks are done very often. If
|
||||
the check condition fails, ``YYPEEK`` returns the real character, otherwise it
|
||||
returns a fake sentinel character.
|
||||
|
||||
+55
-49
@@ -1,71 +1,77 @@
|
||||
One of the main problems for the lexer is to know when to stop.
|
||||
There are a few terminating conditions:
|
||||
|
||||
- the lexer may match some rule (including default rule ``*``) and come to a final state
|
||||
- the lexer may match some rule (including default rule ``*``) and come to a
|
||||
final state
|
||||
- the lexer may fail to match any rule and come to a default state
|
||||
- the lexer may reach the end of input
|
||||
|
||||
The first two conditions terminate the lexer in a "natural" way:
|
||||
it comes to a state with no outgoing transitions, and the matching automatically stops.
|
||||
The third condition, end of input, is different: it may happen in any state, and the lexer should be able to handle it.
|
||||
Checking for the end of input interrupts the normal lexer workflow
|
||||
and adds conditional branches to the generated program, therefore it is necessary to minimize the number of such checks.
|
||||
re2c supports a few different methods for end of input handling.
|
||||
Which one to use depends on the complexity of regular expressions, the need for buffering, performance considerations and other factors.
|
||||
Here is a list of all methods:
|
||||
The first two conditions terminate the lexer in a "natural" way: it comes to a
|
||||
state with no outgoing transitions, and the matching automatically stops. The
|
||||
third condition, end of input, is different: it may happen in any state, and the
|
||||
lexer should be able to handle it. Checking for the end of input interrupts the
|
||||
normal lexer workflow and adds conditional branches to the generated program,
|
||||
therefore it is necessary to minimize the number of such checks. re2c supports a
|
||||
few different methods for handling the end of input. Which one to use depends on
|
||||
the complexity of regular expressions, the need for buffering, performance
|
||||
considerations and other factors. Here is a list of methods:
|
||||
|
||||
- **Sentinel character.**
|
||||
This method eliminates the need for the end of input checks altogether.
|
||||
It is simple and efficient, but limited to the case when there is a natural "sentinel" character that can never occur in valid input.
|
||||
This character may still occur in invalid input, but it is not allowed by the regular expressions, except perhaps as the last character of a rule.
|
||||
The sentinel character is appended at the end of input and serves as a stop signal:
|
||||
when the lexer reads it, it must be either the end of input, or a syntax error.
|
||||
In both cases the lexer stops.
|
||||
This method is used if ``YYFILL`` is disabled with ``re2c:yyfill:enable = 0;`` and ``re2c:eof`` has the default value -1.
|
||||
- **Sentinel.**
|
||||
This method eliminates the need for the end of input checks altogether. It is
|
||||
simple and efficient, but limited to the case when there is a natural
|
||||
"sentinel" character that can never occur in valid input. This character may
|
||||
still occur in invalid input, but it should not be allowed by the regular
|
||||
expressions, except perhaps as the last character of a rule. The sentinel is
|
||||
appended at the end of input and serves as a stop signal: when the lexer reads
|
||||
this character, it is either a syntax error or the end of input. In both
|
||||
cases the lexer should stop. This method is used if ``YYFILL`` is disabled
|
||||
with ``re2c:yyfill:enable = 0;`` and ``re2c:eof`` has the default value
|
||||
``-1``.
|
||||
|
||||
|
|
||||
|
||||
- **Sentinel character with bounds checks.**
|
||||
This method is generic: it allows to handle any input without restrictions on the regular expressions.
|
||||
The idea is to reduce the number of end of input checks by performing them only on certain characters.
|
||||
Similar to the "sentinel character" method, one of the characters is chosen as a "sentinel" and appended at the end of input.
|
||||
However, there is no restriction on where the sentinel character may occur (in fact, any character can be chosen for a sentinel).
|
||||
- **Sentinel with bounds checks.**
|
||||
This method is generic: it allows to handle any input without restrictions on
|
||||
the regular expressions. The idea is to reduce the number of end of input
|
||||
checks by performing them only on certain characters. Similar to the
|
||||
"sentinel" method, one of the characters is chosen as a "sentinel" and
|
||||
appended at the end of input. However, there is no restriction on where the
|
||||
sentinel may occur (in fact, any character can be chosen for a sentinel).
|
||||
When the lexer reads this character, it additionally performs a bounds check.
|
||||
If the current position is within bounds, the lexer will resume matching and handle the sentinel character as a regular one.
|
||||
Otherwise it will try to get more input with ``YYFILL`` (unless ``YYFILL`` is disabled).
|
||||
If more input is available, the lexer will rematch the last character and continue as if the sentinel never occurred.
|
||||
Otherwise it is the real end of input, and the lexer will stop.
|
||||
This method is used if ``re2c:eof`` has non-negative value (it should be set to the ordinal of the sentinel character).
|
||||
``YYFILL`` must be either defined or disabled with ``re2c:yyfill:enable = 0;``.
|
||||
If the current position is within bounds, the lexer resumes matching and
|
||||
handles the sentinel as a regular character. Otherwise it invokes ``YYFILL``
|
||||
(unless it is disabled). If more input is supplied, the lexer will rematch the
|
||||
last character and continue as if the sentinel wasn't there. Otherwise it must
|
||||
be the real end of input, and the lexer stops. This method is used when
|
||||
``re2c:eof`` has non-negative value (it should be set to the numeric value of
|
||||
the sentinel). ``YYFILL`` is optional.
|
||||
|
||||
|
|
||||
|
||||
- **Bounds checks with padding.**
|
||||
This method is the default one.
|
||||
It is generic, and it is usually faster than the "sentinel character with bounds checks" method, but also more complex to use.
|
||||
The idea is to partition the underlying finite-state automaton into strongly connected components (SCCs),
|
||||
and generate only one bounds check per SCC, but make it check for multiple characters at once
|
||||
(enough to cover the longest non-looping path in the SCC).
|
||||
This way the checks are less frequent, which makes the lexer run much faster.
|
||||
If a check shows that there is not enough input, the lexer will invoke ``YYFILL``,
|
||||
which may either supply enough input or else it should not return (in the latter case the lexer will stop).
|
||||
This approach has a problem with matching short lexemes at the end of input,
|
||||
because the multi-character check requires enough characters to cover the longest possible lexeme.
|
||||
To fix this problem, it is necessary to append a few fake characters at the end of input.
|
||||
The padding should not form a valid lexeme suffix to avoid fooling the lexer into matching it as part of the input.
|
||||
The minimum sufficient length of padding is ``YYMAXFILL`` and it is autogenerated by re2c with ``/*!max:re2c*/``.
|
||||
This method is used if ``re2c:yyfill:enable`` has the default nonzero value, and ``re2c:eof`` has the default value -1.
|
||||
``YYFILL`` must be defined.
|
||||
This method is generic, and it may be faster than the "sentinel with bounds
|
||||
checks" method, but it is also more complex. The idea is to partition DFA
|
||||
states into strongly connected components (SCCs) and generate a single check
|
||||
per SCC for enough characters to cover the longest non-looping path in this
|
||||
SCC. This reduces the number of checks, but there is a problem with short
|
||||
lexemes at the end of input, as the check requires enough characters to cover
|
||||
the longest lexeme. This can be fixed by padding the input with a few fake
|
||||
characters that do not form a valid lexeme suffix (so that the lexer cannot
|
||||
match them). The length of padding should be ``YYMAXFILL``, generated with
|
||||
``/*!max:re2c*/``. If there is not enough input, the lexer invokes ``YYFILL``
|
||||
which should supply at least the required number of characters or not return.
|
||||
This method is used if ``YYFILL`` is enabled and ``re2c:eof`` is ``-1``
|
||||
(this is the default configuration).
|
||||
|
||||
|
|
||||
|
||||
- **Custom methods with generic API.**
|
||||
- **Custom checks.**
|
||||
Generic API allows to override basic operations like reading a character,
|
||||
which makes it possible to include the end of input checks as part of them.
|
||||
Such methods are error-prone and should be used with caution, only if other methods cannot be used.
|
||||
These methods are used if generic API is enabled with ``--input custom`` or ``re2c:flags:input = custom;``
|
||||
and default bounds checks are disabled with ``re2c:yyfill:enable = 0;``.
|
||||
Note that the use of generic API does not imply the use of custom methods, it merely allows it.
|
||||
which makes it possible to include the end-of-input checks as part of them.
|
||||
This approach is error-prone and should be used with caution. To use a custom
|
||||
method, enable generic API with ``--api custom`` or ``re2c:api = custom;`` and
|
||||
disable default bounds checks with ``re2c:yyfill:enable = 0;`` or
|
||||
``re2c:yyfill:check = 0;``.
|
||||
|
||||
|
||||
The following subsections contain an example of each method.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
YYFILL with sentinel character
|
||||
------------------------------
|
||||
YYFILL with sentinel
|
||||
--------------------
|
||||
|
||||
If EOF rule is used, ``YYFILL`` is a function-like primitive that accepts
|
||||
no arguments and returns a value which is checked against zero. ``YYFILL``
|
||||
invocation is triggered by condition ``YYLIMIT <= YYCURSOR`` in default API and
|
||||
invocation is triggered by condition ``YYLIMIT <= YYCURSOR`` in C pointer API and
|
||||
``YYLESSTHAN()`` in generic API. A non-zero return value means that ``YYFILL``
|
||||
has failed. A successful ``YYFILL`` call must supply at least one character and
|
||||
adjust input positions accordingly. Limit must always be set to one after the
|
||||
|
||||
@@ -4,7 +4,7 @@ YYFILL with padding
|
||||
In the default case (when EOF rule is not used) ``YYFILL`` is a function-like
|
||||
primitive that accepts a single argument and does not return any value.
|
||||
``YYFILL`` invocation is triggered by condition ``(YYLIMIT - YYCURSOR) < n`` in
|
||||
default API and ``YYLESSTHAN(n)`` in generic API. The argument passed to
|
||||
C pointer API and ``YYLESSTHAN(n)`` in generic API. The argument passed to
|
||||
``YYFILL`` is the minimal number of characters that must be supplied. If it
|
||||
fails to do so, ``YYFILL`` must not return to the lexer (for that reason it is
|
||||
best implemented as a macro that returns from the calling function on failure).
|
||||
|
||||
@@ -4,13 +4,13 @@ from a socket). The usual technique in such cases is to allocate a fixed-sized
|
||||
memory buffer and process input in chunks that fit into the buffer. When the
|
||||
current chunk is processed, it is moved out and new data is moved in. In
|
||||
practice it is somewhat more complex, because lexer state consists not of a
|
||||
single input position, but a set of interrelated posiitons:
|
||||
single input position, but a set of interrelated positions:
|
||||
|
||||
- cursor: the next input character to be read (``YYCURSOR`` in default API or
|
||||
- cursor: the next input character to be read (``YYCURSOR`` in C pointer API or
|
||||
``YYSKIP``/``YYPEEK`` in generic API)
|
||||
|
||||
- limit: the position after the last available input character (``YYLIMIT`` in
|
||||
default API, implicitly handled by ``YYLESSTHAN`` in generic API)
|
||||
C pointer API, implicitly handled by ``YYLESSTHAN`` in generic API)
|
||||
|
||||
- marker: the position of the most recent match, if any (``YYMARKER`` in default
|
||||
API or ``YYBACKUP``/``YYRESTORE`` in generic API)
|
||||
@@ -20,7 +20,7 @@ single input position, but a set of interrelated posiitons:
|
||||
user)
|
||||
|
||||
- context marker: the position of the trailing context (``YYCTXMARKER`` in
|
||||
default API or ``YYBACKUPCTX``/``YYRESTORECTX`` in generic API)
|
||||
C pointer API or ``YYBACKUPCTX``/``YYRESTORECTX`` in generic API)
|
||||
|
||||
- tag variables: submatch positions (defined with ``/*!stags:re2c*/`` and
|
||||
``/*!mtags:re2c*/`` directives and
|
||||
@@ -37,4 +37,4 @@ lexer). The details of ``YYFILL`` implementation are slightly different
|
||||
depending on which EOF handling method is used: the case of EOF rule is somewhat
|
||||
simpler than the case of bounds-checking with padding. Also note that if
|
||||
``-f --storable-state`` option is used, ``YYFILL`` has slightly different
|
||||
semantics (desrbed in the section about storable state).
|
||||
semantics (described in the section about storable state).
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Re2c allows one to generate header file from the input ``.re`` file using option
|
||||
re2c allows one to generate header file from the input ``.re`` file using option
|
||||
``-t``, ``--type-header`` or configuration ``re2c:flags:type-header`` and
|
||||
directives ``/*!header:re2c:on*/`` and ``/*!header:re2c:off*/``. The first directive
|
||||
marks the beginning of header file, and the second directive marks the end of
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
|
||||
``-D --emit-dot``
|
||||
Instead of normal output generate lexer graph in .dot format.
|
||||
The output can be converted to an image with the help of Graphviz
|
||||
(e.g. something like ``dot -Tpng -odfa.png dfa.dot``).
|
||||
|
||||
``-d --debug-output``
|
||||
Emit ``YYDEBUG`` in the generated code.
|
||||
``YYDEBUG`` should be defined by the user in the form of a void function
|
||||
with two parameters: ``state`` (lexer state or -1) and ``symbol`` (current
|
||||
input symbol of type ``YYCTYPE``).
|
||||
``--debug-output -d``
|
||||
Emit ``YYDEBUG`` invocations in the generated code. This is useful to trace
|
||||
lexer execution.
|
||||
|
||||
``--dump-adfa``
|
||||
Debug option: output DFA after tunneling (in .dot format).
|
||||
@@ -43,3 +36,7 @@
|
||||
``--dump-nfa``
|
||||
Debug option: output NFA (in .dot format).
|
||||
|
||||
``--emit-dot -D``
|
||||
Instead of normal output generate lexer graph in .dot format.
|
||||
The output can be converted to an image with the help of Graphviz
|
||||
(e.g. something like ``dot -Tpng -odfa.png dfa.dot``).
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
This option has effect only with ``--tags`` or ``--posix-captures`` options.
|
||||
|
||||
``--no-optimize-tags``
|
||||
Internal optionL: suppress optimization of tag variables (useful for
|
||||
Internal option: suppress optimization of tag variables (useful for
|
||||
debugging).
|
||||
|
||||
``--posix-closure <gor1 | gtop>``
|
||||
@@ -45,7 +45,7 @@
|
||||
(``all``), none of them (``none``), or only those in toplevel concatenation
|
||||
(``toplevel``). The default is ``all``.
|
||||
"Fixed" tags are those that are located within a fixed distance to some
|
||||
other tag (called "base"). In such cases only tha base tag needs to be
|
||||
other tag (called "base"). In such cases only the base tag needs to be
|
||||
tracked, and the value of the fixed tag can be computed as the value of the
|
||||
base tag plus a static offset. For tags that are under alternative or
|
||||
repetition it is also necessary to check if the base tag has a no-match
|
||||
|
||||
+107
-91
@@ -1,22 +1,15 @@
|
||||
|
||||
``-? -h --help``
|
||||
``-? --help -h``
|
||||
Show help message.
|
||||
|
||||
``-1 --single-pass``
|
||||
Deprecated. Does nothing (single pass is the default now).
|
||||
``--api --input <default | custom>``
|
||||
Specify the API used by the generated code to interface with used-defined
|
||||
code: ``default`` is the API based on pointer arithmetic (the default for
|
||||
C), and ``custom`` is the generic API (the default for Go and Rust).
|
||||
|
||||
``-8 --utf-8``
|
||||
Generate a lexer that reads input in UTF-8 encoding.
|
||||
re2c assumes that character range is 0 -- 0x10FFFF and character size is
|
||||
1 byte.
|
||||
|
||||
``-b --bit-vectors``
|
||||
Optimize conditional jumps using bit masks. Implies ``-s``.
|
||||
|
||||
``-c --conditions --start-conditions``
|
||||
Enable support of Flex-like "conditions": multiple interrelated lexers
|
||||
within one block. Option ``--start-conditions`` is a legacy alias; use
|
||||
``--conditions`` instead.
|
||||
``--bit-vectors -b``
|
||||
Optimize conditional jumps using bit masks.
|
||||
This option implies ``--nested-ifs``.
|
||||
|
||||
``--case-insensitive``
|
||||
Treat single-quoted and double-quoted strings as case-insensitive.
|
||||
@@ -28,22 +21,34 @@
|
||||
|
||||
``--case-ranges``
|
||||
Collapse consecutive cases in a switch statements into a range of the form
|
||||
``case low ... high:``. This syntax is an extension of the C/C++ language,
|
||||
``low ... high``. This syntax is a C/C++ language extension that is
|
||||
supported by compilers like GCC, Clang and Tcc. The main advantage over
|
||||
using single cases is smaller generated C code and faster generation time,
|
||||
using single cases is smaller generated code and faster generation time,
|
||||
although for some compilers like Tcc it also results in smaller binary size.
|
||||
This option doesn't work for the Go backend.
|
||||
This option is supported only for C.
|
||||
|
||||
``--computed-gotos -g``
|
||||
Optimize conditional jumps using non-standard "computed goto" extension
|
||||
(which must be supported by the compiler). re2c generates jump tables
|
||||
only in complex cases with a lot of conditional branches. Complexity
|
||||
threshold can be configured with ``cgoto:threshold`` configuration. This
|
||||
option implies ``--bit-vectors``. It is supported only for C.
|
||||
|
||||
``--conditions --start-conditions -c``
|
||||
Enable support of Flex-like "conditions": multiple interrelated lexers
|
||||
within one block. This is an alternative to manually specifying different
|
||||
re2c blocks connected with ``goto`` or function calls.
|
||||
|
||||
``--depfile FILE``
|
||||
Write dependency information to ``FILE`` in the form of a Makefile rule
|
||||
``<output-file> : <input-file> [include-file ...]``. This allows to track
|
||||
build dependencies in the presence of ``/*!include:re2c*/`` directives, so
|
||||
that updating include files triggers regeneration of the output file.
|
||||
This option requires that ``-o --output`` option is specified.
|
||||
``<output-file> : <input-file> [include-file ...]``. This allows one to
|
||||
track build dependencies in the presence of ``include:re2c`` directives,
|
||||
so that updating include files triggers regeneration of the output file.
|
||||
This option depends on the ``--output`` option.
|
||||
|
||||
``-e --ecb``
|
||||
Generate a lexer that reads input in EBCDIC encoding.
|
||||
re2c assumes that character range is 0 -- 0xFF an character size is 1 byte.
|
||||
``--ebcdic --ecb -e``
|
||||
Generate a lexer that reads input in EBCDIC encoding. re2c assumes that the
|
||||
character range is 0 -- 0xFF and character size is 1 byte.
|
||||
|
||||
``--empty-class <match-empty | match-none | error>``
|
||||
Define the way re2c treats empty character classes. With ``match-empty``
|
||||
@@ -59,43 +64,23 @@
|
||||
normal code points. The Unicode standard says that standalone surrogates
|
||||
are invalid, but real-world libraries and programs behave in different ways.
|
||||
|
||||
``-f --storable-state``
|
||||
Generate a lexer which can store its inner state.
|
||||
This is useful in push-model lexers which are stopped by an outer program
|
||||
when there is not enough input, and then resumed when more input becomes
|
||||
available. In this mode users should additionally define ``YYGETSTATE()``
|
||||
and ``YYSETSTATE(state)`` macros and variables ``yych``, ``yyaccept``
|
||||
and ``state`` as part of the lexer state.
|
||||
|
||||
``-F --flex-syntax``
|
||||
``--flex-syntax -F``
|
||||
Partial support for Flex syntax: in this mode named definitions don't need
|
||||
the equal sign and the terminating semicolon, and when used they must be
|
||||
surrounded by curly braces. Names without curly braces are treated as
|
||||
surrounded with curly braces. Names without curly braces are treated as
|
||||
double-quoted strings.
|
||||
|
||||
``-g --computed-gotos``
|
||||
Optimize conditional jumps using non-standard "computed goto" extension
|
||||
(which must be supported by the compiler). re2c generates jump tables
|
||||
only in complex cases with a lot of conditional branches. Complexity
|
||||
threshold can be configured with ``cgoto:threshold`` configuration. This
|
||||
option implies ``-b``. This option doesn't work for the Go backend.
|
||||
``--header --type-header -t HEADER``
|
||||
Generate a ``HEADER`` file. The contents of the file can be specified with
|
||||
directives ``header:re2c:on`` and ``header:re2c:off``.
|
||||
If conditions are used the header will have a condition enum automatically
|
||||
appended to it (unless there is an explicit ``conditions:re2c`` directive).
|
||||
|
||||
``-I PATH``
|
||||
Add ``PATH`` to the list of locations which are used when searching for
|
||||
include files. This option is useful in combination with
|
||||
``/*!include:re2c ... */`` directive. Re2c looks for ``FILE`` in the
|
||||
directory of including file and in the list of include paths specified by
|
||||
``-I`` option.
|
||||
|
||||
``-i --no-debug-info``
|
||||
Do not output ``#line`` information. This is useful when the generated code
|
||||
is tracked by some version control system or IDE.
|
||||
|
||||
``--input <default | custom>``
|
||||
Specify the API used by the generated code to interface with used-defined
|
||||
code. Option ``default`` is the C API based on pointer arithmetic (it is
|
||||
the default for the C backend). Option ``custom`` is the generic API (it is
|
||||
the default for the Go backend).
|
||||
include files. This option is useful in combination with ``include:re2c``
|
||||
directive. re2c looks for ``FILE`` in the directory of the parent file and
|
||||
in the include locations specified with ``-I`` option.
|
||||
|
||||
``--input-encoding <ascii | utf8>``
|
||||
Specify the way re2c parses regular expressions.
|
||||
@@ -104,15 +89,34 @@
|
||||
With ``utf8`` re2c handles input as UTF8-encoded and recognizes multibyte
|
||||
characters.
|
||||
|
||||
``--lang <c | go>``
|
||||
Specify the output language. Supported languages are C and Go (the default
|
||||
is C).
|
||||
``--lang <c | go | rust>``
|
||||
Specify the output language. Supported languages are C, Go and Rust.
|
||||
The default is C for re2c, Go for re2go and Rust for re2rust.
|
||||
|
||||
``--location-format <gnu | msvc>``
|
||||
Specify location format in messages.
|
||||
With ``gnu`` locations are printed as 'filename:line:column: ...'.
|
||||
With ``msvc`` locations are printed as 'filename(line,column) ...'.
|
||||
Default is ``gnu``.
|
||||
The default is ``gnu``.
|
||||
|
||||
``--loop-switch``
|
||||
Encode DFA in a form of a loop over a switch statement. Individual states
|
||||
are switch cases. The current state is stored in a variable ``yystate``.
|
||||
Transitions between states update ``yystate`` to the case label of the
|
||||
destination state and ``continue`` to the head of the loop. This option is
|
||||
always enabled for Rust, as it has no ``goto`` statement and cannot use the
|
||||
goto/label approach which is the default for C and Go backends.
|
||||
|
||||
``--nested-ifs -s``
|
||||
Use nested ``if`` statements instead of ``switch`` statements in conditional
|
||||
jumps. This usually results in more efficient code with non-optimizing
|
||||
compilers.
|
||||
|
||||
``--no-debug-info -i``
|
||||
Do not output line directives. This may be useful when the generated code is
|
||||
stored in a version control system (to avoid huge autogenerated diffs on
|
||||
small changes). This option is on by default for Rust, as it does not have
|
||||
line directives.
|
||||
|
||||
``--no-generation-date``
|
||||
Suppress date output in the generated file.
|
||||
@@ -120,56 +124,68 @@
|
||||
``--no-version``
|
||||
Suppress version output in the generated file.
|
||||
|
||||
``-o OUTPUT --output=OUTPUT``
|
||||
``--no-unsafe``
|
||||
Do not generate ``unsafe`` wrapper over ``YYPEEK`` (this option is specific
|
||||
to Rust). For performance reasons ``YYPEEK`` should avoid bounds-checking,
|
||||
as the lexer already performs end-of-input checks in a more efficient way.
|
||||
The user may choose to provide a safe ``YYPEEK`` definition, or a definition
|
||||
that is unsafe only in release builds, in which case the ``--no-unsafe``
|
||||
option helps to avoid warnings about redundant ``unsafe`` blocks.
|
||||
|
||||
``--output -o OUTPUT``
|
||||
Specify the ``OUTPUT`` file.
|
||||
|
||||
``-P --posix-captures``
|
||||
``--posix-captures -P``
|
||||
Enable submatch extraction with POSIX-style capturing groups.
|
||||
|
||||
``-r --reusable``
|
||||
Deprecated since re2c version 2.2 (reusable blocks are allowed by default
|
||||
now).
|
||||
``--reusable -r``
|
||||
Deprecated since version 2.2 (reusable blocks are allowed by default now).
|
||||
|
||||
``-S --skeleton``
|
||||
``--skeleton -S``
|
||||
Ignore user-defined interface code and generate a self-contained "skeleton"
|
||||
program. Additionally, generate input files with strings derived from the
|
||||
regular grammar and compressed match results that are used to verify
|
||||
"skeleton" behavior on all inputs. This option is useful for finding bugs
|
||||
in optimizations and code generation. This option doesn't work for the Go
|
||||
backend.
|
||||
in optimizations and code generation. This option is supported only for C.
|
||||
|
||||
``-s --nested-ifs``
|
||||
Use nested ``if`` statements instead of ``switch`` statements in conditional
|
||||
jumps. This usually results in more efficient code with non-optimizing
|
||||
compilers.
|
||||
``--storable-state -f``
|
||||
Generate a lexer which can store its inner state.
|
||||
This is useful in push-model lexers which are stopped by an outer program
|
||||
when there is not enough input, and then resumed when more input becomes
|
||||
available. In this mode users should additionally define ``YYGETSTATE``
|
||||
and ``YYSETSTATE`` primitives, and variables ``yych``, ``yyaccept`` and
|
||||
``state`` should be part of the stored lexer state.
|
||||
|
||||
``-T --tags``
|
||||
``--tags -T``
|
||||
Enable submatch extraction with tags.
|
||||
|
||||
``-t HEADER --type-header=HEADER``
|
||||
Generate a ``HEADER`` file that contains enum with condition names.
|
||||
Requires ``-c`` option.
|
||||
``--ucs2 --wide-chars -w``
|
||||
Generate a lexer that reads UCS2-encoded input. re2c assumes that the
|
||||
character range is 0 -- 0xFFFF and character size is 2 bytes.
|
||||
This option implies ``--nested-ifs``.
|
||||
|
||||
``-u --unicode``
|
||||
Generate a lexer that reads UTF32-encoded input. Re2c assumes that character
|
||||
range is 0 -- 0x10FFFF and character size is 4 bytes. This option implies
|
||||
``-s``.
|
||||
``--utf8 --utf-8 -8``
|
||||
Generate a lexer that reads input in UTF-8 encoding. re2c assumes that the
|
||||
character range is 0 -- 0x10FFFF and character size is 1 byte.
|
||||
|
||||
``-V --vernum``
|
||||
Show version information in ``MMmmpp`` format (major, minor, patch).
|
||||
``--utf16 --utf-16 -x``
|
||||
Generate a lexer that reads UTF16-encoded input. re2c assumes that the
|
||||
character range is 0 -- 0x10FFFF and character size is 2 bytes.
|
||||
This option implies ``--nested-ifs``.
|
||||
|
||||
``--utf32 --unicode -u``
|
||||
Generate a lexer that reads UTF32-encoded input. re2c assumes that the
|
||||
character range is 0 -- 0x10FFFF and character size is 4 bytes.
|
||||
This option implies ``--nested-ifs``.
|
||||
|
||||
``--verbose``
|
||||
Output a short message in case of success.
|
||||
|
||||
``-v --version``
|
||||
``--vernum -V``
|
||||
Show version information in ``MMmmpp`` format (major, minor, patch).
|
||||
|
||||
``--version -v``
|
||||
Show version information.
|
||||
|
||||
``-w --wide-chars``
|
||||
Generate a lexer that reads UCS2-encoded input. Re2c assumes that character
|
||||
range is 0 -- 0xFFFF and character size is 2 bytes. This option implies
|
||||
``-s``.
|
||||
|
||||
``-x --utf-16``
|
||||
Generate a lexer that reads UTF16-encoded input. Re2c assumes that character
|
||||
range is 0 -- 0x10FFFF and character size is 2 bytes. This option implies
|
||||
``-s``.
|
||||
``--single-pass -1``
|
||||
Deprecated. Does nothing (single pass is the default now).
|
||||
|
||||
@@ -19,7 +19,7 @@ Skeleton programs are very useful for a number of reasons:
|
||||
|
||||
The difficulty with generating input data is that for all but the most trivial
|
||||
cases the number of possible input strings is too large (even if the string
|
||||
length is limited). Re2c solves this difficulty by generating sufficiently
|
||||
length is limited). re2c solves this difficulty by generating sufficiently
|
||||
many strings to cover almost all DFA transitions. It uses the following
|
||||
algorithm. First, it constructs a skeleton of the DFA. For encodings with 1-byte
|
||||
code unit size (such as ASCII, UTF-8 and EBCDIC) skeleton is just an exact copy
|
||||
|
||||
+19
-26
@@ -1,4 +1,4 @@
|
||||
With ``-f`` ``--storable-state`` option re2c generates a lexer that can store
|
||||
With ``--storable-state`` option re2c generates a lexer that can store
|
||||
its current state, return to the caller, and later resume operations exactly
|
||||
where it left off. The default mode of operation in re2c is a "pull" model,
|
||||
in which the lexer "pulls" more input whenever it needs it. This may be
|
||||
@@ -12,10 +12,10 @@ returns to the caller. Later, when more input becomes available, the caller
|
||||
resumes the lexer exactly where it stopped. There are a few changes necessary
|
||||
compared to the "pull" model:
|
||||
|
||||
* Define ``YYSETSTATE()`` and ``YYGETSTATE(state)`` promitives.
|
||||
* Define ``YYSETSTATE()`` and ``YYGETSTATE(state)`` primitives.
|
||||
|
||||
* Define ``yych``, ``yyaccept`` and ``state`` variables as a part of persistent
|
||||
lexer state. The ``state`` variable should be initialized to ``-1``.
|
||||
* Define ``yych``, ``yyaccept`` (if used) and ``state`` variables as a part of
|
||||
persistent lexer state. The ``state`` variable should be initialized to ``-1``.
|
||||
|
||||
* ``YYFILL`` should return to the outer program instead of trying to supply more
|
||||
input. Return code should indicate that lexer needs more input.
|
||||
@@ -23,27 +23,20 @@ compared to the "pull" model:
|
||||
* The outer program should recognize situations when lexer needs more input and
|
||||
respond appropriately.
|
||||
|
||||
* Use ``/*!getstate:re2c*/`` directive if it is necessary to execute any code
|
||||
before entering the lexer.
|
||||
* Optionally use ``getstate:re2c`` to generate ``YYGETSTATE`` switch detached
|
||||
from the main lexer. This only works for languages that have ``goto`` (not in
|
||||
``--loop-switch`` mode).
|
||||
|
||||
* Use configurations ``state:abort`` and ``state:nextlabel`` to further tweak
|
||||
the generated code.
|
||||
* Use ``re2c:eof`` and the `sentinel with bounds checks`_ method to handle the
|
||||
end of input. Padding-based method may not work because it is unclear when to
|
||||
append padding: the current end of input may not be the ultimate end of input,
|
||||
and appending padding too early may cut off a partially read greedy lexeme.
|
||||
Furthermore, due to high-level program logic getting more input may depend on
|
||||
processing the lexeme at the end of buffer (which already is blocked due to
|
||||
the end-of-input condition).
|
||||
|
||||
Here is an example of a "push"-model lexer that reads input from ``stdin`` and
|
||||
expects a sequence of words separated by spaces and newlines. The lexer loops
|
||||
forever, waiting for more input. It can be terminated by sending a special EOF
|
||||
token --- a word "stop", in which case the lexer terminates successfully and
|
||||
prints the number of words it has seen. Abnormal termination happens in case of
|
||||
a syntax error, premature end of input (without the "stop" word) or in case the
|
||||
buffer is too small to hold a lexeme (for example, if one of the words exceeds
|
||||
buffer size). Premature end of input happens in case the lexer fails to read any
|
||||
input while being in the initial state --- this is the only case when EOF rule
|
||||
matches. Note that the lexer may call ``YYFILL`` twice before terminating (and
|
||||
thus require hitting ``Ctrl+D`` a few times). First time ``YYFILL`` is called
|
||||
when the lexer expects continuation of the current greedy lexeme (either a word
|
||||
or a whitespace sequence). If ``YYFILL`` fails, the lexer knows that it has
|
||||
reached the end of the current lexeme and executes the corresponding semantic
|
||||
action. The action jumps to the beginning of the loop, the lexer enters the
|
||||
initial state and calls ``YYFILL`` once more. If it fails, the lexer matches EOF
|
||||
rule. (Alternatively EOF rule can be used for termination instead of a special
|
||||
EOF lexeme.)
|
||||
Here is an example of a "push" model lexer that simulates reading packets from a
|
||||
socket. The lexer loops until it encounters the end of input and returns to the
|
||||
calling function. The calling function provides more input by "sending" the next
|
||||
packet and resumes lexing. This process stops when all the packets have been
|
||||
sent, or when there is an error.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Re2c has two options for submatch extraction.
|
||||
re2c has two options for submatch extraction.
|
||||
|
||||
The first option is ``-T --tags``. With this option one can use standalone tags
|
||||
of the form ``@stag`` and ``#mtag``, where ``stag`` and ``mtag`` are arbitrary
|
||||
@@ -18,7 +18,7 @@ beginning and the end of capturing groups; the whole regular expression is group
|
||||
number zero. The number of groups for the matching rule is stored in a variable
|
||||
``yynmatch``, and submatch results are stored in ``yypmatch`` array. Both
|
||||
``yynmatch`` and ``yypmatch`` should be defined by the user, and ``yypmatch``
|
||||
size must be at least ``[yynmatch * 2]``. Re2c provides a directive
|
||||
size must be at least ``[yynmatch * 2]``. re2c provides a directive
|
||||
``/*!maxnmatch:re2c*/`` that defines ``YYMAXNMATCH``: a constant equal to the
|
||||
maximal value of ``yynmatch`` among all rules. Note that re2c implements
|
||||
POSIX-compliant disambiguation: each subexpression matches as long as possible,
|
||||
@@ -49,9 +49,9 @@ tag variables).
|
||||
|
||||
S-tags support the following operations:
|
||||
|
||||
* save input position to an s-tag: ``t = YYCURSOR`` with default API or a
|
||||
* save input position to an s-tag: ``t = YYCURSOR`` with C pointer API or a
|
||||
user-defined operation ``YYSTAGP(t)`` with generic API
|
||||
* save default value to an s-tag: ``t = NULL`` with default API or a
|
||||
* save default value to an s-tag: ``t = NULL`` with C pointer API or a
|
||||
user-defined operation ``YYSTAGN(t)`` with generic API
|
||||
* copy one s-tag to another: ``t1 = t2``
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
Here is an example of using m-tags to parse a semicolon-separated sequence of
|
||||
words (C++). Tag variables are stored in a tree that is packed in a vector.
|
||||
Here is an example of using m-tags to parse a version with a variable number of
|
||||
components. Tag variables are stored in a trie.
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
Here is an example of using POSIX capturing groups to parse an IPv4 address.
|
||||
Here is an example of using POSIX capturing groups to parse semantic versions.
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
Here is a simple example of using s-tags to parse an IPv4 address
|
||||
(see below for a more complex example that uses ``YYFILL``).
|
||||
Here is a simple example of using s-tags to parse semantic versions consisting
|
||||
of three numeric components: major, minor, patch (the latter is optional).
|
||||
See below for a more complex example that uses ``YYFILL``.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Here is a more complex example of using s-tags with ``YYFILL`` to parse a file
|
||||
with IPv4 addresses. Tag variables are part of the lexer state, and they are
|
||||
adjusted in ``YYFILL`` like other input positions.
|
||||
with newline-separated semantic versions. Tag variables are part of the lexer
|
||||
state, and they are adjusted in ``YYFILL`` like other input positions.
|
||||
Note that it is necessary for s-tags because their values are invalidated after
|
||||
shifting buffer contents. It may not be necessary in a custom implementation
|
||||
where tag variables store offsets relative to the start of the input string
|
||||
rather than buffer, which may be the case with m-tags.
|
||||
rather than the buffer, which may be the case with m-tags.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
.. code-block::
|
||||
|
||||
re2c [ OPTIONS ] [ WARNINGS ] INPUT
|
||||
re2go [ OPTIONS ] [ WARNINGS ] INPUT
|
||||
re2rust [ OPTIONS ] [ WARNINGS ] INPUT
|
||||
|
||||
Input can be either a file or ``-`` for stdin.
|
||||
+18
-26
@@ -1,30 +1,28 @@
|
||||
|
||||
The generated code interfaces with the outer program with the help of
|
||||
*primitives* -- symbolic names that can be defined as variables, functions or
|
||||
macros in the target language (collectively referred to as the API).
|
||||
The primitives should be defined by the user. This approach gives the user
|
||||
freedom and flexibility in customizing the lexer, but it also requires some
|
||||
understanding of how the lexer works in order to implement the primitives
|
||||
correctly and efficiently. The manual provides examples for the most popular
|
||||
use cases. For the full list of primitives see the `interface primitives`_
|
||||
section.
|
||||
macros in the target language (collectively referred to as the **API**).
|
||||
The definition of primitives is left for the user: this gives them both
|
||||
freedom in customizing the lexer and responsibility to understand how it works.
|
||||
Not all primitives have to be defined --- only those used by a given program.
|
||||
The manual provides definitions for the most popular use cases. For a full list
|
||||
of primitives and their meaning see the `API primitives`_ section.
|
||||
|
||||
.. _generic_api:
|
||||
|
||||
There are two *API flavours* that define the set of primitives used by re2c:
|
||||
There are two API flavors that define the set of primitives used by re2c:
|
||||
|
||||
**Pointer API**
|
||||
This API is also called *default API*, since it was historically the first,
|
||||
and for a long time the only one. This is a more restrictive API based on C
|
||||
pointer arithmetics. It consists of pointer-like primitives ``YYCURSOR``,
|
||||
``YYMARKER``, ``YYCTXMARKER``, ``YYLIMIT`` (which are normally defined as
|
||||
pointers of type ``YYCTYPE*``) and ``YYFILL``. Pointer API is enabled by
|
||||
default for the C backend, and it cannot be used with backends that do not
|
||||
support pointer arithmetics.
|
||||
This API is based on C pointer arithmetic. It was historically the first,
|
||||
and for a long time the only one. It consists of pointer-like primitives
|
||||
``YYCURSOR``, ``YYMARKER``, ``YYCTXMARKER``, ``YYLIMIT`` (which are normally
|
||||
defined as pointers of type ``YYCTYPE*``) and ``YYFILL``. This API is
|
||||
enabled by default for C, and it cannot be used with other backends that do
|
||||
not support pointer arithmetic.
|
||||
|
||||
**Generic API**
|
||||
This is a more flexible API that does not assume pointer semantics. It
|
||||
consists of primitives
|
||||
This API is more flexible. It consists generic operations and does not
|
||||
assume any particular implementation. The primitives are
|
||||
``YYPEEK``,
|
||||
``YYSKIP``,
|
||||
``YYBACKUP``,
|
||||
@@ -41,13 +39,7 @@ There are two *API flavours* that define the set of primitives used by re2c:
|
||||
``YYSHIFTMTAG``,
|
||||
``YYLESSTHAN``
|
||||
and ``YYFILL``.
|
||||
For the C backend generic API is enabled with ``--input custom`` option or
|
||||
``re2c:flags:input = custom;`` configuration; for the Go backend it is
|
||||
enabled by default. Generic API was added in version 0.14. It is
|
||||
intentionally designed to give the user as much freedom as possible in
|
||||
redefining the input model and the semantics of different actions performed
|
||||
by the generated code.
|
||||
|
||||
There are two *API styles* determine the form in which the primitives should be
|
||||
defined:
|
||||
For the C backend generic API is enabled with ``--api custom`` option or
|
||||
``re2c:api = custom;`` configuration; for Go and Rust it is enabled by
|
||||
default. Generic API was added in version 0.14.
|
||||
|
||||
|
||||
@@ -1,39 +1,42 @@
|
||||
There are two API styles that determine the form in which the primitives should
|
||||
be defined:
|
||||
|
||||
**Free-form**
|
||||
This style is enabled with ``re2c:api:style = free-form;`` configuration.
|
||||
Interface primitives should be defined as free-form pieces of code with
|
||||
interpolated variables of the form ``@@{name}`` or optionally just ``@@``
|
||||
if there is only one variable. The ``@@`` marker can be customized with the
|
||||
``re2c:api:sigil`` configuration. In C/C++ free-form style generic API can
|
||||
be defined in terms of pointers ``cursor``, ``limit``, ``marker`` and
|
||||
``ctxmarker`` as follows:
|
||||
Free-form style is enabled with configuration
|
||||
``re2c:api:style = free-form;``.
|
||||
In this style interface primitives should be defined as free-form pieces of
|
||||
code with interpolated variables of the form ``@@{var}`` or optionally just
|
||||
``@@`` if there is a single variable.
|
||||
The set of variables is specific to each primitive.
|
||||
Generic API can be defined in terms of pointers ``cursor``, ``limit``,
|
||||
``marker`` and ``ctxmarker`` as follows:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/*!re2c
|
||||
re2c:define:YYPEEK = "*cursor";
|
||||
re2c:define:YYSKIP = "++cursor";
|
||||
re2c:define:YYBACKUP = "marker = cursor";
|
||||
re2c:define:YYRESTORE = "cursor = marker";
|
||||
re2c:define:YYBACKUPCTX = "ctxmarker = cursor";
|
||||
re2c:define:YYRESTORECTX = "cursor = ctxmarker";
|
||||
re2c:define:YYRESTORETAG = "cursor = ${tag}";
|
||||
re2c:define:YYLESSTHAN = "limit - cursor < @@{len}";
|
||||
re2c:define:YYSTAGP = "@@{tag} = cursor";
|
||||
re2c:define:YYSTAGN = "@@{tag} = NULL";
|
||||
re2c:define:YYSHIFT = "cursor += @@{shift}";
|
||||
re2c:define:YYSHIFTSTAG = "@@{tag} += @@{shift}";
|
||||
re2c:define:YYPEEK = "*cursor";
|
||||
re2c:define:YYSKIP = "++cursor;";
|
||||
re2c:define:YYBACKUP = "marker = cursor;";
|
||||
re2c:define:YYRESTORE = "cursor = marker;";
|
||||
re2c:define:YYBACKUPCTX = "ctxmarker = cursor;";
|
||||
re2c:define:YYRESTORECTX = "cursor = ctxmarker;";
|
||||
re2c:define:YYRESTORETAG = "cursor = ${tag};";
|
||||
re2c:define:YYLESSTHAN = "limit - cursor < @@{len}";
|
||||
re2c:define:YYSTAGP = "@@{tag} = cursor;";
|
||||
re2c:define:YYSTAGN = "@@{tag} = NULL;";
|
||||
re2c:define:YYSHIFT = "cursor += @@{shift};";
|
||||
re2c:define:YYSHIFTSTAG = "@@{tag} += @@{shift};";
|
||||
*/
|
||||
|
||||
|
|
||||
|
||||
**Function-like**
|
||||
This style is enabled with ``re2c:api:style = functions;`` configuration.
|
||||
Primitives should be defined as functions or macros with parentheses,
|
||||
accepting the necessary number of arguments. For historical reasons this
|
||||
API style is the default for C/C++ backend. Function style generic API can
|
||||
be defined in terms of pointers ``cursor``, ``limit``, ``marker`` and
|
||||
``ctxmarker`` as follows:
|
||||
Function-like style is enabled with configuration
|
||||
``re2c:api:style = functions;``. In this style primitives should be defined
|
||||
as functions or macros with parentheses, accepting the necessary arguments.
|
||||
For historical reasons this API style is the default for C/C++ backend.
|
||||
Generic API can be defined in terms of pointers ``cursor``, ``limit``,
|
||||
``marker`` and ``ctxmarker`` as follows:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
|
||||
@@ -1,41 +1,45 @@
|
||||
There are two API styles that determine the form in which the primitives should
|
||||
be defined:
|
||||
|
||||
**Free-form**
|
||||
This style is enabled with ``re2c:api:style = free-form;`` configuration,
|
||||
and it is the default for the Go backend. Interface primitives should be
|
||||
defined as free-form pieces of code with interpolated variables of the form
|
||||
``@@{name}`` or optionally just ``@@`` if there is only one variable. The
|
||||
``@@`` text can be customized with the ``re2c:api:sigil`` configuration.
|
||||
In Go free-form style generic API can be defined in terms of integer
|
||||
variables ``cursor``, ``limit``, ``marker``, ``ctxmarker`` and a string (or
|
||||
a byte slice) ``data`` as follows:
|
||||
Free-form style is enabled with configuration
|
||||
``re2c:api:style = free-form;``. It is the default for Go.
|
||||
In this style interface primitives should be defined as free-form pieces of
|
||||
code with interpolated variables of the form ``@@{var}`` or optionally just
|
||||
``@@`` if there is a single variable.
|
||||
The set of variables is specific to each primitive.
|
||||
Free-form style generic API can be defined in terms of integer variables
|
||||
``cursor``, ``limit``, ``marker``, ``ctxmarker`` and a string (or a byte
|
||||
slice) ``data`` as follows:
|
||||
|
||||
.. code-block:: go
|
||||
|
||||
/*!re2c
|
||||
re2c:define:YYPEEK = "data[cursor]";
|
||||
re2c:define:YYSKIP = "cursor++";
|
||||
re2c:define:YYBACKUP = "marker = cursor";
|
||||
re2c:define:YYRESTORE = "cursor = marker";
|
||||
re2c:define:YYBACKUPCTX = "ctxmarker = cursor";
|
||||
re2c:define:YYRESTORECTX = "cursor = ctxmarker";
|
||||
re2c:define:YYRESTORETAG = "cursor = ${tag}";
|
||||
re2c:define:YYLESSTHAN = "limit - cursor < @@{len}";
|
||||
re2c:define:YYSTAGP = "@@{tag} = cursor";
|
||||
re2c:define:YYSTAGN = "@@{tag} = -1";
|
||||
re2c:define:YYSHIFT = "cursor += @@{shift}";
|
||||
re2c:define:YYSHIFTSTAG = "@@{tag} += @@{shift}";
|
||||
re2c:define:YYPEEK = "data[cursor]";
|
||||
re2c:define:YYSKIP = "cursor++";
|
||||
re2c:define:YYBACKUP = "marker = cursor";
|
||||
re2c:define:YYRESTORE = "cursor = marker";
|
||||
re2c:define:YYBACKUPCTX = "ctxmarker = cursor";
|
||||
re2c:define:YYRESTORECTX = "cursor = ctxmarker";
|
||||
re2c:define:YYRESTORETAG = "cursor = ${tag}";
|
||||
re2c:define:YYLESSTHAN = "limit - cursor < @@{len}";
|
||||
re2c:define:YYSTAGP = "@@{tag} = cursor";
|
||||
re2c:define:YYSTAGN = "@@{tag} = -1";
|
||||
re2c:define:YYSHIFT = "cursor += @@{shift}";
|
||||
re2c:define:YYSHIFTSTAG = "@@{tag} += @@{shift}";
|
||||
*/
|
||||
|
||||
|
|
||||
|
||||
**Function-like**
|
||||
This style is enabled with ``re2c:api:style = functions;`` configuration.
|
||||
Primitives should be defined as functions with parentheses, accepting the
|
||||
necessary number of arguments. This style can be used with the Go backend,
|
||||
but it is more restrictive than the free-form style and some primitives are
|
||||
problematic to define. Most of the primitives can be defined as closures in
|
||||
terms of integer variables ``cursor``, ``limit``, ``marker``, ``ctxmarker``
|
||||
and a string (or a byte slice) ``data``:
|
||||
Function-like style is enabled with configuration
|
||||
``re2c:api:style = functions;``. In this style primitives should be defined
|
||||
as functions or macros with parentheses, accepting the necessary arguments.
|
||||
This style is more restrictive than the free-form style, but it can be used
|
||||
with Go closures.
|
||||
For example, if the input is a string (or a byte slice) ``data``, and
|
||||
integer variables ``cursor``, ``limit``, ``marker`` and ``ctxmarker``
|
||||
represent input positions, then the primitives can be defined as follows:
|
||||
|
||||
.. code-block:: go
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
There are two API styles that determine the form in which the primitives should
|
||||
be defined:
|
||||
|
||||
**Free-form**
|
||||
Free-form style is enabled with configuration
|
||||
``re2c:api:style = free-form;``. It is the default for Rust.
|
||||
In this style interface primitives should be defined as free-form pieces of
|
||||
code with interpolated variables of the form ``@@{var}`` or optionally just
|
||||
``@@`` if there is a single variable.
|
||||
The set of variables is specific to each primitive.
|
||||
For example, if the input is a byte slice ``buffer: &[u8]``,
|
||||
variables ``cursor``, ``limit``, ``marker`` and ``ctxmarker``
|
||||
of type ``usize`` represent input positions,
|
||||
and a constant ``NONE`` represents invalid position,
|
||||
then the API can be defined as follows:
|
||||
|
||||
.. code-block:: rust
|
||||
|
||||
/*!re2c
|
||||
re2c:define:YYPEEK = "*buffer.get_unchecked(cursor)";
|
||||
re2c:define:YYSKIP = "cursor += 1;";
|
||||
re2c:define:YYBACKUP = "marker = cursor;";
|
||||
re2c:define:YYRESTORE = "cursor = marker;";
|
||||
re2c:define:YYBACKUPCTX = "ctxmarker = cursor;";
|
||||
re2c:define:YYRESTORECTX = "cursor = ctxmarker;";
|
||||
re2c:define:YYRESTORETAG = "cursor = @@{tag};";
|
||||
re2c:define:YYLESSTHAN = "limit - cursor < @@{len}";
|
||||
re2c:define:YYSTAGP = "@@{tag} = cursor;";
|
||||
re2c:define:YYSTAGN = "@@{tag} = NONE;";
|
||||
re2c:define:YYSHIFT = "cursor = (cursor as isize + @@{shift}) as usize;";
|
||||
re2c:define:YYSHIFTSTAG = "@@{tag} = (@@{tag} as isize + @@{shift}) as usize;";
|
||||
*/
|
||||
|
||||
|
|
||||
|
||||
**Function-like**
|
||||
Function-like style is enabled with configuration
|
||||
``re2c:api:style = functions;``. In this style primitives should be defined
|
||||
as functions or macros with parentheses, accepting the necessary arguments.
|
||||
This is well-suited for C macros or Go closures, but it cannot be used with
|
||||
hygienic macros or functions in Rust as the primitives need to access lexer
|
||||
context that is not passed as an argument. It is possible to use closures,
|
||||
but the borrow-checker makes it hard because different primitives read and
|
||||
modify the same parts of lexer context in a series of interleaved
|
||||
invocations. As a workaround, one can use Rust ``Cell`` type.
|
||||
For example, if the input is a byte slice ``buffer: &[u8]`` and
|
||||
``cursor: Cell::<usize>`` is the current input position, then ``YYPEEK`` and
|
||||
``YYSKIP`` can be defined as follows:
|
||||
|
||||
.. code-block:: rust
|
||||
|
||||
let YYPEEK = || unsafe { *buffer.get_unchecked(cursor.get()) };
|
||||
let YYSKIP = || { cursor.set(cur.get() + 1); };
|
||||
@@ -0,0 +1,6 @@
|
||||
re2c works as a preprocessor. It reads the input file (which is usually a
|
||||
program in the target language, but can be anything) and looks for blocks of
|
||||
code enclosed in special-form comments. The text outside of these blocks is
|
||||
copied verbatim into the output file. The contents of the blocks are processed
|
||||
by re2c. It translates them to code in the target language and outputs the
|
||||
generated code in place of the block.
|
||||
@@ -1,37 +1,31 @@
|
||||
Re2c works as a preprocessor. It reads the input file (which is usually a
|
||||
program in the target language, but can be anything) and looks for blocks of
|
||||
code enclosed in special-form comments. The text outside of these blocks is
|
||||
copied verbatim into the output file. The contents of the blocks are processed
|
||||
by re2c. It translates them to code in the target language and outputs the
|
||||
generated code in place of the block. There are different kinds of blocks;
|
||||
see the `blocks and directives`_ section for a full list of them. The main block
|
||||
kinds are the following:
|
||||
A re2c program consists of a sequence of *blocks* intermixed with code in the
|
||||
target language. There are three main kinds of blocks:
|
||||
|
||||
``/*!re2c[:<name>] ... */``
|
||||
A *global block* that contains a mixture of named definitions,
|
||||
configurations, directives and rules (regular expressions with associated
|
||||
semantic actions). Re2c compiles regular expressions to a deterministic
|
||||
finite automaton, encodes it in the form of conditional jumps and replaces
|
||||
the block with the generated code. Names and configurations defined
|
||||
in the block are added to the global scope and become visible to subsequent
|
||||
blocks (at the start of the program global scope is initialized with the
|
||||
`command-line options`_).
|
||||
A *global block* contains definitions, configurations, directives and rules.
|
||||
re2c compiles regular expressions associated with each rule into a
|
||||
deterministic finite automaton, encodes it in the form of conditional jumps
|
||||
in the target language and replaces the block with the generated code. Names
|
||||
and configurations defined in a global block are added to the global scope
|
||||
and become visible to subsequent blocks. At the start of the program the
|
||||
global scope is initialized with command-line `options`_.
|
||||
The ``:<name>`` part is optional: if specified, the name can be used to
|
||||
refer to the block in another part of the program.
|
||||
|
||||
``/*!local:re2c[:<name>] ... */``
|
||||
A *local block* is like a global block, but the names and configurations
|
||||
defined in it have local scope (they do not affect other blocks).
|
||||
A *local block* is like a global block, but the names and configurations in
|
||||
it have local scope (they do not affect other blocks).
|
||||
|
||||
``/*!rules:re2c[:<name>] ... */``
|
||||
A *rules block* is like a local block, but it does not generate any code and
|
||||
is meant to be reused in other blocks. This is a way of sharing code
|
||||
(more details in the `reusable blocks`_ section).
|
||||
|
||||
A block may contain the following kinds of statements:
|
||||
There are also many auxiliary blocks; see section `blocks and directives`_ for a
|
||||
full list of them. A block may contain the following kinds of statements:
|
||||
|
||||
``<name> = <regular expression>;``
|
||||
A *named definition* binds a name to a regular expression. Names may contain
|
||||
A *definition* binds a name to a regular expression. Names may contain
|
||||
alphanumeric characters and underscore. The `regular expressions`_ section
|
||||
gives an overview of re2c syntax for regular expressions. Once defined, the
|
||||
name can be used in other regular expressions and in rules. Recursion in
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
|
||||
``-Wcondition-order``
|
||||
Warn if the generated program makes implicit
|
||||
assumptions about condition numbering. One should use either the ``-t, --type-header`` option or
|
||||
the ``/*!types:re2c*/`` directive to generate a mapping of condition names to numbers and then use
|
||||
the autogenerated condition names.
|
||||
Warn if the generated program makes implicit assumptions about condition
|
||||
numbering. One should use either the ``---header`` option or the
|
||||
``conditions:re2c`` directive to generate a mapping of condition names to
|
||||
numbers and then use the autogenerated condition names.
|
||||
|
||||
``-Wempty-character-class``
|
||||
Warn if a regular expression contains an empty
|
||||
character class. Trying to match an empty character class makes no sense: it should always fail.
|
||||
However, for backwards compatibility reasons ``re2c`` allows empty character classes and
|
||||
treats them as empty strings. Use the ``--empty-class`` option to change the default
|
||||
behavior.
|
||||
Warn if a regular expression contains an empty character class. Trying to
|
||||
match an empty character class makes no sense: it should always fail.
|
||||
However, for backwards compatibility reasons re2c permits empty character
|
||||
classes and treats them as empty strings. Use the ``--empty-class`` option
|
||||
to change the default behavior.
|
||||
|
||||
``-Wmatch-empty-string``
|
||||
Warn if a rule is nullable (matches an empty string).
|
||||
If the lexer runs in a loop and the empty match is unintentional,
|
||||
the lexer may unexpectedly hang in an infinite loop.
|
||||
If the lexer runs in a loop and the empty match is unintentional, the lexer
|
||||
may unexpectedly hang in an infinite loop.
|
||||
|
||||
``-Wswapped-range``
|
||||
Warn if the lower bound of a range is greater than its upper
|
||||
bound. The default behavior is to silently swap the range bounds.
|
||||
Warn if the lower bound of a range is greater than its upper bound. The
|
||||
default behavior is to silently swap the range bounds.
|
||||
|
||||
``-Wundefined-control-flow``
|
||||
Warn if some input strings cause undefined
|
||||
control flow in the lexer (the faulty patterns are reported). This is the
|
||||
most dangerous and most common mistake. It can be easily fixed by adding
|
||||
the default rule ``*`` which has the lowest priority, matches any code unit, and consumes
|
||||
exactly one code unit.
|
||||
Warn if some input strings cause undefined control flow in the lexer (the
|
||||
faulty patterns are reported). This is a dangerous and common mistake. It
|
||||
can be easily fixed by adding the default rule ``*`` which has the lowest
|
||||
priority, matches any code unit, and always consumes a single code unit.
|
||||
|
||||
``-Wunreachable-rules``
|
||||
Warn about rules that are shadowed by other rules and will never match.
|
||||
|
||||
``-Wuseless-escape``
|
||||
Warn if a symbol is escaped when it shouldn't be.
|
||||
By default, re2c silently ignores such escapes, but this may as well indicate a
|
||||
typo or an error in the escape sequence.
|
||||
By default, re2c silently ignores such escapes, but this may as well
|
||||
indicate a typo or an error in the escape sequence.
|
||||
|
||||
``-Wnondeterministic-tags``
|
||||
Warn if a tag has ``n``-th degree of nondeterminism, where ``n`` is greater than 1.
|
||||
Warn if a tag has ``n``-th degree of nondeterminism, where ``n`` is greater
|
||||
than 1.
|
||||
|
||||
``-Wsentinel-in-midrule``
|
||||
Warn if the sentinel symbol occurs in the middle of a rule --- this may
|
||||
|
||||
+20
-20
@@ -1,33 +1,33 @@
|
||||
/* Generated by re2c */
|
||||
// re2c $INPUT -o $OUTPUT --case-ranges -i
|
||||
|
||||
int lex(const char *YYCURSOR) { // C/C++ code
|
||||
// re2c $INPUT -o $OUTPUT -i --case-ranges
|
||||
#include <assert.h>
|
||||
|
||||
bool lex(const char *s) {
|
||||
const char *YYCURSOR = s;
|
||||
|
||||
{
|
||||
char yych;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 'A' ... 'Z':
|
||||
case 'a' ... 'z': goto yy4;
|
||||
default: goto yy2;
|
||||
case '1' ... '9': goto yy2;
|
||||
default: goto yy1;
|
||||
}
|
||||
yy2:
|
||||
yy1:
|
||||
++YYCURSOR;
|
||||
{ return 1; }
|
||||
yy4:
|
||||
{ return false; }
|
||||
yy2:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0' ... '9':
|
||||
case 'A' ... 'Z':
|
||||
case 'a' ... 'z': goto yy4;
|
||||
default: goto yy6;
|
||||
case '0' ... '9': goto yy2;
|
||||
default: goto yy3;
|
||||
}
|
||||
yy6:
|
||||
{ return 0; }
|
||||
yy3:
|
||||
{ return true; }
|
||||
}
|
||||
|
||||
} //
|
||||
//
|
||||
int main() { // C/C++ code
|
||||
return lex("qwerty42"); //
|
||||
} //
|
||||
}
|
||||
|
||||
int main() {
|
||||
assert(lex("1234"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
+19
-17
@@ -1,18 +1,20 @@
|
||||
// re2c $INPUT -o $OUTPUT --case-ranges -i
|
||||
// re2c $INPUT -o $OUTPUT -i --case-ranges
|
||||
#include <assert.h>
|
||||
|
||||
int lex(const char *YYCURSOR) { // C/C++ code
|
||||
/*!re2c
|
||||
re2c:define:YYCTYPE = char; // configurations
|
||||
re2c:yyfill:enable = 0; //
|
||||
//
|
||||
alpha = [a-zA-Z]; // named definitions
|
||||
ident = alpha (alpha | [0-9])*; //
|
||||
//
|
||||
ident { return 0; } // rules
|
||||
* { return 1; } //
|
||||
*/
|
||||
} //
|
||||
//
|
||||
int main() { // C/C++ code
|
||||
return lex("qwerty42"); //
|
||||
} //
|
||||
bool lex(const char *s) {
|
||||
const char *YYCURSOR = s;
|
||||
/*!re2c
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:define:YYCTYPE = char;
|
||||
|
||||
number = [1-9][0-9]*;
|
||||
|
||||
number { return true; }
|
||||
* { return false; }
|
||||
*/
|
||||
}
|
||||
|
||||
int main() {
|
||||
assert(lex("1234"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,8 @@ for f in $(find -name '*.re'); do
|
||||
head -n $l "$ctest" > "$ctest".mod && mv "$ctest".mod "$ctest"
|
||||
fi
|
||||
|
||||
g++ "$ctest" -Wall -oexample && ./example 2>/dev/null || { echo "*** error ***"; exit 1; }
|
||||
g++ -fsanitize=leak -fsanitize=address -g -Wall -oexample "$ctest" \
|
||||
&& ./example 2>/dev/null || { echo "*** error ***"; exit 1; }
|
||||
|
||||
rm -f "$ctest" example
|
||||
cd $root_dir
|
||||
|
||||
@@ -4,101 +4,96 @@
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
static const uint64_t ERROR = ~0lu;
|
||||
enum YYCONDTYPE {
|
||||
};
|
||||
static const uint64_t ERROR = UINT64_MAX;
|
||||
|
||||
|
||||
template<int BASE> static void adddgt(uint64_t &u, unsigned int d)
|
||||
{
|
||||
template<int BASE> static void add(uint64_t &u, char d) {
|
||||
u = u * BASE + d;
|
||||
if (u > UINT32_MAX) u = ERROR;
|
||||
}
|
||||
|
||||
static uint64_t parse_u32(const char *s)
|
||||
{
|
||||
const char *YYMARKER;
|
||||
static uint64_t parse_u32(const char *s) {
|
||||
const char *YYCURSOR = s, *YYMARKER;
|
||||
uint64_t u = 0;
|
||||
|
||||
|
||||
{
|
||||
char yych;
|
||||
yych = *s;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0': goto yy4;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy6;
|
||||
default: goto yy2;
|
||||
case '0': goto yy2;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy4;
|
||||
default: goto yy1;
|
||||
}
|
||||
yy2:
|
||||
++s;
|
||||
yy1:
|
||||
++YYCURSOR;
|
||||
{ return ERROR; }
|
||||
yy4:
|
||||
yych = *(YYMARKER = ++s);
|
||||
yy2:
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
switch (yych) {
|
||||
case 'B':
|
||||
case 'b': goto yy8;
|
||||
case 'X':
|
||||
case 'x': goto yy10;
|
||||
default: goto yy5;
|
||||
case 'B':
|
||||
case 'b': goto yy5;
|
||||
case 'X':
|
||||
case 'x': goto yy7;
|
||||
default: goto yy3;
|
||||
}
|
||||
yy5:
|
||||
yy3:
|
||||
{ goto oct; }
|
||||
yy6:
|
||||
++s;
|
||||
s -= 1;
|
||||
yy4:
|
||||
++YYCURSOR;
|
||||
YYCURSOR -= 1;
|
||||
{ goto dec; }
|
||||
yy5:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1': goto yy8;
|
||||
default: goto yy6;
|
||||
}
|
||||
yy6:
|
||||
YYCURSOR = YYMARKER;
|
||||
goto yy3;
|
||||
yy7:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f': goto yy9;
|
||||
default: goto yy6;
|
||||
}
|
||||
yy8:
|
||||
yych = *++s;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1': goto yy11;
|
||||
default: goto yy9;
|
||||
}
|
||||
yy9:
|
||||
s = YYMARKER;
|
||||
goto yy5;
|
||||
yy10:
|
||||
yych = *++s;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f': goto yy13;
|
||||
default: goto yy9;
|
||||
}
|
||||
yy11:
|
||||
++s;
|
||||
s -= 1;
|
||||
++YYCURSOR;
|
||||
YYCURSOR -= 1;
|
||||
{ goto bin; }
|
||||
yy13:
|
||||
++s;
|
||||
s -= 1;
|
||||
yy9:
|
||||
++YYCURSOR;
|
||||
YYCURSOR -= 1;
|
||||
{ goto hex; }
|
||||
}
|
||||
|
||||
@@ -106,139 +101,138 @@ bin:
|
||||
|
||||
{
|
||||
char yych;
|
||||
yych = *s;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy17;
|
||||
case '0':
|
||||
case '1': goto yy21;
|
||||
default: goto yy19;
|
||||
case 0x00: goto yy11;
|
||||
case '0':
|
||||
case '1': goto yy13;
|
||||
default: goto yy12;
|
||||
}
|
||||
yy17:
|
||||
++s;
|
||||
yy11:
|
||||
++YYCURSOR;
|
||||
{ return u; }
|
||||
yy19:
|
||||
++s;
|
||||
yy12:
|
||||
++YYCURSOR;
|
||||
{ return ERROR; }
|
||||
yy21:
|
||||
++s;
|
||||
{ adddgt<2>(u, s[-1] - '0'); goto bin; }
|
||||
yy13:
|
||||
++YYCURSOR;
|
||||
{ add<2>(u, YYCURSOR[-1] - '0'); goto bin; }
|
||||
}
|
||||
|
||||
oct:
|
||||
|
||||
{
|
||||
char yych;
|
||||
yych = *s;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy25;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7': goto yy29;
|
||||
default: goto yy27;
|
||||
case 0x00: goto yy15;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7': goto yy17;
|
||||
default: goto yy16;
|
||||
}
|
||||
yy25:
|
||||
++s;
|
||||
yy15:
|
||||
++YYCURSOR;
|
||||
{ return u; }
|
||||
yy27:
|
||||
++s;
|
||||
yy16:
|
||||
++YYCURSOR;
|
||||
{ return ERROR; }
|
||||
yy29:
|
||||
++s;
|
||||
{ adddgt<8>(u, s[-1] - '0'); goto oct; }
|
||||
yy17:
|
||||
++YYCURSOR;
|
||||
{ add<8>(u, YYCURSOR[-1] - '0'); goto oct; }
|
||||
}
|
||||
|
||||
dec:
|
||||
|
||||
{
|
||||
char yych;
|
||||
yych = *s;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy33;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy37;
|
||||
default: goto yy35;
|
||||
case 0x00: goto yy19;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy21;
|
||||
default: goto yy20;
|
||||
}
|
||||
yy33:
|
||||
++s;
|
||||
yy19:
|
||||
++YYCURSOR;
|
||||
{ return u; }
|
||||
yy35:
|
||||
++s;
|
||||
yy20:
|
||||
++YYCURSOR;
|
||||
{ return ERROR; }
|
||||
yy37:
|
||||
++s;
|
||||
{ adddgt<10>(u, s[-1] - '0'); goto dec; }
|
||||
yy21:
|
||||
++YYCURSOR;
|
||||
{ add<10>(u, YYCURSOR[-1] - '0'); goto dec; }
|
||||
}
|
||||
|
||||
hex:
|
||||
|
||||
{
|
||||
char yych;
|
||||
yych = *s;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy41;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy45;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F': goto yy47;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f': goto yy49;
|
||||
default: goto yy43;
|
||||
case 0x00: goto yy23;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy25;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F': goto yy26;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f': goto yy27;
|
||||
default: goto yy24;
|
||||
}
|
||||
yy41:
|
||||
++s;
|
||||
yy23:
|
||||
++YYCURSOR;
|
||||
{ return u; }
|
||||
yy43:
|
||||
++s;
|
||||
yy24:
|
||||
++YYCURSOR;
|
||||
{ return ERROR; }
|
||||
yy45:
|
||||
++s;
|
||||
{ adddgt<16>(u, s[-1] - '0'); goto hex; }
|
||||
yy47:
|
||||
++s;
|
||||
{ adddgt<16>(u, s[-1] - 'A' + 10); goto hex; }
|
||||
yy49:
|
||||
++s;
|
||||
{ adddgt<16>(u, s[-1] - 'a' + 10); goto hex; }
|
||||
yy25:
|
||||
++YYCURSOR;
|
||||
{ add<16>(u, YYCURSOR[-1] - '0'); goto hex; }
|
||||
yy26:
|
||||
++YYCURSOR;
|
||||
{ add<16>(u, YYCURSOR[-1] - 'A' + 10); goto hex; }
|
||||
yy27:
|
||||
++YYCURSOR;
|
||||
{ add<16>(u, YYCURSOR[-1] - 'a' + 10); goto hex; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
assert(parse_u32("") == ERROR);
|
||||
assert(parse_u32("1234567890") == 1234567890);
|
||||
assert(parse_u32("0b1101") == 13);
|
||||
assert(parse_u32("0x7Fe") == 2046);
|
||||
assert(parse_u32("0644") == 420);
|
||||
assert(parse_u32("9999999999") == ERROR);
|
||||
assert(parse_u32("") == ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,68 +3,63 @@
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
static const uint64_t ERROR = ~0lu;
|
||||
/*!types:re2c*/
|
||||
static const uint64_t ERROR = UINT64_MAX;
|
||||
|
||||
template<int BASE> static void adddgt(uint64_t &u, unsigned int d)
|
||||
{
|
||||
template<int BASE> static void add(uint64_t &u, char d) {
|
||||
u = u * BASE + d;
|
||||
if (u > UINT32_MAX) u = ERROR;
|
||||
}
|
||||
|
||||
static uint64_t parse_u32(const char *s)
|
||||
{
|
||||
const char *YYMARKER;
|
||||
static uint64_t parse_u32(const char *s) {
|
||||
const char *YYCURSOR = s, *YYMARKER;
|
||||
uint64_t u = 0;
|
||||
|
||||
/*!re2c
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYCURSOR = s;
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:define:YYCTYPE = char;
|
||||
|
||||
end = "\x00";
|
||||
end = "\x00";
|
||||
|
||||
'0b' / [01] { goto bin; }
|
||||
"0" { goto oct; }
|
||||
"" / [1-9] { goto dec; }
|
||||
'0x' / [0-9a-fA-F] { goto hex; }
|
||||
* { return ERROR; }
|
||||
'0b' / [01] { goto bin; }
|
||||
"0" { goto oct; }
|
||||
"" / [1-9] { goto dec; }
|
||||
'0x' / [0-9a-fA-F] { goto hex; }
|
||||
* { return ERROR; }
|
||||
*/
|
||||
bin:
|
||||
/*!re2c
|
||||
end { return u; }
|
||||
[01] { adddgt<2>(u, s[-1] - '0'); goto bin; }
|
||||
* { return ERROR; }
|
||||
end { return u; }
|
||||
[01] { add<2>(u, YYCURSOR[-1] - '0'); goto bin; }
|
||||
* { return ERROR; }
|
||||
*/
|
||||
oct:
|
||||
/*!re2c
|
||||
end { return u; }
|
||||
[0-7] { adddgt<8>(u, s[-1] - '0'); goto oct; }
|
||||
* { return ERROR; }
|
||||
end { return u; }
|
||||
[0-7] { add<8>(u, YYCURSOR[-1] - '0'); goto oct; }
|
||||
* { return ERROR; }
|
||||
*/
|
||||
dec:
|
||||
/*!re2c
|
||||
end { return u; }
|
||||
[0-9] { adddgt<10>(u, s[-1] - '0'); goto dec; }
|
||||
* { return ERROR; }
|
||||
end { return u; }
|
||||
[0-9] { add<10>(u, YYCURSOR[-1] - '0'); goto dec; }
|
||||
* { return ERROR; }
|
||||
*/
|
||||
hex:
|
||||
/*!re2c
|
||||
end { return u; }
|
||||
[0-9] { adddgt<16>(u, s[-1] - '0'); goto hex; }
|
||||
[a-f] { adddgt<16>(u, s[-1] - 'a' + 10); goto hex; }
|
||||
[A-F] { adddgt<16>(u, s[-1] - 'A' + 10); goto hex; }
|
||||
* { return ERROR; }
|
||||
end { return u; }
|
||||
[0-9] { add<16>(u, YYCURSOR[-1] - '0'); goto hex; }
|
||||
[a-f] { add<16>(u, YYCURSOR[-1] - 'a' + 10); goto hex; }
|
||||
[A-F] { add<16>(u, YYCURSOR[-1] - 'A' + 10); goto hex; }
|
||||
* { return ERROR; }
|
||||
*/
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
assert(parse_u32("") == ERROR);
|
||||
assert(parse_u32("1234567890") == 1234567890);
|
||||
assert(parse_u32("0b1101") == 13);
|
||||
assert(parse_u32("0x7Fe") == 2046);
|
||||
assert(parse_u32("0644") == 420);
|
||||
assert(parse_u32("9999999999") == ERROR);
|
||||
assert(parse_u32("") == ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
static const uint64_t ERROR = ~0lu;
|
||||
static const uint64_t ERROR = UINT64_MAX;
|
||||
enum YYCONDTYPE {
|
||||
yycinit,
|
||||
yycbin,
|
||||
@@ -14,15 +14,13 @@ enum YYCONDTYPE {
|
||||
};
|
||||
|
||||
|
||||
template<int BASE> static void adddgt(uint64_t &u, unsigned int d)
|
||||
{
|
||||
template<int BASE> static void add(uint64_t &u, char d) {
|
||||
u = u * BASE + d;
|
||||
if (u > UINT32_MAX) u = ERROR;
|
||||
}
|
||||
|
||||
static uint64_t parse_u32(const char *s)
|
||||
{
|
||||
const char *YYMARKER;
|
||||
static uint64_t parse_u32(const char *s) {
|
||||
const char *YYCURSOR = s, *YYMARKER;
|
||||
int c = yycinit;
|
||||
uint64_t u = 0;
|
||||
|
||||
@@ -30,223 +28,217 @@ static uint64_t parse_u32(const char *s)
|
||||
{
|
||||
char yych;
|
||||
switch (c) {
|
||||
case yycinit:
|
||||
goto yyc_init;
|
||||
case yycbin:
|
||||
goto yyc_bin;
|
||||
case yycdec:
|
||||
goto yyc_dec;
|
||||
case yychex:
|
||||
goto yyc_hex;
|
||||
case yycoct:
|
||||
goto yyc_oct;
|
||||
case yycinit: goto yyc_init;
|
||||
case yycbin: goto yyc_bin;
|
||||
case yycdec: goto yyc_dec;
|
||||
case yychex: goto yyc_hex;
|
||||
case yycoct: goto yyc_oct;
|
||||
}
|
||||
/* *********************************** */
|
||||
yyc_init:
|
||||
yych = *s;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0': goto yy4;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy6;
|
||||
default: goto yy2;
|
||||
case '0': goto yy2;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy4;
|
||||
default: goto yy1;
|
||||
}
|
||||
yy2:
|
||||
++s;
|
||||
yy1:
|
||||
++YYCURSOR;
|
||||
{ return ERROR; }
|
||||
yy4:
|
||||
yych = *(YYMARKER = ++s);
|
||||
yy2:
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
switch (yych) {
|
||||
case 'B':
|
||||
case 'b': goto yy8;
|
||||
case 'X':
|
||||
case 'x': goto yy10;
|
||||
default: goto yy5;
|
||||
case 'B':
|
||||
case 'b': goto yy5;
|
||||
case 'X':
|
||||
case 'x': goto yy7;
|
||||
default: goto yy3;
|
||||
}
|
||||
yy5:
|
||||
yy3:
|
||||
c = yycoct;
|
||||
goto yyc_oct;
|
||||
yy6:
|
||||
++s;
|
||||
s -= 1;
|
||||
yy4:
|
||||
++YYCURSOR;
|
||||
YYCURSOR -= 1;
|
||||
c = yycdec;
|
||||
goto yyc_dec;
|
||||
yy5:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1': goto yy8;
|
||||
default: goto yy6;
|
||||
}
|
||||
yy6:
|
||||
YYCURSOR = YYMARKER;
|
||||
goto yy3;
|
||||
yy7:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f': goto yy9;
|
||||
default: goto yy6;
|
||||
}
|
||||
yy8:
|
||||
yych = *++s;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1': goto yy11;
|
||||
default: goto yy9;
|
||||
}
|
||||
yy9:
|
||||
s = YYMARKER;
|
||||
goto yy5;
|
||||
yy10:
|
||||
yych = *++s;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f': goto yy13;
|
||||
default: goto yy9;
|
||||
}
|
||||
yy11:
|
||||
++s;
|
||||
s -= 1;
|
||||
++YYCURSOR;
|
||||
YYCURSOR -= 1;
|
||||
c = yycbin;
|
||||
goto yyc_bin;
|
||||
yy13:
|
||||
++s;
|
||||
s -= 1;
|
||||
yy9:
|
||||
++YYCURSOR;
|
||||
YYCURSOR -= 1;
|
||||
c = yychex;
|
||||
goto yyc_hex;
|
||||
/* *********************************** */
|
||||
yyc_bin:
|
||||
yych = *s;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy17;
|
||||
case '0':
|
||||
case '1': goto yy21;
|
||||
default: goto yy19;
|
||||
case 0x00: goto yy11;
|
||||
case '0':
|
||||
case '1': goto yy13;
|
||||
default: goto yy12;
|
||||
}
|
||||
yy17:
|
||||
++s;
|
||||
yy11:
|
||||
++YYCURSOR;
|
||||
{ return u; }
|
||||
yy19:
|
||||
++s;
|
||||
yy12:
|
||||
++YYCURSOR;
|
||||
{ return ERROR; }
|
||||
yy21:
|
||||
++s;
|
||||
{ adddgt<2> (u, s[-1] - '0'); goto yyc_bin; }
|
||||
yy13:
|
||||
++YYCURSOR;
|
||||
{ add<2>(u, YYCURSOR[-1] - '0'); goto yyc_bin; }
|
||||
/* *********************************** */
|
||||
yyc_dec:
|
||||
yych = *s;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy25;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy29;
|
||||
default: goto yy27;
|
||||
case 0x00: goto yy15;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy17;
|
||||
default: goto yy16;
|
||||
}
|
||||
yy25:
|
||||
++s;
|
||||
yy15:
|
||||
++YYCURSOR;
|
||||
{ return u; }
|
||||
yy27:
|
||||
++s;
|
||||
yy16:
|
||||
++YYCURSOR;
|
||||
{ return ERROR; }
|
||||
yy29:
|
||||
++s;
|
||||
{ adddgt<10>(u, s[-1] - '0'); goto yyc_dec; }
|
||||
yy17:
|
||||
++YYCURSOR;
|
||||
{ add<10>(u, YYCURSOR[-1] - '0'); goto yyc_dec; }
|
||||
/* *********************************** */
|
||||
yyc_hex:
|
||||
yych = *s;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy33;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy37;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F': goto yy39;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f': goto yy41;
|
||||
default: goto yy35;
|
||||
case 0x00: goto yy19;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy21;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F': goto yy22;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f': goto yy23;
|
||||
default: goto yy20;
|
||||
}
|
||||
yy33:
|
||||
++s;
|
||||
yy19:
|
||||
++YYCURSOR;
|
||||
{ return u; }
|
||||
yy35:
|
||||
++s;
|
||||
yy20:
|
||||
++YYCURSOR;
|
||||
{ return ERROR; }
|
||||
yy37:
|
||||
++s;
|
||||
{ adddgt<16>(u, s[-1] - '0'); goto yyc_hex; }
|
||||
yy39:
|
||||
++s;
|
||||
{ adddgt<16>(u, s[-1] - 'A' + 10); goto yyc_hex; }
|
||||
yy41:
|
||||
++s;
|
||||
{ adddgt<16>(u, s[-1] - 'a' + 10); goto yyc_hex; }
|
||||
yy21:
|
||||
++YYCURSOR;
|
||||
{ add<16>(u, YYCURSOR[-1] - '0'); goto yyc_hex; }
|
||||
yy22:
|
||||
++YYCURSOR;
|
||||
{ add<16>(u, YYCURSOR[-1] - 'A' + 10); goto yyc_hex; }
|
||||
yy23:
|
||||
++YYCURSOR;
|
||||
{ add<16>(u, YYCURSOR[-1] - 'a' + 10); goto yyc_hex; }
|
||||
/* *********************************** */
|
||||
yyc_oct:
|
||||
yych = *s;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy45;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7': goto yy49;
|
||||
default: goto yy47;
|
||||
case 0x00: goto yy25;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7': goto yy27;
|
||||
default: goto yy26;
|
||||
}
|
||||
yy45:
|
||||
++s;
|
||||
yy25:
|
||||
++YYCURSOR;
|
||||
{ return u; }
|
||||
yy47:
|
||||
++s;
|
||||
yy26:
|
||||
++YYCURSOR;
|
||||
{ return ERROR; }
|
||||
yy49:
|
||||
++s;
|
||||
{ adddgt<8> (u, s[-1] - '0'); goto yyc_oct; }
|
||||
yy27:
|
||||
++YYCURSOR;
|
||||
{ add<8>(u, YYCURSOR[-1] - '0'); goto yyc_oct; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
assert(parse_u32("") == ERROR);
|
||||
assert(parse_u32("1234567890") == 1234567890);
|
||||
assert(parse_u32("0b1101") == 13);
|
||||
assert(parse_u32("0x7Fe") == 2046);
|
||||
assert(parse_u32("0644") == 420);
|
||||
assert(parse_u32("9999999999") == ERROR);
|
||||
assert(parse_u32("") == ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,54 +3,50 @@
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
static const uint64_t ERROR = ~0lu;
|
||||
/*!types:re2c*/
|
||||
static const uint64_t ERROR = UINT64_MAX;
|
||||
/*!conditions:re2c*/
|
||||
|
||||
template<int BASE> static void adddgt(uint64_t &u, unsigned int d)
|
||||
{
|
||||
template<int BASE> static void add(uint64_t &u, char d) {
|
||||
u = u * BASE + d;
|
||||
if (u > UINT32_MAX) u = ERROR;
|
||||
}
|
||||
|
||||
static uint64_t parse_u32(const char *s)
|
||||
{
|
||||
const char *YYMARKER;
|
||||
static uint64_t parse_u32(const char *s) {
|
||||
const char *YYCURSOR = s, *YYMARKER;
|
||||
int c = yycinit;
|
||||
uint64_t u = 0;
|
||||
|
||||
/*!re2c
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYCURSOR = s;
|
||||
re2c:define:YYGETCONDITION = "c";
|
||||
re2c:define:YYSETCONDITION = "c = @@;";
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYGETCONDITION = "c";
|
||||
re2c:define:YYSETCONDITION = "c = @@;";
|
||||
re2c:yyfill:enable = 0;
|
||||
|
||||
<*> * { return ERROR; }
|
||||
<*> * { return ERROR; }
|
||||
|
||||
<init> '0b' / [01] :=> bin
|
||||
<init> "0" :=> oct
|
||||
<init> "" / [1-9] :=> dec
|
||||
<init> '0x' / [0-9a-fA-F] :=> hex
|
||||
<init> '0b' / [01] :=> bin
|
||||
<init> "0" :=> oct
|
||||
<init> "" / [1-9] :=> dec
|
||||
<init> '0x' / [0-9a-fA-F] :=> hex
|
||||
|
||||
<bin, oct, dec, hex> "\x00" { return u; }
|
||||
<bin, oct, dec, hex> "\x00" { return u; }
|
||||
|
||||
<bin> [01] { adddgt<2> (u, s[-1] - '0'); goto yyc_bin; }
|
||||
<oct> [0-7] { adddgt<8> (u, s[-1] - '0'); goto yyc_oct; }
|
||||
<dec> [0-9] { adddgt<10>(u, s[-1] - '0'); goto yyc_dec; }
|
||||
<hex> [0-9] { adddgt<16>(u, s[-1] - '0'); goto yyc_hex; }
|
||||
<hex> [a-f] { adddgt<16>(u, s[-1] - 'a' + 10); goto yyc_hex; }
|
||||
<hex> [A-F] { adddgt<16>(u, s[-1] - 'A' + 10); goto yyc_hex; }
|
||||
<bin> [01] { add<2>(u, YYCURSOR[-1] - '0'); goto yyc_bin; }
|
||||
<oct> [0-7] { add<8>(u, YYCURSOR[-1] - '0'); goto yyc_oct; }
|
||||
<dec> [0-9] { add<10>(u, YYCURSOR[-1] - '0'); goto yyc_dec; }
|
||||
<hex> [0-9] { add<16>(u, YYCURSOR[-1] - '0'); goto yyc_hex; }
|
||||
<hex> [a-f] { add<16>(u, YYCURSOR[-1] - 'a' + 10); goto yyc_hex; }
|
||||
<hex> [A-F] { add<16>(u, YYCURSOR[-1] - 'A' + 10); goto yyc_hex; }
|
||||
*/
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
assert(parse_u32("") == ERROR);
|
||||
assert(parse_u32("1234567890") == 1234567890);
|
||||
assert(parse_u32("0b1101") == 13);
|
||||
assert(parse_u32("0x7Fe") == 2046);
|
||||
assert(parse_u32("0644") == 420);
|
||||
assert(parse_u32("9999999999") == ERROR);
|
||||
assert(parse_u32("") == ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1994
-2000
File diff suppressed because it is too large
Load Diff
@@ -1,31 +1,27 @@
|
||||
// re2c $INPUT -o $OUTPUT -8 --case-ranges -i
|
||||
//
|
||||
// Simplified "Unicode Identifier and Pattern Syntax"
|
||||
// (see https://unicode.org/reports/tr31)
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*!include:re2c "unicode_categories.re" */
|
||||
|
||||
static int lex(const char *YYCURSOR)
|
||||
{
|
||||
const char *YYMARKER;
|
||||
static int lex(const char *s) {
|
||||
const char *YYCURSOR = s, *YYMARKER;
|
||||
/*!re2c
|
||||
re2c:define:YYCTYPE = 'unsigned char';
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:define:YYCTYPE = 'unsigned char';
|
||||
re2c:yyfill:enable = 0;
|
||||
|
||||
id_start = L | Nl | [$_];
|
||||
id_continue = id_start | Mn | Mc | Nd | Pc | [\u200D\u05F3];
|
||||
identifier = id_start id_continue*;
|
||||
// Simplified "Unicode Identifier and Pattern Syntax"
|
||||
// (see https://unicode.org/reports/tr31)
|
||||
id_start = L | Nl | [$_];
|
||||
id_continue = id_start | Mn | Mc | Nd | Pc | [\u200D\u05F3];
|
||||
identifier = id_start id_continue*;
|
||||
|
||||
identifier { return 0; }
|
||||
* { return 1; }
|
||||
identifier { return 0; }
|
||||
* { return 1; }
|
||||
*/
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
assert(lex("_Ыдентификатор") == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,111 +1,111 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "c/eof/01_sentinel.re"
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
|
||||
// expect a null-terminated string
|
||||
static int lex(const char *YYCURSOR)
|
||||
{
|
||||
// Expect a null-terminated string.
|
||||
static int lex(const char *YYCURSOR) {
|
||||
int count = 0;
|
||||
loop:
|
||||
|
||||
for (;;) {
|
||||
|
||||
#line 13 "c/eof/01_sentinel.c"
|
||||
{
|
||||
char yych;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy2;
|
||||
case ' ': goto yy6;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z': goto yy9;
|
||||
default: goto yy4;
|
||||
case 0x00: goto yy1;
|
||||
case ' ': goto yy3;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z': goto yy5;
|
||||
default: goto yy2;
|
||||
}
|
||||
yy2:
|
||||
yy1:
|
||||
++YYCURSOR;
|
||||
#line 14 "c/eof/01_sentinel.re"
|
||||
{ return count; }
|
||||
#line 52 "c/eof/01_sentinel.c"
|
||||
yy4:
|
||||
yy2:
|
||||
++YYCURSOR;
|
||||
#line 13 "c/eof/01_sentinel.re"
|
||||
{ return -1; }
|
||||
#line 57 "c/eof/01_sentinel.c"
|
||||
yy6:
|
||||
yy3:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case ' ': goto yy6;
|
||||
default: goto yy8;
|
||||
case ' ': goto yy3;
|
||||
default: goto yy4;
|
||||
}
|
||||
yy8:
|
||||
yy4:
|
||||
#line 16 "c/eof/01_sentinel.re"
|
||||
{ goto loop; }
|
||||
{ continue; }
|
||||
#line 67 "c/eof/01_sentinel.c"
|
||||
yy9:
|
||||
yy5:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z': goto yy9;
|
||||
default: goto yy11;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z': goto yy5;
|
||||
default: goto yy6;
|
||||
}
|
||||
yy11:
|
||||
yy6:
|
||||
#line 15 "c/eof/01_sentinel.re"
|
||||
{ ++count; goto loop; }
|
||||
{ ++count; continue; }
|
||||
#line 102 "c/eof/01_sentinel.c"
|
||||
}
|
||||
#line 18 "c/eof/01_sentinel.re"
|
||||
#line 17 "c/eof/01_sentinel.re"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
assert(lex("") == 0);
|
||||
assert(lex("one two three") == 3);
|
||||
assert(lex("f0ur") == -1);
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
|
||||
// expect a null-terminated string
|
||||
static int lex(const char *YYCURSOR)
|
||||
{
|
||||
// Expect a null-terminated string.
|
||||
static int lex(const char *YYCURSOR) {
|
||||
int count = 0;
|
||||
loop:
|
||||
|
||||
for (;;) {
|
||||
/*!re2c
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:yyfill:enable = 0;
|
||||
|
||||
* { return -1; }
|
||||
[\x00] { return count; }
|
||||
[a-z]+ { ++count; goto loop; }
|
||||
[ ]+ { goto loop; }
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:yyfill:enable = 0;
|
||||
|
||||
* { return -1; }
|
||||
[\x00] { return count; }
|
||||
[a-z]+ { ++count; continue; }
|
||||
[ ]+ { continue; }
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
assert(lex("") == 0);
|
||||
assert(lex("one two three") == 3);
|
||||
assert(lex("f0ur") == -1);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "c/eof/02_bounds_checking.re"
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -10,87 +10,88 @@
|
||||
#line 6 "c/eof/02_bounds_checking.re"
|
||||
|
||||
|
||||
// expect YYMAXFILL-padded string
|
||||
static int lex(const char *str, unsigned int len)
|
||||
{
|
||||
const char *YYCURSOR = str, *YYLIMIT = str + len + YYMAXFILL;
|
||||
static int lex(const char *str, unsigned int len) {
|
||||
// Make a copy of the string with YYMAXFILL zeroes at the end.
|
||||
char *buf = (char*) malloc(len + YYMAXFILL);
|
||||
memcpy(buf, str, len);
|
||||
memset(buf + len, 0, YYMAXFILL);
|
||||
|
||||
const char *YYCURSOR = buf, *YYLIMIT = buf + len + YYMAXFILL;
|
||||
int count = 0;
|
||||
|
||||
loop:
|
||||
|
||||
#line 22 "c/eof/02_bounds_checking.c"
|
||||
#line 25 "c/eof/02_bounds_checking.c"
|
||||
{
|
||||
char yych;
|
||||
if (YYLIMIT <= YYCURSOR) return -1;
|
||||
if (YYLIMIT <= YYCURSOR) goto fail;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy2;
|
||||
case ' ': goto yy6;
|
||||
case '\'': goto yy9;
|
||||
default: goto yy4;
|
||||
case 0x00: goto yy1;
|
||||
case ' ': goto yy3;
|
||||
case '\'': goto yy5;
|
||||
default: goto yy2;
|
||||
}
|
||||
yy1:
|
||||
++YYCURSOR;
|
||||
#line 25 "c/eof/02_bounds_checking.re"
|
||||
{
|
||||
// Check that it is the sentinel, not some unexpected null.
|
||||
if (YYCURSOR - 1 == buf + len) goto exit; else goto fail;
|
||||
}
|
||||
#line 43 "c/eof/02_bounds_checking.c"
|
||||
yy2:
|
||||
++YYCURSOR;
|
||||
#line 21 "c/eof/02_bounds_checking.re"
|
||||
{ return YYCURSOR + YYMAXFILL - 1 == YYLIMIT ? count : -1; }
|
||||
#line 37 "c/eof/02_bounds_checking.c"
|
||||
yy4:
|
||||
#line 31 "c/eof/02_bounds_checking.re"
|
||||
{ goto fail; }
|
||||
#line 48 "c/eof/02_bounds_checking.c"
|
||||
yy3:
|
||||
++YYCURSOR;
|
||||
#line 20 "c/eof/02_bounds_checking.re"
|
||||
{ return -1; }
|
||||
#line 42 "c/eof/02_bounds_checking.c"
|
||||
if (YYLIMIT <= YYCURSOR) goto fail;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case ' ': goto yy3;
|
||||
default: goto yy4;
|
||||
}
|
||||
yy4:
|
||||
#line 30 "c/eof/02_bounds_checking.re"
|
||||
{ goto loop; }
|
||||
#line 60 "c/eof/02_bounds_checking.c"
|
||||
yy5:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) goto fail;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case '\'': goto yy6;
|
||||
case '\\': goto yy7;
|
||||
default: goto yy5;
|
||||
}
|
||||
yy6:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) return -1;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case ' ': goto yy6;
|
||||
default: goto yy8;
|
||||
}
|
||||
yy8:
|
||||
#line 23 "c/eof/02_bounds_checking.re"
|
||||
{ goto loop; }
|
||||
#line 54 "c/eof/02_bounds_checking.c"
|
||||
yy9:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) return -1;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case '\'': goto yy11;
|
||||
case '\\': goto yy13;
|
||||
default: goto yy9;
|
||||
}
|
||||
yy11:
|
||||
++YYCURSOR;
|
||||
#line 22 "c/eof/02_bounds_checking.re"
|
||||
#line 29 "c/eof/02_bounds_checking.re"
|
||||
{ ++count; goto loop; }
|
||||
#line 68 "c/eof/02_bounds_checking.c"
|
||||
yy13:
|
||||
#line 74 "c/eof/02_bounds_checking.c"
|
||||
yy7:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) return -1;
|
||||
yych = *YYCURSOR;
|
||||
goto yy9;
|
||||
if (YYLIMIT <= YYCURSOR) goto fail;
|
||||
goto yy5;
|
||||
}
|
||||
#line 25 "c/eof/02_bounds_checking.re"
|
||||
#line 32 "c/eof/02_bounds_checking.re"
|
||||
|
||||
|
||||
fail:
|
||||
count = -1;
|
||||
|
||||
exit:
|
||||
free(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
// make a copy of the string with YYMAXFILL zeroes at the end
|
||||
static void test(const char *str, unsigned int len, int res)
|
||||
{
|
||||
char *s = (char*) malloc(len + YYMAXFILL);
|
||||
memcpy(s, str, len);
|
||||
memset(s + len, 0, YYMAXFILL);
|
||||
int r = lex(s, len);
|
||||
free(s);
|
||||
assert(r == res);
|
||||
}
|
||||
|
||||
#define TEST(s, r) test(s, sizeof(s) - 1, r)
|
||||
int main()
|
||||
{
|
||||
#define TEST(s, r) assert(lex(s, sizeof(s) - 1) == r)
|
||||
int main() {
|
||||
TEST("", 0);
|
||||
TEST("'qu\0tes' 'are' 'fine: \\'' ", 3);
|
||||
TEST("'unterminated\\'", -1);
|
||||
TEST("'unexpected \0 null\\'", -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,46 +1,49 @@
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*!max:re2c*/
|
||||
|
||||
// expect YYMAXFILL-padded string
|
||||
static int lex(const char *str, unsigned int len)
|
||||
{
|
||||
const char *YYCURSOR = str, *YYLIMIT = str + len + YYMAXFILL;
|
||||
static int lex(const char *str, unsigned int len) {
|
||||
// Make a copy of the string with YYMAXFILL zeroes at the end.
|
||||
char *buf = (char*) malloc(len + YYMAXFILL);
|
||||
memcpy(buf, str, len);
|
||||
memset(buf + len, 0, YYMAXFILL);
|
||||
|
||||
const char *YYCURSOR = buf, *YYLIMIT = buf + len + YYMAXFILL;
|
||||
int count = 0;
|
||||
|
||||
loop:
|
||||
/*!re2c
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYFILL = "return -1;";
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYFILL = "goto fail;";
|
||||
|
||||
* { return -1; }
|
||||
[\x00] { return YYCURSOR + YYMAXFILL - 1 == YYLIMIT ? count : -1; }
|
||||
['] ([^'\\] | [\\][^])* ['] { ++count; goto loop; }
|
||||
[ ]+ { goto loop; }
|
||||
str = ['] ([^'\\] | [\\][^])* ['];
|
||||
|
||||
[\x00] {
|
||||
// Check that it is the sentinel, not some unexpected null.
|
||||
if (YYCURSOR - 1 == buf + len) goto exit; else goto fail;
|
||||
}
|
||||
str { ++count; goto loop; }
|
||||
[ ]+ { goto loop; }
|
||||
* { goto fail; }
|
||||
*/
|
||||
|
||||
fail:
|
||||
count = -1;
|
||||
|
||||
exit:
|
||||
free(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
// make a copy of the string with YYMAXFILL zeroes at the end
|
||||
static void test(const char *str, unsigned int len, int res)
|
||||
{
|
||||
char *s = (char*) malloc(len + YYMAXFILL);
|
||||
memcpy(s, str, len);
|
||||
memset(s + len, 0, YYMAXFILL);
|
||||
int r = lex(s, len);
|
||||
free(s);
|
||||
assert(r == res);
|
||||
}
|
||||
|
||||
#define TEST(s, r) test(s, sizeof(s) - 1, r)
|
||||
int main()
|
||||
{
|
||||
#define TEST(s, r) assert(lex(s, sizeof(s) - 1) == r)
|
||||
int main() {
|
||||
TEST("", 0);
|
||||
TEST("'qu\0tes' 'are' 'fine: \\'' ", 3);
|
||||
TEST("'unterminated\\'", -1);
|
||||
TEST("'unexpected \0 null\\'", -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,84 +1,83 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "c/eof/03_eof_rule.re"
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
|
||||
// expect a null-terminated string
|
||||
static int lex(const char *str, unsigned int len)
|
||||
{
|
||||
// Expect a null-terminated string.
|
||||
static int lex(const char *str, unsigned int len) {
|
||||
const char *YYCURSOR = str, *YYLIMIT = str + len, *YYMARKER;
|
||||
int count = 0;
|
||||
|
||||
loop:
|
||||
for (;;) {
|
||||
|
||||
#line 15 "c/eof/03_eof_rule.c"
|
||||
#line 14 "c/eof/03_eof_rule.c"
|
||||
{
|
||||
char yych;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case ' ': goto yy4;
|
||||
case '\'': goto yy7;
|
||||
default:
|
||||
if (YYLIMIT <= YYCURSOR) goto yy13;
|
||||
goto yy2;
|
||||
case ' ': goto yy3;
|
||||
case '\'': goto yy5;
|
||||
default:
|
||||
if (YYLIMIT <= YYCURSOR) goto yy10;
|
||||
goto yy1;
|
||||
}
|
||||
yy1:
|
||||
++YYCURSOR;
|
||||
yy2:
|
||||
++YYCURSOR;
|
||||
yy3:
|
||||
#line 16 "c/eof/03_eof_rule.re"
|
||||
#line 17 "c/eof/03_eof_rule.re"
|
||||
{ return -1; }
|
||||
#line 31 "c/eof/03_eof_rule.c"
|
||||
#line 30 "c/eof/03_eof_rule.c"
|
||||
yy3:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case ' ': goto yy3;
|
||||
default: goto yy4;
|
||||
}
|
||||
yy4:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case ' ': goto yy4;
|
||||
default: goto yy6;
|
||||
}
|
||||
yy6:
|
||||
#line 19 "c/eof/03_eof_rule.re"
|
||||
{ goto loop; }
|
||||
#line 41 "c/eof/03_eof_rule.c"
|
||||
yy7:
|
||||
#line 20 "c/eof/03_eof_rule.re"
|
||||
{ continue; }
|
||||
#line 40 "c/eof/03_eof_rule.c"
|
||||
yy5:
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if (yych >= 0x01) goto yy9;
|
||||
if (YYLIMIT <= YYCURSOR) goto yy3;
|
||||
yy8:
|
||||
if (yych >= 0x01) goto yy7;
|
||||
if (YYLIMIT <= YYCURSOR) goto yy2;
|
||||
yy6:
|
||||
yych = *++YYCURSOR;
|
||||
yy9:
|
||||
yy7:
|
||||
switch (yych) {
|
||||
case '\'': goto yy10;
|
||||
case '\\': goto yy12;
|
||||
default:
|
||||
if (YYLIMIT <= YYCURSOR) goto yy14;
|
||||
goto yy8;
|
||||
case '\'': goto yy8;
|
||||
case '\\': goto yy9;
|
||||
default:
|
||||
if (YYLIMIT <= YYCURSOR) goto yy11;
|
||||
goto yy6;
|
||||
}
|
||||
yy10:
|
||||
yy8:
|
||||
++YYCURSOR;
|
||||
#line 18 "c/eof/03_eof_rule.re"
|
||||
{ ++count; goto loop; }
|
||||
#line 60 "c/eof/03_eof_rule.c"
|
||||
yy12:
|
||||
#line 19 "c/eof/03_eof_rule.re"
|
||||
{ ++count; continue; }
|
||||
#line 59 "c/eof/03_eof_rule.c"
|
||||
yy9:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= 0x00) {
|
||||
if (YYLIMIT <= YYCURSOR) goto yy14;
|
||||
goto yy8;
|
||||
if (YYLIMIT <= YYCURSOR) goto yy11;
|
||||
goto yy6;
|
||||
}
|
||||
goto yy8;
|
||||
yy13:
|
||||
#line 17 "c/eof/03_eof_rule.re"
|
||||
goto yy6;
|
||||
yy10:
|
||||
#line 18 "c/eof/03_eof_rule.re"
|
||||
{ return count; }
|
||||
#line 71 "c/eof/03_eof_rule.c"
|
||||
yy14:
|
||||
#line 70 "c/eof/03_eof_rule.c"
|
||||
yy11:
|
||||
YYCURSOR = YYMARKER;
|
||||
goto yy3;
|
||||
goto yy2;
|
||||
}
|
||||
#line 21 "c/eof/03_eof_rule.re"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#define TEST(s, r) assert(lex(s, sizeof(s) - 1) == r)
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
TEST("", 0);
|
||||
TEST("'qu\0tes' 'are' 'fine: \\'' ", 3);
|
||||
TEST("'unterminated\\'", -1);
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
|
||||
// expect a null-terminated string
|
||||
static int lex(const char *str, unsigned int len)
|
||||
{
|
||||
// Expect a null-terminated string.
|
||||
static int lex(const char *str, unsigned int len) {
|
||||
const char *YYCURSOR = str, *YYLIMIT = str + len, *YYMARKER;
|
||||
int count = 0;
|
||||
|
||||
loop:
|
||||
for (;;) {
|
||||
/*!re2c
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:eof = 0;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:eof = 0;
|
||||
|
||||
* { return -1; }
|
||||
$ { return count; }
|
||||
['] ([^'\\] | [\\][^])* ['] { ++count; goto loop; }
|
||||
[ ]+ { goto loop; }
|
||||
str = ['] ([^'\\] | [\\][^])* ['];
|
||||
|
||||
* { return -1; }
|
||||
$ { return count; }
|
||||
str { ++count; continue; }
|
||||
[ ]+ { continue; }
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#define TEST(s, r) assert(lex(s, sizeof(s) - 1) == r)
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
TEST("", 0);
|
||||
TEST("'qu\0tes' 'are' 'fine: \\'' ", 3);
|
||||
TEST("'unterminated\\'", -1);
|
||||
|
||||
@@ -1,128 +1,123 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "c/eof/04_generic_api_sentinel.re"
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// expect a string without terminating null
|
||||
static int lex(const char *str, unsigned int len)
|
||||
{
|
||||
const char *cur = str, *lim = str + len;
|
||||
static int lex(const char *str, unsigned int len) {
|
||||
// For the sake of example create a string without terminating null.
|
||||
char *buf = (char*) malloc(len);
|
||||
memcpy(buf, str, len);
|
||||
|
||||
const char *cur = buf, *lim = buf + len;
|
||||
int count = 0;
|
||||
|
||||
loop:
|
||||
for (;;) {
|
||||
|
||||
#line 17 "c/eof/04_generic_api_sentinel.c"
|
||||
#line 19 "c/eof/04_generic_api_sentinel.c"
|
||||
{
|
||||
char yych;
|
||||
yych = cur < lim ? *cur : 0;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy2;
|
||||
case ' ': goto yy6;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z': goto yy9;
|
||||
default: goto yy4;
|
||||
case 0x00: goto yy1;
|
||||
case ' ': goto yy3;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z': goto yy5;
|
||||
default: goto yy2;
|
||||
}
|
||||
yy1:
|
||||
++cur;
|
||||
#line 24 "c/eof/04_generic_api_sentinel.re"
|
||||
{ break;; }
|
||||
#line 58 "c/eof/04_generic_api_sentinel.c"
|
||||
yy2:
|
||||
++cur;
|
||||
#line 23 "c/eof/04_generic_api_sentinel.re"
|
||||
{ return count; }
|
||||
#line 56 "c/eof/04_generic_api_sentinel.c"
|
||||
{ count = -1; break; }
|
||||
#line 63 "c/eof/04_generic_api_sentinel.c"
|
||||
yy3:
|
||||
++cur;
|
||||
yych = cur < lim ? *cur : 0;
|
||||
switch (yych) {
|
||||
case ' ': goto yy3;
|
||||
default: goto yy4;
|
||||
}
|
||||
yy4:
|
||||
#line 26 "c/eof/04_generic_api_sentinel.re"
|
||||
{ continue; }
|
||||
#line 74 "c/eof/04_generic_api_sentinel.c"
|
||||
yy5:
|
||||
++cur;
|
||||
#line 22 "c/eof/04_generic_api_sentinel.re"
|
||||
{ return -1; }
|
||||
#line 61 "c/eof/04_generic_api_sentinel.c"
|
||||
yych = cur < lim ? *cur : 0;
|
||||
switch (yych) {
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z': goto yy5;
|
||||
default: goto yy6;
|
||||
}
|
||||
yy6:
|
||||
++cur;
|
||||
yych = cur < lim ? *cur : 0;
|
||||
switch (yych) {
|
||||
case ' ': goto yy6;
|
||||
default: goto yy8;
|
||||
}
|
||||
yy8:
|
||||
#line 25 "c/eof/04_generic_api_sentinel.re"
|
||||
{ goto loop; }
|
||||
#line 72 "c/eof/04_generic_api_sentinel.c"
|
||||
yy9:
|
||||
++cur;
|
||||
yych = cur < lim ? *cur : 0;
|
||||
switch (yych) {
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z': goto yy9;
|
||||
default: goto yy11;
|
||||
}
|
||||
yy11:
|
||||
#line 24 "c/eof/04_generic_api_sentinel.re"
|
||||
{ ++count; goto loop; }
|
||||
#line 108 "c/eof/04_generic_api_sentinel.c"
|
||||
{ ++count; continue;; }
|
||||
#line 110 "c/eof/04_generic_api_sentinel.c"
|
||||
}
|
||||
#line 27 "c/eof/04_generic_api_sentinel.re"
|
||||
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
// make a copy of the string without terminating null
|
||||
static void test(const char *str, unsigned int len, int res)
|
||||
{
|
||||
char *s = (char*) malloc(len);
|
||||
memcpy(s, str, len);
|
||||
int r = lex(s, len);
|
||||
free(s);
|
||||
assert(r == res);
|
||||
}
|
||||
|
||||
#define TEST(s, r) test(s, sizeof(s) - 1, r)
|
||||
int main()
|
||||
{
|
||||
#define TEST(s, r) assert(lex(s, sizeof(s) - 1) == r)
|
||||
int main() {
|
||||
TEST("", 0);
|
||||
TEST("one two three ", 3);
|
||||
TEST("f0ur", -1);
|
||||
|
||||
@@ -1,45 +1,38 @@
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// expect a string without terminating null
|
||||
static int lex(const char *str, unsigned int len)
|
||||
{
|
||||
const char *cur = str, *lim = str + len;
|
||||
static int lex(const char *str, unsigned int len) {
|
||||
// For the sake of example create a string without terminating null.
|
||||
char *buf = (char*) malloc(len);
|
||||
memcpy(buf, str, len);
|
||||
|
||||
const char *cur = buf, *lim = buf + len;
|
||||
int count = 0;
|
||||
|
||||
loop:
|
||||
for (;;) {
|
||||
/*!re2c
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:flags:input = custom;
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYLESSTHAN = "cur >= lim";
|
||||
re2c:define:YYPEEK = "cur < lim ? *cur : 0"; // fake null
|
||||
re2c:define:YYSKIP = "++cur;";
|
||||
|
||||
* { return -1; }
|
||||
[\x00] { return count; }
|
||||
[a-z]+ { ++count; goto loop; }
|
||||
[ ]+ { goto loop; }
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:api = custom;
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYPEEK = "cur < lim ? *cur : 0"; // fake null
|
||||
re2c:define:YYSKIP = "++cur;";
|
||||
|
||||
* { count = -1; break; }
|
||||
[\x00] { break;; }
|
||||
[a-z]+ { ++count; continue;; }
|
||||
[ ]+ { continue; }
|
||||
*/
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
// make a copy of the string without terminating null
|
||||
static void test(const char *str, unsigned int len, int res)
|
||||
{
|
||||
char *s = (char*) malloc(len);
|
||||
memcpy(s, str, len);
|
||||
int r = lex(s, len);
|
||||
free(s);
|
||||
assert(r == res);
|
||||
}
|
||||
|
||||
#define TEST(s, r) test(s, sizeof(s) - 1, r)
|
||||
int main()
|
||||
{
|
||||
#define TEST(s, r) assert(lex(s, sizeof(s) - 1) == r)
|
||||
int main() {
|
||||
TEST("", 0);
|
||||
TEST("one two three ", 3);
|
||||
TEST("f0ur", -1);
|
||||
|
||||
@@ -1,101 +1,96 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "c/eof/05_generic_api_eof_rule.re"
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// expect a string without terminating null
|
||||
static int lex(const char *str, unsigned int len)
|
||||
{
|
||||
const char *cur = str, *lim = str + len, *mar;
|
||||
static int lex(const char *str, unsigned int len) {
|
||||
// For the sake of example create a string without terminating null.
|
||||
char *buf = (char*) malloc(len);
|
||||
memcpy(buf, str, len);
|
||||
|
||||
const char *cur = buf, *lim = buf + len, *mar;
|
||||
int count = 0;
|
||||
|
||||
loop:
|
||||
for (;;) {
|
||||
|
||||
#line 17 "c/eof/05_generic_api_eof_rule.c"
|
||||
#line 19 "c/eof/05_generic_api_eof_rule.c"
|
||||
{
|
||||
char yych;
|
||||
yych = cur < lim ? *cur : 0;
|
||||
switch (yych) {
|
||||
case ' ': goto yy4;
|
||||
case '\'': goto yy7;
|
||||
default:
|
||||
if (cur >= lim) goto yy13;
|
||||
goto yy2;
|
||||
case ' ': goto yy3;
|
||||
case '\'': goto yy5;
|
||||
default:
|
||||
if (cur >= lim) goto yy10;
|
||||
goto yy1;
|
||||
}
|
||||
yy2:
|
||||
yy1:
|
||||
++cur;
|
||||
yy2:
|
||||
#line 29 "c/eof/05_generic_api_eof_rule.re"
|
||||
{ count = -1; break; }
|
||||
#line 35 "c/eof/05_generic_api_eof_rule.c"
|
||||
yy3:
|
||||
#line 25 "c/eof/05_generic_api_eof_rule.re"
|
||||
{ return -1; }
|
||||
#line 33 "c/eof/05_generic_api_eof_rule.c"
|
||||
yy4:
|
||||
++cur;
|
||||
yych = cur < lim ? *cur : 0;
|
||||
switch (yych) {
|
||||
case ' ': goto yy4;
|
||||
default: goto yy6;
|
||||
case ' ': goto yy3;
|
||||
default: goto yy4;
|
||||
}
|
||||
yy6:
|
||||
#line 28 "c/eof/05_generic_api_eof_rule.re"
|
||||
{ goto loop; }
|
||||
#line 44 "c/eof/05_generic_api_eof_rule.c"
|
||||
yy7:
|
||||
yy4:
|
||||
#line 32 "c/eof/05_generic_api_eof_rule.re"
|
||||
{ continue; }
|
||||
#line 46 "c/eof/05_generic_api_eof_rule.c"
|
||||
yy5:
|
||||
++cur;
|
||||
mar = cur;
|
||||
yych = cur < lim ? *cur : 0;
|
||||
if (yych >= 0x01) goto yy9;
|
||||
if (cur >= lim) goto yy3;
|
||||
yy8:
|
||||
if (yych >= 0x01) goto yy7;
|
||||
if (cur >= lim) goto yy2;
|
||||
yy6:
|
||||
++cur;
|
||||
yych = cur < lim ? *cur : 0;
|
||||
yy9:
|
||||
yy7:
|
||||
switch (yych) {
|
||||
case '\'': goto yy10;
|
||||
case '\\': goto yy12;
|
||||
default:
|
||||
if (cur >= lim) goto yy14;
|
||||
goto yy8;
|
||||
case '\'': goto yy8;
|
||||
case '\\': goto yy9;
|
||||
default:
|
||||
if (cur >= lim) goto yy11;
|
||||
goto yy6;
|
||||
}
|
||||
yy10:
|
||||
yy8:
|
||||
++cur;
|
||||
#line 27 "c/eof/05_generic_api_eof_rule.re"
|
||||
{ ++count; goto loop; }
|
||||
#line 66 "c/eof/05_generic_api_eof_rule.c"
|
||||
yy12:
|
||||
#line 31 "c/eof/05_generic_api_eof_rule.re"
|
||||
{ ++count; continue; }
|
||||
#line 68 "c/eof/05_generic_api_eof_rule.c"
|
||||
yy9:
|
||||
++cur;
|
||||
yych = cur < lim ? *cur : 0;
|
||||
if (yych <= 0x00) {
|
||||
if (cur >= lim) goto yy14;
|
||||
goto yy8;
|
||||
if (cur >= lim) goto yy11;
|
||||
goto yy6;
|
||||
}
|
||||
goto yy8;
|
||||
yy13:
|
||||
#line 26 "c/eof/05_generic_api_eof_rule.re"
|
||||
{ return count; }
|
||||
#line 78 "c/eof/05_generic_api_eof_rule.c"
|
||||
yy14:
|
||||
cur = mar;
|
||||
goto yy3;
|
||||
}
|
||||
goto yy6;
|
||||
yy10:
|
||||
#line 30 "c/eof/05_generic_api_eof_rule.re"
|
||||
{ break;; }
|
||||
#line 80 "c/eof/05_generic_api_eof_rule.c"
|
||||
yy11:
|
||||
cur = mar;
|
||||
goto yy2;
|
||||
}
|
||||
#line 33 "c/eof/05_generic_api_eof_rule.re"
|
||||
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
// make a copy of the string without terminating null
|
||||
static void test(const char *str, unsigned int len, int res)
|
||||
{
|
||||
char *s = (char*) malloc(len);
|
||||
memcpy(s, str, len);
|
||||
int r = lex(s, len);
|
||||
free(s);
|
||||
assert(r == res);
|
||||
}
|
||||
|
||||
#define TEST(s, r) test(s, sizeof(s) - 1, r)
|
||||
int main()
|
||||
{
|
||||
#define TEST(s, r) assert(lex(s, sizeof(s) - 1) == r)
|
||||
int main() {
|
||||
TEST("", 0);
|
||||
TEST("'qu\0tes' 'are' 'fine: \\'' ", 3);
|
||||
TEST("'unterminated\\'", -1);
|
||||
|
||||
@@ -1,48 +1,44 @@
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// expect a string without terminating null
|
||||
static int lex(const char *str, unsigned int len)
|
||||
{
|
||||
const char *cur = str, *lim = str + len, *mar;
|
||||
static int lex(const char *str, unsigned int len) {
|
||||
// For the sake of example create a string without terminating null.
|
||||
char *buf = (char*) malloc(len);
|
||||
memcpy(buf, str, len);
|
||||
|
||||
const char *cur = buf, *lim = buf + len, *mar;
|
||||
int count = 0;
|
||||
|
||||
loop:
|
||||
for (;;) {
|
||||
/*!re2c
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:eof = 0;
|
||||
re2c:flags:input = custom;
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYLESSTHAN = "cur >= lim";
|
||||
re2c:define:YYPEEK = "cur < lim ? *cur : 0"; // fake null
|
||||
re2c:define:YYSKIP = "++cur;";
|
||||
re2c:define:YYBACKUP = "mar = cur;";
|
||||
re2c:define:YYRESTORE = "cur = mar;";
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:eof = 0;
|
||||
re2c:api = custom;
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYLESSTHAN = "cur >= lim";
|
||||
re2c:define:YYPEEK = "cur < lim ? *cur : 0"; // fake null
|
||||
re2c:define:YYSKIP = "++cur;";
|
||||
re2c:define:YYBACKUP = "mar = cur;";
|
||||
re2c:define:YYRESTORE = "cur = mar;";
|
||||
|
||||
* { return -1; }
|
||||
$ { return count; }
|
||||
['] ([^'\\] | [\\][^])* ['] { ++count; goto loop; }
|
||||
[ ]+ { goto loop; }
|
||||
str = ['] ([^'\\] | [\\][^])* ['];
|
||||
|
||||
* { count = -1; break; }
|
||||
$ { break;; }
|
||||
str { ++count; continue; }
|
||||
[ ]+ { continue; }
|
||||
*/
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
// make a copy of the string without terminating null
|
||||
static void test(const char *str, unsigned int len, int res)
|
||||
{
|
||||
char *s = (char*) malloc(len);
|
||||
memcpy(s, str, len);
|
||||
int r = lex(s, len);
|
||||
free(s);
|
||||
assert(r == res);
|
||||
}
|
||||
|
||||
#define TEST(s, r) test(s, sizeof(s) - 1, r)
|
||||
int main()
|
||||
{
|
||||
#define TEST(s, r) assert(lex(s, sizeof(s) - 1) == r)
|
||||
int main() {
|
||||
TEST("", 0);
|
||||
TEST("'qu\0tes' 'are' 'fine: \\'' ", 3);
|
||||
TEST("'unterminated\\'", -1);
|
||||
|
||||
+124
-123
@@ -1,162 +1,163 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "c/fill/01_fill.re"
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SIZE 4096
|
||||
#define BUFSIZE 4095
|
||||
|
||||
typedef struct {
|
||||
struct Input {
|
||||
FILE *file;
|
||||
char buf[SIZE + 1], *lim, *cur, *mar, *tok;
|
||||
int eof;
|
||||
} Input;
|
||||
char buf[BUFSIZE + 1], *lim, *cur, *mar, *tok; // +1 for sentinel
|
||||
bool eof;
|
||||
};
|
||||
|
||||
static int fill(Input *in)
|
||||
{
|
||||
if (in->eof) {
|
||||
return 1;
|
||||
}
|
||||
const size_t free = in->tok - in->buf;
|
||||
if (free < 1) {
|
||||
return 2;
|
||||
}
|
||||
memmove(in->buf, in->tok, in->lim - in->tok);
|
||||
in->lim -= free;
|
||||
in->cur -= free;
|
||||
in->mar -= free;
|
||||
in->tok -= free;
|
||||
in->lim += fread(in->lim, 1, free, in->file);
|
||||
in->lim[0] = 0;
|
||||
in->eof |= in->lim < in->buf + SIZE;
|
||||
static int fill(Input &in) {
|
||||
if (in.eof) return 1;
|
||||
|
||||
const size_t shift = in.tok - in.buf;
|
||||
const size_t used = in.lim - in.tok;
|
||||
|
||||
// Error: lexeme too long. In real life could reallocate a larger buffer.
|
||||
if (shift < 1) return 2;
|
||||
|
||||
// Shift buffer contents (discard everything up to the current token).
|
||||
memmove(in.buf, in.tok, used);
|
||||
in.lim -= shift;
|
||||
in.cur -= shift;
|
||||
in.mar -= shift;
|
||||
in.tok -= shift;
|
||||
|
||||
// Fill free space at the end of buffer with new data from file.
|
||||
in.lim += fread(in.lim, 1, BUFSIZE - used, in.file);
|
||||
in.lim[0] = 0;
|
||||
in.eof = in.lim < in.buf + BUFSIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void init(Input *in, FILE *file)
|
||||
{
|
||||
in->file = file;
|
||||
in->cur = in->mar = in->tok = in->lim = in->buf + SIZE;
|
||||
in->eof = 0;
|
||||
fill(in);
|
||||
}
|
||||
|
||||
static int lex(Input *in)
|
||||
{
|
||||
static int lex(Input &in) {
|
||||
int count = 0;
|
||||
loop:
|
||||
in->tok = in->cur;
|
||||
for (;;) {
|
||||
in.tok = in.cur;
|
||||
|
||||
#line 51 "c/fill/01_fill.c"
|
||||
#line 45 "c/fill/01_fill.c"
|
||||
{
|
||||
char yych;
|
||||
yyFillLabel0:
|
||||
yych = *in->cur;
|
||||
yych = *in.cur;
|
||||
switch (yych) {
|
||||
case ' ': goto yy4;
|
||||
case '\'': goto yy7;
|
||||
default:
|
||||
if (in->lim <= in->cur) {
|
||||
if (fill(in) == 0) goto yyFillLabel0;
|
||||
goto yy13;
|
||||
}
|
||||
case ' ': goto yy3;
|
||||
case '\'': goto yy5;
|
||||
default:
|
||||
if (in.lim <= in.cur) {
|
||||
if (fill(in) == 0) goto yyFillLabel0;
|
||||
goto yy10;
|
||||
}
|
||||
goto yy1;
|
||||
}
|
||||
yy1:
|
||||
++in.cur;
|
||||
yy2:
|
||||
#line 52 "c/fill/01_fill.re"
|
||||
{ return -1; }
|
||||
#line 65 "c/fill/01_fill.c"
|
||||
yy3:
|
||||
++in.cur;
|
||||
yyFillLabel1:
|
||||
yych = *in.cur;
|
||||
switch (yych) {
|
||||
case ' ': goto yy3;
|
||||
default:
|
||||
if (in.lim <= in.cur) {
|
||||
if (fill(in) == 0) goto yyFillLabel1;
|
||||
}
|
||||
goto yy4;
|
||||
}
|
||||
yy4:
|
||||
#line 55 "c/fill/01_fill.re"
|
||||
{ continue; }
|
||||
#line 81 "c/fill/01_fill.c"
|
||||
yy5:
|
||||
in.mar = ++in.cur;
|
||||
yyFillLabel2:
|
||||
yych = *in.cur;
|
||||
if (yych >= 0x01) goto yy7;
|
||||
if (in.lim <= in.cur) {
|
||||
if (fill(in) == 0) goto yyFillLabel2;
|
||||
goto yy2;
|
||||
}
|
||||
yy2:
|
||||
++in->cur;
|
||||
yy3:
|
||||
#line 56 "c/fill/01_fill.re"
|
||||
{ return -1; }
|
||||
#line 71 "c/fill/01_fill.c"
|
||||
yy4:
|
||||
++in->cur;
|
||||
yyFillLabel1:
|
||||
yych = *in->cur;
|
||||
yy6:
|
||||
++in.cur;
|
||||
yyFillLabel3:
|
||||
yych = *in.cur;
|
||||
yy7:
|
||||
switch (yych) {
|
||||
case ' ': goto yy4;
|
||||
default:
|
||||
if (in->lim <= in->cur) {
|
||||
if (fill(in) == 0) goto yyFillLabel1;
|
||||
case '\'': goto yy8;
|
||||
case '\\': goto yy9;
|
||||
default:
|
||||
if (in.lim <= in.cur) {
|
||||
if (fill(in) == 0) goto yyFillLabel3;
|
||||
goto yy11;
|
||||
}
|
||||
goto yy6;
|
||||
}
|
||||
yy8:
|
||||
++in.cur;
|
||||
#line 54 "c/fill/01_fill.re"
|
||||
{ ++count; continue; }
|
||||
#line 110 "c/fill/01_fill.c"
|
||||
yy9:
|
||||
++in.cur;
|
||||
yyFillLabel4:
|
||||
yych = *in.cur;
|
||||
if (yych <= 0x00) {
|
||||
if (in.lim <= in.cur) {
|
||||
if (fill(in) == 0) goto yyFillLabel4;
|
||||
goto yy11;
|
||||
}
|
||||
goto yy6;
|
||||
}
|
||||
yy6:
|
||||
#line 59 "c/fill/01_fill.re"
|
||||
{ goto loop; }
|
||||
#line 87 "c/fill/01_fill.c"
|
||||
yy7:
|
||||
in->mar = ++in->cur;
|
||||
yyFillLabel2:
|
||||
yych = *in->cur;
|
||||
if (yych >= 0x01) goto yy9;
|
||||
if (in->lim <= in->cur) {
|
||||
if (fill(in) == 0) goto yyFillLabel2;
|
||||
goto yy3;
|
||||
}
|
||||
yy8:
|
||||
++in->cur;
|
||||
yyFillLabel3:
|
||||
yych = *in->cur;
|
||||
yy9:
|
||||
switch (yych) {
|
||||
case '\'': goto yy10;
|
||||
case '\\': goto yy12;
|
||||
default:
|
||||
if (in->lim <= in->cur) {
|
||||
if (fill(in) == 0) goto yyFillLabel3;
|
||||
goto yy14;
|
||||
}
|
||||
goto yy8;
|
||||
}
|
||||
goto yy6;
|
||||
yy10:
|
||||
++in->cur;
|
||||
#line 58 "c/fill/01_fill.re"
|
||||
{ ++count; goto loop; }
|
||||
#line 116 "c/fill/01_fill.c"
|
||||
yy12:
|
||||
++in->cur;
|
||||
yyFillLabel4:
|
||||
yych = *in->cur;
|
||||
if (yych <= 0x00) {
|
||||
if (in->lim <= in->cur) {
|
||||
if (fill(in) == 0) goto yyFillLabel4;
|
||||
goto yy14;
|
||||
}
|
||||
goto yy8;
|
||||
}
|
||||
goto yy8;
|
||||
yy13:
|
||||
#line 57 "c/fill/01_fill.re"
|
||||
#line 53 "c/fill/01_fill.re"
|
||||
{ return count; }
|
||||
#line 132 "c/fill/01_fill.c"
|
||||
yy14:
|
||||
in->cur = in->mar;
|
||||
goto yy3;
|
||||
#line 126 "c/fill/01_fill.c"
|
||||
yy11:
|
||||
in.cur = in.mar;
|
||||
goto yy2;
|
||||
}
|
||||
#line 61 "c/fill/01_fill.re"
|
||||
#line 56 "c/fill/01_fill.re"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
const char *fname = "input";
|
||||
const char str[] = "'qu\0tes' 'are' 'fine: \\'' ";
|
||||
FILE *f;
|
||||
Input in;
|
||||
const char content[] = "'qu\0tes' 'are' 'fine: \\'' ";
|
||||
|
||||
// prepare input file: a few times the size of the buffer,
|
||||
// containing strings with zeroes and escaped quotes
|
||||
f = fopen(fname, "w");
|
||||
for (int i = 0; i < SIZE; ++i) {
|
||||
fwrite(str, 1, sizeof(str) - 1, f);
|
||||
// Prepare input file: a few times the size of the buffer, containing
|
||||
// strings with zeroes and escaped quotes.
|
||||
FILE *f = fopen(fname, "w");
|
||||
for (int i = 0; i < BUFSIZE; ++i) {
|
||||
fwrite(content, 1, sizeof(content) - 1, f);
|
||||
}
|
||||
fclose(f);
|
||||
int count = 3 * BUFSIZE; // number of quoted strings written to file
|
||||
|
||||
f = fopen(fname, "r");
|
||||
init(&in, f);
|
||||
assert(lex(&in) == SIZE * 3);
|
||||
fclose(f);
|
||||
// Initialize lexer state: all pointers are at the end of buffer.
|
||||
Input in;
|
||||
in.file = fopen(fname, "r");
|
||||
in.cur = in.mar = in.tok = in.lim = in.buf + BUFSIZE;
|
||||
in.eof = 0;
|
||||
// Sentinel (at YYLIMIT pointer) is set to zero, which triggers YYFILL.
|
||||
in.lim[0] = 0;
|
||||
|
||||
// Run the lexer.
|
||||
assert(lex(in) == count);
|
||||
|
||||
// Cleanup: remove input file.
|
||||
fclose(in.file);
|
||||
remove(fname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+62
-60
@@ -1,86 +1,88 @@
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SIZE 4096
|
||||
#define BUFSIZE 4095
|
||||
|
||||
typedef struct {
|
||||
struct Input {
|
||||
FILE *file;
|
||||
char buf[SIZE + 1], *lim, *cur, *mar, *tok;
|
||||
int eof;
|
||||
} Input;
|
||||
char buf[BUFSIZE + 1], *lim, *cur, *mar, *tok; // +1 for sentinel
|
||||
bool eof;
|
||||
};
|
||||
|
||||
static int fill(Input *in)
|
||||
{
|
||||
if (in->eof) {
|
||||
return 1;
|
||||
}
|
||||
const size_t free = in->tok - in->buf;
|
||||
if (free < 1) {
|
||||
return 2;
|
||||
}
|
||||
memmove(in->buf, in->tok, in->lim - in->tok);
|
||||
in->lim -= free;
|
||||
in->cur -= free;
|
||||
in->mar -= free;
|
||||
in->tok -= free;
|
||||
in->lim += fread(in->lim, 1, free, in->file);
|
||||
in->lim[0] = 0;
|
||||
in->eof |= in->lim < in->buf + SIZE;
|
||||
static int fill(Input &in) {
|
||||
if (in.eof) return 1;
|
||||
|
||||
const size_t shift = in.tok - in.buf;
|
||||
const size_t used = in.lim - in.tok;
|
||||
|
||||
// Error: lexeme too long. In real life could reallocate a larger buffer.
|
||||
if (shift < 1) return 2;
|
||||
|
||||
// Shift buffer contents (discard everything up to the current token).
|
||||
memmove(in.buf, in.tok, used);
|
||||
in.lim -= shift;
|
||||
in.cur -= shift;
|
||||
in.mar -= shift;
|
||||
in.tok -= shift;
|
||||
|
||||
// Fill free space at the end of buffer with new data from file.
|
||||
in.lim += fread(in.lim, 1, BUFSIZE - used, in.file);
|
||||
in.lim[0] = 0;
|
||||
in.eof = in.lim < in.buf + BUFSIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void init(Input *in, FILE *file)
|
||||
{
|
||||
in->file = file;
|
||||
in->cur = in->mar = in->tok = in->lim = in->buf + SIZE;
|
||||
in->eof = 0;
|
||||
fill(in);
|
||||
}
|
||||
|
||||
static int lex(Input *in)
|
||||
{
|
||||
static int lex(Input &in) {
|
||||
int count = 0;
|
||||
loop:
|
||||
in->tok = in->cur;
|
||||
for (;;) {
|
||||
in.tok = in.cur;
|
||||
/*!re2c
|
||||
re2c:eof = 0;
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYCURSOR = in->cur;
|
||||
re2c:define:YYMARKER = in->mar;
|
||||
re2c:define:YYLIMIT = in->lim;
|
||||
re2c:define:YYFILL = "fill(in) == 0";
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYCURSOR = in.cur;
|
||||
re2c:define:YYMARKER = in.mar;
|
||||
re2c:define:YYLIMIT = in.lim;
|
||||
re2c:define:YYFILL = "fill(in) == 0";
|
||||
re2c:eof = 0;
|
||||
|
||||
* { return -1; }
|
||||
$ { return count; }
|
||||
['] ([^'\\] | [\\][^])* ['] { ++count; goto loop; }
|
||||
[ ]+ { goto loop; }
|
||||
str = ['] ([^'\\] | [\\][^])* ['];
|
||||
|
||||
* { return -1; }
|
||||
$ { return count; }
|
||||
str { ++count; continue; }
|
||||
[ ]+ { continue; }
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
const char *fname = "input";
|
||||
const char str[] = "'qu\0tes' 'are' 'fine: \\'' ";
|
||||
FILE *f;
|
||||
Input in;
|
||||
const char content[] = "'qu\0tes' 'are' 'fine: \\'' ";
|
||||
|
||||
// prepare input file: a few times the size of the buffer,
|
||||
// containing strings with zeroes and escaped quotes
|
||||
f = fopen(fname, "w");
|
||||
for (int i = 0; i < SIZE; ++i) {
|
||||
fwrite(str, 1, sizeof(str) - 1, f);
|
||||
// Prepare input file: a few times the size of the buffer, containing
|
||||
// strings with zeroes and escaped quotes.
|
||||
FILE *f = fopen(fname, "w");
|
||||
for (int i = 0; i < BUFSIZE; ++i) {
|
||||
fwrite(content, 1, sizeof(content) - 1, f);
|
||||
}
|
||||
fclose(f);
|
||||
int count = 3 * BUFSIZE; // number of quoted strings written to file
|
||||
|
||||
f = fopen(fname, "r");
|
||||
init(&in, f);
|
||||
assert(lex(&in) == SIZE * 3);
|
||||
fclose(f);
|
||||
// Initialize lexer state: all pointers are at the end of buffer.
|
||||
Input in;
|
||||
in.file = fopen(fname, "r");
|
||||
in.cur = in.mar = in.tok = in.lim = in.buf + BUFSIZE;
|
||||
in.eof = 0;
|
||||
// Sentinel (at YYLIMIT pointer) is set to zero, which triggers YYFILL.
|
||||
in.lim[0] = 0;
|
||||
|
||||
// Run the lexer.
|
||||
assert(lex(in) == count);
|
||||
|
||||
// Cleanup: remove input file.
|
||||
fclose(in.file);
|
||||
remove(fname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+93
-88
@@ -1,6 +1,6 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "c/fill/02_fill.re"
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -9,128 +9,133 @@
|
||||
#define YYMAXFILL 1
|
||||
#line 6 "c/fill/02_fill.re"
|
||||
|
||||
#define SIZE 4096
|
||||
#define BUFSIZE (4096 - YYMAXFILL)
|
||||
|
||||
typedef struct {
|
||||
struct Input {
|
||||
FILE *file;
|
||||
char buf[SIZE + YYMAXFILL], *lim, *cur, *mar, *tok;
|
||||
int eof;
|
||||
} Input;
|
||||
char buf[BUFSIZE + YYMAXFILL], *lim, *cur, *tok;
|
||||
bool eof;
|
||||
};
|
||||
|
||||
static int fill(Input *in, size_t need)
|
||||
{
|
||||
if (in->eof) {
|
||||
return 1;
|
||||
}
|
||||
const size_t free = in->tok - in->buf;
|
||||
if (free < need) {
|
||||
return 2;
|
||||
}
|
||||
memmove(in->buf, in->tok, in->lim - in->tok);
|
||||
in->lim -= free;
|
||||
in->cur -= free;
|
||||
in->mar -= free;
|
||||
in->tok -= free;
|
||||
in->lim += fread(in->lim, 1, free, in->file);
|
||||
if (in->lim < in->buf + SIZE) {
|
||||
in->eof = 1;
|
||||
memset(in->lim, 0, YYMAXFILL);
|
||||
in->lim += YYMAXFILL;
|
||||
static int fill(Input &in, size_t need) {
|
||||
if (in.eof) return 1;
|
||||
|
||||
const size_t shift = in.tok - in.buf;
|
||||
const size_t used = in.lim - in.tok;
|
||||
|
||||
// Error: lexeme too long. In real life could reallocate a larger buffer.
|
||||
if (shift < need) return 2;
|
||||
|
||||
// Shift buffer contents (discard everything up to the current token).
|
||||
memmove(in.buf, in.tok, used);
|
||||
in.lim -= shift;
|
||||
in.cur -= shift;
|
||||
in.tok -= shift;
|
||||
|
||||
// Fill free space at the end of buffer with new data from file.
|
||||
in.lim += fread(in.lim, 1, BUFSIZE - used, in.file);
|
||||
|
||||
// If read less than expected, this is end of input => add zero padding
|
||||
// so that the lexer can access characters at the end of buffer.
|
||||
if (in.lim < in.buf + BUFSIZE) {
|
||||
in.eof = true;
|
||||
memset(in.lim, 0, YYMAXFILL);
|
||||
in.lim += YYMAXFILL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void init(Input *in, FILE *file)
|
||||
{
|
||||
in->file = file;
|
||||
in->cur = in->mar = in->tok = in->lim = in->buf + SIZE;
|
||||
in->eof = 0;
|
||||
fill(in, 1);
|
||||
}
|
||||
|
||||
static int lex(Input *in)
|
||||
{
|
||||
static int lex(Input &in) {
|
||||
int count = 0;
|
||||
loop:
|
||||
in->tok = in->cur;
|
||||
for (;;) {
|
||||
in.tok = in.cur;
|
||||
|
||||
#line 58 "c/fill/02_fill.c"
|
||||
#line 55 "c/fill/02_fill.c"
|
||||
{
|
||||
char yych;
|
||||
if (in->lim <= in->cur) if (fill(in, 1) != 0) return -1;
|
||||
yych = *in->cur;
|
||||
if (in.lim <= in.cur) if (fill(in, 1) != 0) return -1;
|
||||
yych = *in.cur;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy2;
|
||||
case ' ': goto yy6;
|
||||
case '\'': goto yy9;
|
||||
default: goto yy4;
|
||||
case 0x00: goto yy1;
|
||||
case ' ': goto yy3;
|
||||
case '\'': goto yy5;
|
||||
default: goto yy2;
|
||||
}
|
||||
yy2:
|
||||
++in->cur;
|
||||
#line 60 "c/fill/02_fill.re"
|
||||
{ return (in->lim - in->cur == YYMAXFILL - 1) ? count : -1; }
|
||||
yy1:
|
||||
++in.cur;
|
||||
#line 57 "c/fill/02_fill.re"
|
||||
{
|
||||
// Check that it is the sentinel, not some unexpected null.
|
||||
return in.tok == in.lim - YYMAXFILL ? count : -1;
|
||||
}
|
||||
#line 73 "c/fill/02_fill.c"
|
||||
yy4:
|
||||
++in->cur;
|
||||
#line 59 "c/fill/02_fill.re"
|
||||
yy2:
|
||||
++in.cur;
|
||||
#line 63 "c/fill/02_fill.re"
|
||||
{ return -1; }
|
||||
#line 78 "c/fill/02_fill.c"
|
||||
yy6:
|
||||
++in->cur;
|
||||
if (in->lim <= in->cur) if (fill(in, 1) != 0) return -1;
|
||||
yych = *in->cur;
|
||||
yy3:
|
||||
++in.cur;
|
||||
if (in.lim <= in.cur) if (fill(in, 1) != 0) return -1;
|
||||
yych = *in.cur;
|
||||
switch (yych) {
|
||||
case ' ': goto yy6;
|
||||
default: goto yy8;
|
||||
case ' ': goto yy3;
|
||||
default: goto yy4;
|
||||
}
|
||||
yy8:
|
||||
yy4:
|
||||
#line 62 "c/fill/02_fill.re"
|
||||
{ goto loop; }
|
||||
{ continue; }
|
||||
#line 90 "c/fill/02_fill.c"
|
||||
yy9:
|
||||
++in->cur;
|
||||
if (in->lim <= in->cur) if (fill(in, 1) != 0) return -1;
|
||||
yych = *in->cur;
|
||||
yy5:
|
||||
++in.cur;
|
||||
if (in.lim <= in.cur) if (fill(in, 1) != 0) return -1;
|
||||
yych = *in.cur;
|
||||
switch (yych) {
|
||||
case '\'': goto yy11;
|
||||
case '\\': goto yy13;
|
||||
default: goto yy9;
|
||||
case '\'': goto yy6;
|
||||
case '\\': goto yy7;
|
||||
default: goto yy5;
|
||||
}
|
||||
yy11:
|
||||
++in->cur;
|
||||
yy6:
|
||||
++in.cur;
|
||||
#line 61 "c/fill/02_fill.re"
|
||||
{ ++count; goto loop; }
|
||||
{ ++count; continue; }
|
||||
#line 104 "c/fill/02_fill.c"
|
||||
yy13:
|
||||
++in->cur;
|
||||
if (in->lim <= in->cur) if (fill(in, 1) != 0) return -1;
|
||||
yych = *in->cur;
|
||||
goto yy9;
|
||||
yy7:
|
||||
++in.cur;
|
||||
if (in.lim <= in.cur) if (fill(in, 1) != 0) return -1;
|
||||
goto yy5;
|
||||
}
|
||||
#line 64 "c/fill/02_fill.re"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
const char *fname = "input";
|
||||
const char str[] = "'qu\0tes' 'are' 'fine: \\'' ";
|
||||
FILE *f;
|
||||
Input in;
|
||||
const char content[] = "'qu\0tes' 'are' 'fine: \\'' ";
|
||||
|
||||
// prepare input file: a few times the size of the buffer,
|
||||
// containing strings with zeroes and escaped quotes
|
||||
f = fopen(fname, "w");
|
||||
for (int i = 0; i < SIZE; ++i) {
|
||||
fwrite(str, 1, sizeof(str) - 1, f);
|
||||
// Prepare input file: a few times the size of the buffer, containing
|
||||
// strings with zeroes and escaped quotes.
|
||||
FILE *f = fopen(fname, "w");
|
||||
for (int i = 0; i < BUFSIZE; ++i) {
|
||||
fwrite(content, 1, sizeof(content) - 1, f);
|
||||
}
|
||||
fclose(f);
|
||||
int count = 3 * BUFSIZE; // number of quoted strings written to file
|
||||
|
||||
f = fopen(fname, "r");
|
||||
init(&in, f);
|
||||
assert(lex(&in) == SIZE * 3);
|
||||
fclose(f);
|
||||
// Initialize lexer state: all pointers are at the end of buffer.
|
||||
// This immediately triggers YYFILL, as the check `in.cur < in.lim` fails.
|
||||
Input in;
|
||||
in.file = fopen(fname, "r");
|
||||
in.cur = in.tok = in.lim = in.buf + BUFSIZE;
|
||||
in.eof = 0;
|
||||
|
||||
// Run the lexer.
|
||||
assert(lex(in) == count);
|
||||
|
||||
// Cleanup: remove input file.
|
||||
fclose(in.file);
|
||||
remove(fname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+67
-61
@@ -1,89 +1,95 @@
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*!max:re2c*/
|
||||
#define SIZE 4096
|
||||
#define BUFSIZE (4096 - YYMAXFILL)
|
||||
|
||||
typedef struct {
|
||||
struct Input {
|
||||
FILE *file;
|
||||
char buf[SIZE + YYMAXFILL], *lim, *cur, *mar, *tok;
|
||||
int eof;
|
||||
} Input;
|
||||
char buf[BUFSIZE + YYMAXFILL], *lim, *cur, *tok;
|
||||
bool eof;
|
||||
};
|
||||
|
||||
static int fill(Input *in, size_t need)
|
||||
{
|
||||
if (in->eof) {
|
||||
return 1;
|
||||
}
|
||||
const size_t free = in->tok - in->buf;
|
||||
if (free < need) {
|
||||
return 2;
|
||||
}
|
||||
memmove(in->buf, in->tok, in->lim - in->tok);
|
||||
in->lim -= free;
|
||||
in->cur -= free;
|
||||
in->mar -= free;
|
||||
in->tok -= free;
|
||||
in->lim += fread(in->lim, 1, free, in->file);
|
||||
if (in->lim < in->buf + SIZE) {
|
||||
in->eof = 1;
|
||||
memset(in->lim, 0, YYMAXFILL);
|
||||
in->lim += YYMAXFILL;
|
||||
static int fill(Input &in, size_t need) {
|
||||
if (in.eof) return 1;
|
||||
|
||||
const size_t shift = in.tok - in.buf;
|
||||
const size_t used = in.lim - in.tok;
|
||||
|
||||
// Error: lexeme too long. In real life could reallocate a larger buffer.
|
||||
if (shift < need) return 2;
|
||||
|
||||
// Shift buffer contents (discard everything up to the current token).
|
||||
memmove(in.buf, in.tok, used);
|
||||
in.lim -= shift;
|
||||
in.cur -= shift;
|
||||
in.tok -= shift;
|
||||
|
||||
// Fill free space at the end of buffer with new data from file.
|
||||
in.lim += fread(in.lim, 1, BUFSIZE - used, in.file);
|
||||
|
||||
// If read less than expected, this is end of input => add zero padding
|
||||
// so that the lexer can access characters at the end of buffer.
|
||||
if (in.lim < in.buf + BUFSIZE) {
|
||||
in.eof = true;
|
||||
memset(in.lim, 0, YYMAXFILL);
|
||||
in.lim += YYMAXFILL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void init(Input *in, FILE *file)
|
||||
{
|
||||
in->file = file;
|
||||
in->cur = in->mar = in->tok = in->lim = in->buf + SIZE;
|
||||
in->eof = 0;
|
||||
fill(in, 1);
|
||||
}
|
||||
|
||||
static int lex(Input *in)
|
||||
{
|
||||
static int lex(Input &in) {
|
||||
int count = 0;
|
||||
loop:
|
||||
in->tok = in->cur;
|
||||
for (;;) {
|
||||
in.tok = in.cur;
|
||||
/*!re2c
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYCURSOR = in->cur;
|
||||
re2c:define:YYMARKER = in->mar;
|
||||
re2c:define:YYLIMIT = in->lim;
|
||||
re2c:define:YYFILL = "if (fill(in, @@) != 0) return -1;";
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYCURSOR = in.cur;
|
||||
re2c:define:YYLIMIT = in.lim;
|
||||
re2c:define:YYFILL = "if (fill(in, @@) != 0) return -1;";
|
||||
|
||||
* { return -1; }
|
||||
[\x00] { return (in->lim - in->cur == YYMAXFILL - 1) ? count : -1; }
|
||||
['] ([^'\\] | [\\][^])* ['] { ++count; goto loop; }
|
||||
[ ]+ { goto loop; }
|
||||
str = ['] ([^'\\] | [\\][^])* ['];
|
||||
|
||||
[\x00] {
|
||||
// Check that it is the sentinel, not some unexpected null.
|
||||
return in.tok == in.lim - YYMAXFILL ? count : -1;
|
||||
}
|
||||
str { ++count; continue; }
|
||||
[ ]+ { continue; }
|
||||
* { return -1; }
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
const char *fname = "input";
|
||||
const char str[] = "'qu\0tes' 'are' 'fine: \\'' ";
|
||||
FILE *f;
|
||||
Input in;
|
||||
const char content[] = "'qu\0tes' 'are' 'fine: \\'' ";
|
||||
|
||||
// prepare input file: a few times the size of the buffer,
|
||||
// containing strings with zeroes and escaped quotes
|
||||
f = fopen(fname, "w");
|
||||
for (int i = 0; i < SIZE; ++i) {
|
||||
fwrite(str, 1, sizeof(str) - 1, f);
|
||||
// Prepare input file: a few times the size of the buffer, containing
|
||||
// strings with zeroes and escaped quotes.
|
||||
FILE *f = fopen(fname, "w");
|
||||
for (int i = 0; i < BUFSIZE; ++i) {
|
||||
fwrite(content, 1, sizeof(content) - 1, f);
|
||||
}
|
||||
fclose(f);
|
||||
int count = 3 * BUFSIZE; // number of quoted strings written to file
|
||||
|
||||
f = fopen(fname, "r");
|
||||
init(&in, f);
|
||||
assert(lex(&in) == SIZE * 3);
|
||||
fclose(f);
|
||||
// Initialize lexer state: all pointers are at the end of buffer.
|
||||
// This immediately triggers YYFILL, as the check `in.cur < in.lim` fails.
|
||||
Input in;
|
||||
in.file = fopen(fname, "r");
|
||||
in.cur = in.tok = in.lim = in.buf + BUFSIZE;
|
||||
in.eof = 0;
|
||||
|
||||
// Run the lexer.
|
||||
assert(lex(in) == count);
|
||||
|
||||
// Cleanup: remove input file.
|
||||
fclose(in.file);
|
||||
remove(fname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,49 +1,48 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "c/generic_api/ifstream.re"
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
static void convert_newlines(std::ifstream &in, std::ostringstream &out)
|
||||
{
|
||||
static void convert_newlines(std::ifstream &in, std::ostringstream &out) {
|
||||
std::streampos mar;
|
||||
loop:
|
||||
for (;;) {
|
||||
|
||||
#line 15 "c/generic_api/ifstream.c"
|
||||
#line 14 "c/generic_api/ifstream.c"
|
||||
{
|
||||
char yych;
|
||||
yych = in.peek();
|
||||
switch (yych) {
|
||||
case '\r': goto yy4;
|
||||
default: goto yy2;
|
||||
case '\r': goto yy3;
|
||||
default: goto yy1;
|
||||
}
|
||||
yy1:
|
||||
{ in.ignore(); if (in.eof()) return; }
|
||||
yy2:
|
||||
do { in.ignore(); if (in.eof()) return; } while(0);
|
||||
#line 20 "c/generic_api/ifstream.re"
|
||||
{ out.put(yych); continue; }
|
||||
#line 27 "c/generic_api/ifstream.c"
|
||||
yy3:
|
||||
#line 21 "c/generic_api/ifstream.re"
|
||||
{ out.put(yych); goto loop; }
|
||||
#line 28 "c/generic_api/ifstream.c"
|
||||
yy4:
|
||||
do { in.ignore(); if (in.eof()) return; } while(0);
|
||||
{ in.ignore(); if (in.eof()) return; }
|
||||
yych = in.peek();
|
||||
switch (yych) {
|
||||
case '\n': goto yy5;
|
||||
default: goto yy3;
|
||||
case '\n': goto yy4;
|
||||
default: goto yy2;
|
||||
}
|
||||
yy5:
|
||||
do { in.ignore(); if (in.eof()) return; } while(0);
|
||||
yy4:
|
||||
{ in.ignore(); if (in.eof()) return; }
|
||||
#line 21 "c/generic_api/ifstream.re"
|
||||
{ out.put('\n'); continue; }
|
||||
#line 39 "c/generic_api/ifstream.c"
|
||||
}
|
||||
#line 22 "c/generic_api/ifstream.re"
|
||||
{ out.put('\n'); goto loop; }
|
||||
#line 40 "c/generic_api/ifstream.c"
|
||||
}
|
||||
#line 23 "c/generic_api/ifstream.re"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
const char *fname = "input";
|
||||
const char s1[] = "Text\r\nwith\r\nnewlines.\r\n\r\n";
|
||||
const char s2[] = "Text\nwith\nnewlines.\n\n";
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
// re2c $INPUT -o $OUTPUT
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
static void convert_newlines(std::ifstream &in, std::ostringstream &out)
|
||||
{
|
||||
static void convert_newlines(std::ifstream &in, std::ostringstream &out) {
|
||||
std::streampos mar;
|
||||
loop:
|
||||
for (;;) {
|
||||
/*!re2c
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:flags:input = custom;
|
||||
re2c:api= custom;
|
||||
re2c:api:style = free-form;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYPEEK = "in.peek()";
|
||||
re2c:define:YYSKIP = "do { in.ignore(); if (in.eof()) return; } while(0);";
|
||||
re2c:define:YYSKIP = "{ in.ignore(); if (in.eof()) return; }";
|
||||
re2c:define:YYBACKUP = "mar = in.tellg();";
|
||||
re2c:define:YYRESTORE = "in.seekg(mar);";
|
||||
re2c:yyfill:enable = 0;
|
||||
|
||||
* { out.put(yych); goto loop; }
|
||||
"\r\n" { out.put('\n'); goto loop; }
|
||||
* { out.put(yych); continue; }
|
||||
"\r\n" { out.put('\n'); continue; }
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
const char *fname = "input";
|
||||
const char s1[] = "Text\r\nwith\r\nnewlines.\r\n\r\n";
|
||||
const char s2[] = "Text\nwith\nnewlines.\n\n";
|
||||
|
||||
+31
-88
@@ -1,110 +1,53 @@
|
||||
/* Generated by re2c */
|
||||
// re2c $INPUT -o $OUTPUT -i --type-header src/lexer/lexer.h
|
||||
// re2c $INPUT -o $OUTPUT -i --header lexer/state.h
|
||||
#include <assert.h>
|
||||
#include "src/lexer/lexer.h" // generated by re2c
|
||||
#include <stddef.h>
|
||||
#include "lexer/state.h" // the header is generated by re2c
|
||||
|
||||
|
||||
|
||||
int lex(LexerState *st)
|
||||
{
|
||||
long lex(LexerState& st) {
|
||||
const char *t;
|
||||
|
||||
{
|
||||
char yych;
|
||||
yych = *st->cur;
|
||||
goto yy0;
|
||||
yy1:
|
||||
++st.cur;
|
||||
yy0:
|
||||
yych = *st.cur;
|
||||
switch (yych) {
|
||||
case 'x': goto yy4;
|
||||
default: goto yy2;
|
||||
case 'a': goto yy1;
|
||||
case 'b':
|
||||
st.yyt1 = st.cur;
|
||||
goto yy3;
|
||||
default:
|
||||
st.yyt1 = st.cur;
|
||||
goto yy2;
|
||||
}
|
||||
yy2:
|
||||
++st->cur;
|
||||
t = st.yyt1;
|
||||
{ return t - st.str; }
|
||||
yy3:
|
||||
{ return 1; }
|
||||
yy4:
|
||||
yych = *(st->mar = ++st->cur);
|
||||
yych = *++st.cur;
|
||||
switch (yych) {
|
||||
case 'x':
|
||||
st->yyt1 = st->cur;
|
||||
goto yy5;
|
||||
default: goto yy3;
|
||||
case 'b': goto yy3;
|
||||
default: goto yy2;
|
||||
}
|
||||
yy5:
|
||||
yych = *++st->cur;
|
||||
switch (yych) {
|
||||
case 'x':
|
||||
st->yyt2 = st->cur;
|
||||
goto yy7;
|
||||
default: goto yy6;
|
||||
}
|
||||
yy6:
|
||||
st->cur = st->mar;
|
||||
goto yy3;
|
||||
yy7:
|
||||
yych = *++st->cur;
|
||||
switch (yych) {
|
||||
case 'x':
|
||||
st->yyt3 = st->cur;
|
||||
goto yy8;
|
||||
default: goto yy6;
|
||||
}
|
||||
yy8:
|
||||
yych = *++st->cur;
|
||||
switch (yych) {
|
||||
case 'x':
|
||||
st->yyt1 = st->cur;
|
||||
goto yy10;
|
||||
default: goto yy9;
|
||||
}
|
||||
yy9:
|
||||
st->cur = st->yyt1;
|
||||
{ return 0; }
|
||||
yy10:
|
||||
yych = *++st->cur;
|
||||
switch (yych) {
|
||||
case 'x': goto yy11;
|
||||
default:
|
||||
st->yyt1 = st->yyt2;
|
||||
goto yy9;
|
||||
}
|
||||
yy11:
|
||||
yych = *++st->cur;
|
||||
switch (yych) {
|
||||
case 'x': goto yy12;
|
||||
default:
|
||||
st->yyt1 = st->yyt3;
|
||||
goto yy9;
|
||||
}
|
||||
yy12:
|
||||
yych = *++st->cur;
|
||||
switch (yych) {
|
||||
case 'x': goto yy13;
|
||||
default: goto yy9;
|
||||
}
|
||||
yy13:
|
||||
yych = *++st->cur;
|
||||
switch (yych) {
|
||||
case 'x': goto yy14;
|
||||
default: goto yy9;
|
||||
}
|
||||
yy14:
|
||||
++st->cur;
|
||||
goto yy9;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
LexerState st;
|
||||
st.str = st.cur = "xxxxxxxx";
|
||||
assert(lex(&st) == 0 && st.cur - st.str == 4);
|
||||
int main() {
|
||||
const char *s = "ab";
|
||||
LexerState st = { s, s , NULL };
|
||||
assert(lex(st) == 1);
|
||||
return 0;
|
||||
}
|
||||
/* Generated by re2c */
|
||||
|
||||
|
||||
typedef struct {
|
||||
const char *str, *cur, *mar;
|
||||
const char *yyt1; const char *yyt2; const char *yyt3;
|
||||
} LexerState;
|
||||
|
||||
c/headers/header.re:25:24: warning: trailing context has 4th degree of nondeterminism [-Wnondeterministic-tags]
|
||||
struct LexerState {
|
||||
const char *str, *cur;
|
||||
const char *yyt1;
|
||||
};
|
||||
c/headers/header.re:23:21: warning: rule matches empty string [-Wmatch-empty-string]
|
||||
|
||||
@@ -1,36 +1,32 @@
|
||||
// re2c $INPUT -o $OUTPUT -i --type-header src/lexer/lexer.h
|
||||
// re2c $INPUT -o $OUTPUT -i --header lexer/state.h
|
||||
#include <assert.h>
|
||||
#include "src/lexer/lexer.h" // generated by re2c
|
||||
#include <stddef.h>
|
||||
#include "lexer/state.h" // the header is generated by re2c
|
||||
|
||||
/*!header:re2c:on*/
|
||||
|
||||
typedef struct {
|
||||
const char *str, *cur, *mar;
|
||||
/*!stags:re2c format = "const char *@@{tag}; "; */
|
||||
} LexerState;
|
||||
|
||||
struct LexerState {
|
||||
const char *str, *cur;
|
||||
/*!stags:re2c format = "const char *@@;"; */
|
||||
};
|
||||
/*!header:re2c:off*/
|
||||
|
||||
int lex(LexerState *st)
|
||||
{
|
||||
long lex(LexerState& st) {
|
||||
const char *t;
|
||||
/*!re2c
|
||||
re2c:flags:type-header = "src/lexer/lexer.h";
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:flags:tags = 1;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYCURSOR = "st->cur";
|
||||
re2c:define:YYMARKER = "st->mar";
|
||||
re2c:tags:expression = "st->@@{tag}";
|
||||
re2c:header = "lexer/state.h";
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:define:YYCURSOR = "st.cur";
|
||||
re2c:tags = 1;
|
||||
re2c:tags:expression = "st.@@";
|
||||
|
||||
[x]{1,4} / [x]{3,5} { return 0; } // ambiguous trailing context
|
||||
* { return 1; }
|
||||
[a]* @t [b]* { return t - st.str; }
|
||||
*/
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
LexerState st;
|
||||
st.str = st.cur = "xxxxxxxx";
|
||||
assert(lex(&st) == 0 && st.cur - st.str == 4);
|
||||
int main() {
|
||||
const char *s = "ab";
|
||||
LexerState st = { s, s /*!stags:re2c format = ", NULL"; */ };
|
||||
assert(lex(st) == 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
|
||||
typedef struct {
|
||||
const char *str, *cur, *mar;
|
||||
const char *yyt1; const char *yyt2; const char *yyt3;
|
||||
const char *yyt1;
|
||||
} LexerState;
|
||||
|
||||
+140
-145
@@ -6,188 +6,183 @@ typedef enum { OK, FAIL } Result;
|
||||
|
||||
|
||||
|
||||
Result lex(const char *YYCURSOR)
|
||||
{
|
||||
const char *YYMARKER;
|
||||
Result lex(const char *s) {
|
||||
const char *YYCURSOR = s, *YYMARKER;
|
||||
|
||||
{
|
||||
char yych;
|
||||
unsigned int yyaccept = 0;
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case '.': goto yy4;
|
||||
case '0': goto yy5;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy6;
|
||||
default: goto yy2;
|
||||
case '.': goto yy3;
|
||||
case '0': goto yy4;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy5;
|
||||
default: goto yy1;
|
||||
}
|
||||
yy2:
|
||||
yy1:
|
||||
++YYCURSOR;
|
||||
yy3:
|
||||
yy2:
|
||||
{ return FAIL; }
|
||||
yy4:
|
||||
yy3:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy9;
|
||||
default: goto yy3;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy7;
|
||||
default: goto yy2;
|
||||
}
|
||||
yy5:
|
||||
yy4:
|
||||
yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
switch (yych) {
|
||||
case '.': goto yy9;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy12;
|
||||
case 'E':
|
||||
case 'e': goto yy15;
|
||||
default: goto yy3;
|
||||
case '.': goto yy7;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy9;
|
||||
case 'E':
|
||||
case 'e': goto yy11;
|
||||
default: goto yy2;
|
||||
}
|
||||
yy6:
|
||||
yy5:
|
||||
yyaccept = 1;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
switch (yych) {
|
||||
case '.': goto yy9;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy6;
|
||||
case 'E':
|
||||
case 'e': goto yy15;
|
||||
default: goto yy8;
|
||||
case '.': goto yy7;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy5;
|
||||
case 'E':
|
||||
case 'e': goto yy11;
|
||||
default: goto yy6;
|
||||
}
|
||||
yy6:
|
||||
{ return OK; }
|
||||
yy7:
|
||||
yyaccept = 2;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy7;
|
||||
case 'E':
|
||||
case 'e': goto yy11;
|
||||
default: goto yy8;
|
||||
}
|
||||
yy8:
|
||||
{ return OK; }
|
||||
yy9:
|
||||
yyaccept = 2;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy9;
|
||||
case 'E':
|
||||
case 'e': goto yy15;
|
||||
default: goto yy11;
|
||||
case '.': goto yy7;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy9;
|
||||
case 'E':
|
||||
case 'e': goto yy11;
|
||||
default: goto yy10;
|
||||
}
|
||||
yy10:
|
||||
YYCURSOR = YYMARKER;
|
||||
switch (yyaccept) {
|
||||
case 0: goto yy2;
|
||||
case 1: goto yy6;
|
||||
default: goto yy8;
|
||||
}
|
||||
yy11:
|
||||
{ return OK; }
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case '+':
|
||||
case '-': goto yy12;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy13;
|
||||
default: goto yy10;
|
||||
}
|
||||
yy12:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case '.': goto yy9;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy12;
|
||||
case 'E':
|
||||
case 'e': goto yy15;
|
||||
default: goto yy14;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy13;
|
||||
default: goto yy10;
|
||||
}
|
||||
yy14:
|
||||
YYCURSOR = YYMARKER;
|
||||
switch (yyaccept) {
|
||||
case 0:
|
||||
goto yy3;
|
||||
case 1:
|
||||
goto yy8;
|
||||
default:
|
||||
goto yy11;
|
||||
}
|
||||
yy15:
|
||||
yy13:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case '+':
|
||||
case '-': goto yy16;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy17;
|
||||
default: goto yy14;
|
||||
}
|
||||
yy16:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy17;
|
||||
default: goto yy14;
|
||||
}
|
||||
yy17:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy17;
|
||||
default: goto yy11;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy13;
|
||||
default: goto yy8;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
assert(lex("123") == OK);
|
||||
assert(lex("123.4567") == OK);
|
||||
return 0;
|
||||
|
||||
@@ -2,21 +2,19 @@
|
||||
#include <assert.h>
|
||||
/*!include:re2c "definitions.h" */
|
||||
|
||||
Result lex(const char *YYCURSOR)
|
||||
{
|
||||
const char *YYMARKER;
|
||||
Result lex(const char *s) {
|
||||
const char *YYCURSOR = s, *YYMARKER;
|
||||
/*!re2c
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:define:YYCTYPE = char;
|
||||
re2c:yyfill:enable = 0;
|
||||
|
||||
number { return OK; }
|
||||
!include "extra_rules.re.inc";
|
||||
* { return FAIL; }
|
||||
* { return FAIL; }
|
||||
number { return OK; }
|
||||
!include "extra_rules.re.inc";
|
||||
*/
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
assert(lex("123") == OK);
|
||||
assert(lex("123.4567") == OK);
|
||||
return 0;
|
||||
|
||||
+6754
-6759
File diff suppressed because it is too large
Load Diff
@@ -103,10 +103,10 @@ static bool lex_str(input_t &in, unsigned char q)
|
||||
for (unsigned long u = q;; fprintf(stderr, "\\x%lx", u)) {
|
||||
in.tok = in.cur;
|
||||
/*!re2c
|
||||
re2c:yyfill:enable = 1;
|
||||
re2c:define:YYCURSOR = in.cur;
|
||||
re2c:define:YYMARKER = in.mar;
|
||||
re2c:define:YYLIMIT = in.lim;
|
||||
re2c:yyfill:enable = 1;
|
||||
re2c:define:YYFILL = "if (!in.fill(@@)) return false;";
|
||||
re2c:define:YYFILL:naked = 1;
|
||||
* { return false; }
|
||||
@@ -179,10 +179,10 @@ static bool lex(input_t &in)
|
||||
for (;;) {
|
||||
in.tok = in.cur;
|
||||
/*!re2c
|
||||
re2c:yyfill:enable = 1;
|
||||
re2c:define:YYCURSOR = in.cur;
|
||||
re2c:define:YYMARKER = in.mar;
|
||||
re2c:define:YYLIMIT = in.lim;
|
||||
re2c:yyfill:enable = 1;
|
||||
re2c:define:YYFILL = "if (!in.fill(@@)) return false;";
|
||||
re2c:define:YYFILL:naked = 1;
|
||||
|
||||
|
||||
+669
-671
File diff suppressed because it is too large
Load Diff
@@ -43,7 +43,7 @@ struct out_t {
|
||||
/*!rules:re2c
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:api:style = free-form;
|
||||
re2c:flags:8 = 1;
|
||||
re2c:encoding:utf8 = 1;
|
||||
re2c:define:YYGETCONDITION = "c";
|
||||
re2c:define:YYSETCONDITION = "c = @@;";
|
||||
|
||||
@@ -136,7 +136,7 @@ static void lex_utf8(const iutf8_t & in)
|
||||
out_t out;
|
||||
/*!use:re2c
|
||||
re2c:define:YYCTYPE = "unsigned char";
|
||||
re2c:flags:8 = 1;
|
||||
re2c:encoding:utf8 = 1;
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ static void lex_utf16(const iutf16_t & in)
|
||||
out_t out;
|
||||
/*!use:re2c
|
||||
re2c:define:YYCTYPE = "unsigned int";
|
||||
re2c:flags:x = 1;
|
||||
re2c:encoding:utf16 = 1;
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ static void lex_utf32(const iutf32_t & in)
|
||||
out_t out;
|
||||
/*!use:re2c
|
||||
re2c:define:YYCTYPE = "unsigned int";
|
||||
re2c:flags:u = 1;
|
||||
re2c:encoding:utf32 = 1;
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ static void lex_ucs2(const iucs2_t & in)
|
||||
out_t out;
|
||||
/*!use:re2c
|
||||
re2c:define:YYCTYPE = "unsigned int";
|
||||
re2c:flags:w = 1;
|
||||
re2c:encoding:ucs2 = 1;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user