Compare commits

...
137 Commits
Author SHA1 Message Date
Ulya Trofimovich 3a7c3fedf2 Release 3.0. 2022-01-27 08:41:08 +00:00
Ulya Trofimovich e6cd3eaaec Update CHANGELOG. 2022-01-24 23:11:59 +00:00
Ulya Trofimovich f18ce1b7d3 Update README.md and BUILD.md. 2022-01-24 07:38:02 +00:00
Ulya Trofimovich f8ea4ea47d Fix the build on FreeBSD.
The build was broken by https://github.com/skvadrik/re2c/pull/376, which
added define of _POSIX_SOURCE to unbreak the build on Cygwin. The build
on FreeBSD is fixed by additionally defining _POSIX_C_SOURCE, which is
required by fdopen.
2022-01-23 19:40:18 +00:00
Ulya Trofimovich e262466260 Adjust build script for non-multilib environments.
Instead of passing compiler and linker option -m32, call 32-bit compiler
binaries directly (prefixed with "i686-pc-linux-gnu-"). This allows one
to run the script on NixOS where it's hard to get a system-wide multilib
environment.
2022-01-23 10:48:49 +00:00
Ulya Trofimovich 85dab53916 Add missing header include. 2022-01-23 10:23:40 +00:00
Ulya Trofimovich 38a07a3304 Rust backend: add example of a C lexer contributed by Perry Metzger. 2022-01-22 20:51:56 +00:00
Ulya Trofimovich 039c189491 Emit an error when repetition lower bound exceeds upper bound.
Historically this was allowed and re2c swapped the bounds. However, it
most likely indicates an error in user code and there is only a single
occurrence in the tests (and the test in an artificial one), so although
the change is backwards incompatible there is low chance of breaking
real-world code.

This fixes second test case in the bug #394 "Stack overflow due to
recursion in src/dfa/dead_rules.cc" (the actual fix is to limit DFA size
but the test also has counted repetition with swapped bounds).
2022-01-21 23:30:04 +00:00
Ulya Trofimovich a3473fd7be Limit maximum allowed NFA and DFA size.
Instead of failing with an out of memory exception or crashing with a
stack overflow, emit an error message and exit. This is a partial fix
for bug #394 "Stack overflow due to recursion in src/dfa/dead_rules.cc",
where re2c hit stack overflow on a counted repetition regexp with high
upper bound.

The patch adds the following limits:
  1. the number of NFA states
  2. NFA depth (maximum length of a non-looping path from start to end)
  3. the number of DFA states
  3. total DFA size (sum total of all NFA substates in all DFA states)

There are tests for the first three limits, but not for the DFA size as
all examples that trigger this behavior take a long time to finish (a
few seconds), which increases test run time almost twice.
2022-01-21 21:58:20 +00:00
Ulya Trofimovich aa02264d2f More documentation updates (rewrote parts of different sections). 2022-01-20 08:23:09 +00:00
Ulya Trofimovich d9f431c9bd Small fixes in a few more examples.
- Add `assert` to the basic C example (to clarify the intent).
- Change `types:re2c` to its new alias `conditions:re2c`.
2022-01-19 07:38:06 +00:00
Ulya Trofimovich f3016baacb Restructure a few initial sections in the manual. 2022-01-15 20:10:02 +00:00
Ulya Trofimovich 638c1db7fc Update docs following recent example changes. 2022-01-15 19:06:24 +00:00
Ulya Trofimovich 37cfc0b63f Rust backend: add a test for function-like API.
Function-like API is difficult to use in Rust, because API primitives
cannot be defined as functions or hygienic macros (they do not accept
all the necessary parameters), and closures are problematic due to the
borrow checker (in this test `Cell` is used as a workaround).
2022-01-15 09:28:35 +00:00
Ulya Trofimovich c01efa343a Unify the basic example across language backends. 2022-01-15 09:26:22 +00:00
Ulya Trofimovich 4dc0a787ee Examples: avoid explicit YYFILL call when initializing lexer state.
Instead, add more comments explaining how the lexer state is initialized
and why YYFILL is triggered automatically.
2022-01-15 09:08:05 +00:00
Ulya Trofimovich 9054e09967 Docs: update configuration description. 2022-01-14 22:21:22 +00:00
Ulya Trofimovich ff18b2b5b4 Docs: describe new options and new aliases for old options. 2022-01-13 07:28:14 +00:00
Ulya Trofimovich 769ecc83c7 Docs: add initial documentation for Rust. 2022-01-12 08:52:37 +00:00
Ulya Trofimovich 87f0fb454b Docs: regenerate manpages for C and Go with updated examples. 2022-01-10 23:51:43 +00:00
Ulya Trofimovich 644a151070 Cosmetic fixes in examples for all backends. 2022-01-10 22:39:43 +00:00
Ulya Trofimovich e0c7d453e3 Rewrite POSIX captures example for C and Go backends. 2022-01-10 07:34:26 +00:00
Ulya Trofimovich 38226f2a6b Rust backend: add example of submatch extraction with POSIX captures. 2022-01-09 20:46:23 +00:00
Ulya Trofimovich 1d515be714 Rewrite m-tags example for C and Go backends. 2022-01-09 17:07:44 +00:00
Ulya Trofimovich b48833c5a7 Rust backend: add example of submatch extraction with m-tags. 2022-01-09 16:21:54 +00:00
Ulya Trofimovich ee88b9670a Rewrite s-tags example with YYFILL for C and Go backends. 2022-01-08 19:58:50 +00:00
Ulya Trofimovich f8aa528686 Rust backend: add example of submatch extraction with s-tags and YYFILL. 2022-01-08 19:58:50 +00:00
Ulya Trofimovich 552ba7e687 Rewrite s-tags example for C and Go backends.
The new example parses semantic versions, while the old one parsed
IPv4 addresses. The new example demonstrates a conditional tag, as the
last version part may be missing.
2022-01-07 23:03:28 +00:00
Ulya Trofimovich 2251d3813a Rust backend: add example of submatch extraction with s-tags. 2022-01-07 08:20:35 +00:00
Ulya Trofimovich 6df5cc4024 Rust backend: add another example of reuse mode (!use directive). 2022-01-06 08:36:52 +00:00
Ulya Trofimovich faffbd78a7 Rust backend: add example of reuse mode (use:re2c blocks). 2022-01-06 08:09:03 +00:00
Ulya Trofimovich f60aedbf65 Rust backend: add example with include directives. 2022-01-05 23:49:41 +00:00
Ulya Trofimovich 282fbc0791 Simplify example for autogenerated header feature (for C, Go, Rust). 2022-01-05 23:49:41 +00:00
Ulya Trofimovich bb27b0e6ef Rust backend: completely disable line directives.
This is necessary because some parts of codegen conditionally generate
newlines depending on the line directives option. In Rust mode, unless
line directives are disabled codegen generates redundant newlines (e.g.
for the `stags:re2c` directive).
2022-01-05 23:03:52 +00:00
Ulya Trofimovich 2d60c74d00 Rust backend: add example with an autogenerated header. 2022-01-05 08:42:35 +00:00
Ulya Trofimovich c05af363e6 Go backend: use loop label to avoid potential continue ambiguity. 2022-01-05 07:31:15 +00:00
Ulya Trofimovich ef05cd2bc0 Add configuration re2c:label:yyloop.
The default is empty for C or Go, and "'yyl" for Rust.
2022-01-04 23:30:46 +00:00
Ulya Trofimovich 58c71a9e3f Rust backend: use loop label to avoid potential continue ambiguity. 2022-01-04 23:17:06 +00:00
Ulya Trofimovich 3ec2e646fa Rust backend: add example with blocks (functions) instead of conditions. 2022-01-03 14:42:16 +00:00
Ulya Trofimovich cca31d2225 Do not generate redundant YYPEEK statements.
YYPEEK statement is redundant if the assigned `yych` value is
overwritten before it is read. This may happen if a state has a single
transition to a non-move state (so there is no need to match on `yych`).
Transitions to a move state is different because a move state does not
have its own YYPEEK (it relies on a previously read `yych` value).
2022-01-02 23:35:04 +00:00
Ulya Trofimovich 919570c46a Do not allocate indices for unused state labels (in goto/label mode).
This change affects nearly every test (with the exception of tests for
errors that abort before code generation, and tests that use loop/switch
approach that have been updated earlier).

Since the change affects so many tests, it is impossible to verify
manually, but skeleton tests pass (and they actually compile and run the
generated code).
2022-01-02 17:06:24 +00:00
Ulya Trofimovich 82b704f693 Do not allocate indices for unused state labels (in loop/switch mode). 2022-01-02 16:47:44 +00:00
Ulya Trofimovich a46f01e603 Do not generate YYDEBUG statements for unused states labels.
Currently DFA states with unused labels still have their own index, but
this will change soon and there won't be any state number to pass to
YYDEBUG. This patch prepares the code by removing YYDEBUG statements for
states with unused labels.

One exception is the initial label: it may be unused (if there are no
transitions into the initial state), but still have a valid index. Keep
YYDEBUG statements for the initial label as they may be useful.
2022-01-02 16:38:41 +00:00
Ulya Trofimovich 705e687028 Split label generation and numbering into separate passes.
Labels should be generated before DFA transitions, because the pass that
generates transitions performs used label analysis: for every transition
its destination state label is marked as used. However label indices
should be assigned after used label analysis, otherwise indices may be
assigned to unused labels.

This is particularly important with the loop/switch approach, as label
indices map to `yystate` switch cases which should have consecutive
numbers.

This patch does not change label numbering yet, it only prepares the
code for the change (so no tests are updated).
2022-01-02 15:42:44 +00:00
Ulya Trofimovich 99ff66bc23 Add run scripts for a few test directories.
The scrips heuristically check if a test is complete (can be compiled
and run as a standalone program) and if so, compiles and runs it.
2022-01-02 15:37:04 +00:00
Ulya Trofimovich 2e7935e569 Optimize loop/switch code: avoid redundant looping via yystate switch.
As long as the following state has no incoming transitions (its label is
unused), generate it as a continuation of the current state. This avoids
looping through the `yystate` switch only to return to the next case.

The optimization is based on used label analysis for DFA state labels.
2021-12-31 23:22:17 +00:00
Ulya Trofimovich 51d3808418 Move used label analysis before the actual codegen.
This is necessary in order to generate better code with loop/switch
(avoid looping through the `yystate` switch in cases when the only
transition from a DFA state goes to the state immediately following the
current one). For that we need to know which DFA states are used (have
incoming transitions) before actually generating them.

Previously used label analysis was needed only to avoid generating
unused labels with goto/label approach. Since the decision whether to
output a label or not is taken at a late stage in codegen, it was ok to
perform the analysis when generating the states. With the loop/switch
approach this is no longer sufficient.

This patch moves used label analysis to an earlier codegen pass. A few
special labels are still handled at a late phase (such as the start
labels of blocks, some of which are only marked as used after expanding
`getstate` directives). These few exceptions do not affect DFA state
labels that matter for the loop/switch approach.
2021-12-31 23:22:17 +00:00
Ulya Trofimovich 1d72fbe950 Rust backend: add a Unicode example. 2021-12-28 12:48:10 +00:00
Ulya Trofimovich 0fcedefbfb Rust backend: emit correct code with -s, --nested-ifs option.
In Rust there is no implicit coersion between `u8` and `char` literals,
so it is necessary to emit hexadecimal literals in `yych` comparisons.
2021-12-28 12:21:24 +00:00
Ulya Trofimovich 005cdc7b84 Rust backend: add YYFILL example. Refactor examples for other backends.
Try to make YYFILL examples coherent across different backends.
2021-12-27 22:24:13 +00:00
Ulya Trofimovich d191cd86ac Rust backend: use isize as condition type in storable state mode.
With storable states `yystate` may have value -1, so it needs to have
signed type. Conditions have the same type as they are assigned to
`yystate`.

Also add a test for the combination of storable state and conditions.
2021-12-27 14:50:42 +00:00
Ulya Trofimovich d40ed35011 Rust backend: always generate braces around if body. 2021-12-27 13:37:58 +00:00
Ulya Trofimovich 8727e11e85 Emit better code for -1 state in loop/switch mode.
In loop/switch mode case -1 should be the same as case 0. Previously
the generated code handled these two as different cases, but they should
be handled as one case with a range of values.

This commit allows using ranges not only for characters (the switch on
`yych`), but also for numbers (the switch on `yystate`). In storable
state mode -1 is appended to the range of the first case 0.
2021-12-27 13:37:58 +00:00
Ulya Trofimovich 32a757f84c Rust backend: add an example for storable state. 2021-12-27 13:37:58 +00:00
Ulya Trofimovich 1bd47e0244 Rust backend: in storable state mode handle -1 state correctly.
With loop/switch approach (which is implied for the Rust backend) case
-1 is the same as case 0. Normally this is handled by falling through
from case -1 to case 0, but since Rust doesn't have fallthrough it is
necessary to set `yystate` to 0 and loop back to the head of the switch.
2021-12-27 12:06:30 +00:00
Ulya Trofimovich 87f335c560 Correctly parse single-line comments in indented semantic actions.
Semantic actions that start with `:=` are not enclosed in curly braces,
so re2c uses indentation to find the end of user-defined code: as long
as a line has nonzero indentation it is parsed as a continuation of
semantic action. In order to do that re2c needs to analyze if a newline
is followed by a whitespace. Previously this analysis was missing in the
case of newlines in single-line comments.
2021-12-24 21:38:00 +00:00
Ulya Trofimovich dba7d055aa Restrict lexical contexts where %{ is recognized as a block start.
As Krishna noticed in bug #392 "Cannot compile when user c string has a
special pattern", `%{` in the middle of a string makes re2c think that
this is a start of a re2c block. The user has to braek the string in two
in order to separate `%` from `{`.

The problem is exacerbated by the fact that `%{` does not require -F,
--flex-support option. It affects all re2c programs.

In general re2c cannot be sure if `%{` appears in the middle of a
string, a comment, a macro defintion or some other lexical context where
it is a part of a larger lexeme and not a standalone block start marker.
This is because re2c doesn't parse user-defined code in-between re2c
blocks (doing that would require implementing multiple language
frontends in re2c, which is out of the question).

This commit mitigates the problem in #392 by restricting lexical context
wheer `%{` is recognized as a block start: the marker must be on a new
line, optionally preceded by whitespace characters. This does not cover
all the cases and it may break some re2c programs that used block start
`%{` in other lexical contexts, but it is a reasonable compromise
between usability and backards compatibility.
2021-12-24 14:20:32 +00:00
Ulya Trofimovich 92c1a456ae Github Actions: fix path for uploading artifacts when the build fails.
Reorder steps so that 'Get build dir' step is executd before build and
test steps. Otherwise if the build or test steps fail, subsequent steps
are skipped and the path for uploading artifacts is not set properly.
2021-12-19 11:46:27 +00:00
Ulya Trofimovich f80c4995de Update configuration names in examples. Cosmetic formatting changes. 2021-12-19 11:46:27 +00:00
Ulya Trofimovich 0716f1d59b Use option alias --header instead of --type-header in tests and examples. 2021-12-19 11:46:27 +00:00
Ulya Trofimovich 886b73af33 Provide simpler names for some re2c options.
For example, --type-header should be just --header: it used to be for
`/*!types:re2c*/` directives initially, but after the addition of
`/*!header:re2c...*/` it may contain anything.

Also, --input is confusing and should be --api, as we refer to this as
"generic API" or "default API" in the documentation.
2021-12-19 11:46:27 +00:00
Ulya Trofimovich 091df3ab02 Update message for -Wcondition-order warning. 2021-12-17 23:02:04 +00:00
Ulya Trofimovich ad2ddd249c Add directive conditions:re2c (an alias for types:re2c).
Also guard against confusing error when instead of a local block
`local:re2c` the user specifies a named block `re2c:local`.
2021-12-17 22:41:35 +00:00
Ulya Trofimovich 45dbbe88b1 Revise re2c configurations, provide simpler aliases for some.
Configurations have evolved over time, and some of the names are quite
illogical. For example `re2c:flags:tags` should be just `re2c:tags`,
and `re2c:flags:unicode` should be `re2c:encoding:utf-32`. While we
cannot remove the old names (that would break existing programs), we can
still provide simpler and more logical aliases.

Take that opportunity to clean up configuration lexer a bit.
2021-12-17 22:02:42 +00:00
Ulya Trofimovich 4c88da02c5 Add option --no-unsafe and configuration re2c:flags:unsafe.
This allows to suppress generation of `unsafe { ... }` wrapper around
YYPEEK (for the Rust backend). Normally YYPEEK should avoid bounds
checks, as the lexer already does them (and goes to great lengths in
order to minimize the number of checks). However it may be useful to
enable bounds checks in YYPEEK for debug purposes, or just extra safety.
In that case the new option/configuration is needed to avoid warnings
emitted by the Rust compiler about redundant `unsafe`.

Also extend the script that compiles and runs examples for Rust to run
each test twice: first with the unsafe YYPEEK definition, and second
time after patching it to avoid `unsafe`. This allows to check that the
examples do not have trivial memory errors.
2021-12-15 22:53:26 +00:00
Ulya Trofimovich f081edd09e C backend: fix a memory leak in one of the examples.
Build and run examples with LeakSanitizer and AddressSanitizer.
2021-12-15 22:45:27 +00:00
Ulya Trofimovich 01a46937a0 Rust backend: avoid redundant braces around sematic actions.
Normally sematic are surrounded by line directives, so they occupy
multiple lines and should be wrapped in curly braces. In Rust there are
no line directives, but the codegen was still confused by empty stubs
and rendered semantic actions as multiline code blocks.

In order to fix this, it was necessary to separate removal of empty
code blocks into a separate pass (previously it was a part of `combine`,
but `combine` is too specialized and does not remove all empty blocks).
2021-12-14 00:17:56 +00:00
Ulya Trofimovich 0575cf7291 Rust backend: suppress warnings about unused yych initializer.
It is necessary to initialize `yych` (even though the initial value will
never be used) because in Rust a potentially uninitialized variable is a
compilation error. However, in cases when the compiler is able to see
that the variable is overwritten on all code paths, it instead emits a
warning about unused assignments.

Suppress the warning with `#[allow(unused_assignments)]`.
2021-12-13 23:26:16 +00:00
Ulya Trofimovich 0ff77971aa Rust backend: add an example for conditions. 2021-12-13 22:28:09 +00:00
Ulya Trofimovich c9eb8622c3 Rust backend: fix codegen for condition enum.
Generate standalone constants for each condition instead of an enum in
order to avoid casting to `yystate` type on each operation.
2021-12-12 19:22:39 +00:00
Ulya Trofimovich ed88e12e60 C backend: change formatting of switch statements.
Do indent cases with the default indent string. Do not auto-align cases
that fit on one line with tabs, use a single space before the case body.
Tab alignment didn't work very well and required special handling (for
example with --case-ranges it had to be turned off, because case length
varies more than one tab).

Over a thousand of tests were updated, but all the changes are trivial.
2021-12-11 20:53:52 +00:00
Ulya Trofimovich 4131ae7244 Rust backend: add YYFILL example with re2c:eof. 2021-12-11 10:21:28 +00:00
Ulya Trofimovich 48f2a0ca10 Rust backend: add end-of-input example with generic API and re2c:eof. 2021-12-09 22:20:55 +00:00
Ulya Trofimovich 0c2dfbdd96 Rewrite Go examples to be normal programs with main rather than tests.
Also delete a useless configuration YYLESSTHAN in one example.
2021-12-08 23:46:02 +00:00
Ulya Trofimovich 6715a02339 Cosmetic fixes in the C examples (also delete a useless configuration). 2021-12-08 00:26:15 +00:00
Ulya Trofimovich 7a1d0aaf2d Rust backend: add end-of-input example with generic API and sentinel. 2021-12-07 22:39:38 +00:00
Ulya Trofimovich de5e439187 Rust backend: add a re2c:eof example. 2021-12-07 22:22:31 +00:00
Ulya Trofimovich 62c3c6a567 Rust backend: wrap YYPEEK in unsafe rather than the whole lexer.
Also restructure YYPEEK generation to avoid code duplication.
2021-12-06 23:40:22 +00:00
Ulya Trofimovich 9df4c535e9 Fix unused variable warning in non-debug mode. 2021-12-06 22:05:19 +00:00
Ulya Trofimovich 7a4b317288 Rust backend: fix YYMAXFILL generation, add a bounds-checking example. 2021-12-06 21:50:27 +00:00
Ulya Trofimovich 297ee84733 Clean up if-then-else code generation and fix it for Rust. 2021-12-06 07:31:58 +00:00
Ulya Trofimovich 92276e73a2 Rust backend: add example for sentinel-based end-of-input check. 2021-12-04 21:07:51 +00:00
Ulya Trofimovich 1501b4df45 Correctly lex Rust code with standalone single quotes.
When lexing code blocks we need to lex string literals because they may
contain closing brace symbol that would otherwise be erroneously lexed
as a real closing brace.

However, single quote in Rust may be either the beginning of a char
literal as in '\u{1F600}', or a standalone one as in 'label. In the
latter case trying to lex a generic string literal will consume a
fragment of the file until the next single quote (if any) and result in
either a spurios parse error, or incorrect generated code. Therefore in
Rust we try to lex a char literal, or else consume the quote.
2021-12-04 20:57:54 +00:00
Ulya Trofimovich 9198728b43 Rust backend: wrap lexer in "unsafe" to avoid it in user-defined code. 2021-12-04 16:53:11 +00:00
Ulya Trofimovich d5bbfbd41d Adjust Github Actions config and CMake presets for re2rust. 2021-12-04 09:15:36 +00:00
Ulya Trofimovich 0c0d674e1d Rust backend: add the first (working) example. 2021-12-04 09:09:22 +00:00
Ulya Trofimovich 27b0008c56 Adjust testing script for Rust. 2021-12-04 09:08:49 +00:00
Ulya Trofimovich 01046e779c Autotools: build re2rust (option RE2C_BUILD_RE2RUST is on by default).
Documentation is yet to be done, so do not add build rules for it.
2021-12-04 09:08:25 +00:00
Ulya Trofimovich 3c02670f0f CMake: build re2rust tool (option RE2C_BUILD_RE2RUST is on by default).
Documentation is yet to be done, so do not add build rules for it.
2021-12-04 09:08:25 +00:00
Ulya Trofimovich 59e3223d0d Rust backend: add support for basic cases. 2021-12-03 23:59:55 +00:00
Ulya Trofimovich 09161b1444 Go backend: render continuous character ranges in compact form.
Use a comma-separated list instead of multiple switch cases.
2021-12-03 23:38:12 +00:00
Ulya Trofimovich e7ffdc5574 Small cleanup in codegen function that renders switch cases.
The only updated test has insignificant changes (comment moved before
the colon in `case ... :`).
2021-12-03 23:17:58 +00:00
Ulya Trofimovich 4937938362 Use abstract variable types in codegen. 2021-12-02 23:21:11 +00:00
Ulya Trofimovich 7e21423866 Abort in the default case in loop/switch mode.
Except for C/C++ when `re2c:state:abort` is not set, as `abort()`
requires including a header, which we don't want to enforce on the user.
2021-12-02 22:36:09 +00:00
Ulya Trofimovich 38f2d1fcd4 Add option stub --lang rust (currently generates incorrect code). 2021-12-01 22:29:53 +00:00
Ulya Trofimovich 987e7e17c3 Add a test for loop/switch used with storable state and conditions. 2021-12-01 22:09:19 +00:00
Ulya Trofimovich 2c0dd72332 Always generate YYSETSTATE in final states in storable state mode.
If the user has an outer loop that goes via YYGETSTATE switch, they
would expect the next iteration of the loop to start from the intiial
state rather than from some YYFILL state left after the last YYFILL
invocation. This especially matters when there is no explicit
`getstate:re2c` and no user-defined code between the YYGETSTATE switch
and the lexer entry (which is always the case in loop/switch mode).

A lot of (54) tests have been updated (they now have additional
YYSETSTATE invocations). One of them (conditions/condition_08_cbif.c)
previously resulted in a crashing program on input file "??(??)", and
now due to the addition of YYSETSTATE it doesn't crash.

Also, use state -1 rather than 0 as the default one in loop/switch mode.
Although it is safe to use 0 (cases always start from zero), using -1 is
unifies it with goto/label mode, where 0 cannot be used (start label
does not have to be `yy0`). And -1 is always safe for both modes, as
the YYGETSTATE switch always has either a default case or an explicit -1
case that goes to the initial state.
2021-11-30 23:53:38 +00:00
Ulya Trofimovich d308e4ed6f Store Msg reference in Opt to give options access to warnings.
Options are managed by `Opt`, and warnings are managed by `Msg`. Both
are created in `main` and have the lifetime of the whole program, so it
is not difficult to connect them.
2021-11-28 21:04:41 +00:00
Ulya Trofimovich 61af1763fd Add missing <assert.h> include. 2021-11-28 18:12:02 +00:00
Ulya Trofimovich edf3cbbd3e CMake: create output directory before building docs.
Previously trying to run rst2man.py with an output file in a nonexistent
directory resulted in the following build error:

  $ cmake --preset=linux-gcc-debug-ootree-skeleton-full
  $ cmake --build --preset=linux-gcc-debug-ootree-skeleton-full
  ...
  [  1%] Generating src/msg/help.cc
  Unable to open destination file for writing:
    OutputError: [Errno 2] No such file or directory:
      '[...]/linux-gcc-debug-ootree-skeleton-full/src/msg/help.cc.1'
2021-11-28 18:03:29 +00:00
Ulya Trofimovich 06c85fb955 CMakePresets.json: inherit "full" configuration before "fast".
Otherwise variable definitions from "fast" configuration take precedence
over the "full" configuration, resulting in disabling some important
configrations, such as Go language support.

For example, if "fast" is inherited before "full" we have the following
incorrect configrations that sets RE2C_BUILD_RE2GO:BOOL="FALSE":

  $ cmake -S .. --preset=linux-gcc-release-ootree-skeleton-full
  Preset CMake variables:

    CMAKE_BUILD_TYPE="Release"
    CMAKE_CXX_COMPILER="g++"
    CMAKE_C_COMPILER="gcc"
    CMAKE_INSTALL_PREFIX:PATH="[CUT]/re2c/install"
    RE2C_BUILD_LIBS:BOOL="TRUE"
    RE2C_BUILD_RE2GO:BOOL="FALSE"
    RE2C_FOR_BUILD="[CUT]/re2c/install/bin/re2c"
    RE2C_REBUILD_DOCS:BOOL="TRUE"
    RE2C_REBUILD_LEXERS:BOOL="TRUE"

But if "full" is inherited after "fast" we have the following (correct):

  $ cmake -S .. --preset=linux-gcc-release-ootree-skeleton-full
  Preset CMake variables:

    CMAKE_BUILD_TYPE="Release"
    CMAKE_CXX_COMPILER="g++"
    CMAKE_C_COMPILER="gcc"
    CMAKE_INSTALL_PREFIX:PATH="[CUT]/re2c/install-2"
    RE2C_BUILD_LIBS:BOOL="TRUE"
    RE2C_BUILD_RE2GO:BOOL="TRUE"
    RE2C_FOR_BUILD="[CUT]/re2c/install/bin/re2c"
    RE2C_REBUILD_DOCS:BOOL="TRUE"
    RE2C_REBUILD_LEXERS:BOOL="TRUE"
2021-11-28 16:49:44 +00:00
Ulya Trofimovich 2d28bfea79 Make --loop-switch work with conditions.
Merge all conditions in one loop/switch where DFA for each condition has
its own set of cases. Use `yystate` variable to switch between
conditions in the same way as between DFA states.

The => rules set user-defined condition variable with YYSETCONDITION.
The :=> rules set `yystate` and continue to the head of the loop/switch.
2021-11-28 16:49:44 +00:00
Ulya Trofimovich 9d58618750 Respect define:YYGETSTATE:naked configuration in loop/switch mode. 2021-11-28 16:49:44 +00:00
Ulya Trofimovich c38c965434 For skeleton and .dot targets merge header file into the output file.
Header file may contain blocks with regular expressions and rules. They
should be handled as well as the blocks in the output file.

This patch fixed a failing skeleton test.
2021-11-28 16:49:40 +00:00
Ulya Trofimovich 96cacc78c0 Use initial state indices as condition numbers with --loop-switch.
Normally with the goto/label approach condition enumeration uses
implicit consecutive indices starting from zero. With the loop/switch
approach it is more convenient to represent conditions with their
initial DFA state index. This allows one to assign condition numbers to
the state variable `yystate` and get rid of the entry condition switch.
2021-11-28 16:48:30 +00:00
Ulya Trofimovich 6f2801248c Factor out block list construction into a separate function. 2021-11-28 16:48:30 +00:00
Ulya Trofimovich cbc33f36f5 Delay YYMAXFILL / YYMAXNMATCH computation until handling the directive.
The `maxfill:re2c` and `maxnmatch:re2c` directives may specify an
optional list of block names. If the list is specified, the directives
compute maximum value over the specified blocks, otherwise they compute
global maximum across all blocks in the program.

Previously the global maximum was prepared in advance even if the
directives were not used. This patch delays the computation of global
YYMAXFILL / YYMAXNMATCH until they are needed, as is already done in
the case when the directive specifies a list of blocks.
2021-11-28 16:48:30 +00:00
Ulya Trofimovich 41f503de5d Delay global tag list construction until handling the directive.
The `stags:re2c` and `mtags:re2c` directives may specify an optional
list of block names. If the list is specified, the directives gather
condition nems from the specified blocks, otherwise they use a global
set of tag names gathered across all blocks.

Previously the global set was prepared in advance even if the directives
were not used, but a set for specific block list was constructed only if
needed. This patch delays global set construction until it is needed and
unifies it with the case of a specific block list.
2021-11-28 16:48:30 +00:00
Ulya Trofimovich 64405f6f62 Do not autogenerate condition enum if there is an explicit types:re2c.
The rationale is, if the user specified an explicit `types:re2c`
directive, they probably do not want the autogenerated enum as well. If
for some reason they need multiple enum definitions (either in the
output file or in the header file), they can use multiple `types:re2c`
directives.
2021-11-28 16:48:26 +00:00
Ulya Trofimovich 64961bf692 Search for named blocks both in the output file and in header.
This fixes a test for condition enum: previously re2c emitted an error
because one of the `types:re2c` directives listed block name for a block
defined in another file, and re2c failed to find it. Now it finds it.
2021-11-28 16:46:56 +00:00
Ulya Trofimovich 9fdd7fca0b Do not generate empty condition enum.
Some compilers or language standards allow it, but generally it's more
likely to indicate an error in user code.

Fix a few tests that generated empty condition enum by mistake.
2021-11-28 16:46:56 +00:00
Ulya Trofimovich eb30417eed Clean up old tests for condition enum and header.
Replace a bunch of simple and similar tests with a few more
comprehensive ones that cover recent re2c features like named blocks and
block lists in the `types:re2c` directive, in addition to older features
such as the --type-header option.

One of the new tests reveals an error in re2c: it fails to find
conditions in header. The error will be fixed in a follow-up commit.
2021-11-28 16:46:56 +00:00
Sergei Trofimovich a6220b8f4b avoid using reserved identifiers (underscores)
clang with -Weverything detects these as:

    ./src/util/free_list.h:9:16:
      warning: identifier '_Ty' is reserved
      because it starts with '_' followed by a capital letter [-Wreserved-identifier]
    template<class _Ty>
                   ^
2021-11-28 16:46:56 +00:00
Sergei Trofimovich bbb9dae8a3 fix struct/class declaration mismatch (-Wmismatched-tags)
Detected by clang's-Weverything:

    ./src/regexp/re.h:17:1: warning: struct 'Msg' was previously declared as a class;
      this is valid, but may result in linker errors under the Microsoft C++ ABI [-Wmismatched-tags]
    struct Msg;
    ^
2021-11-28 16:46:56 +00:00
Ulya Trofimovich 53259db5e7 Make --loop-switch work with storable state.
With the loop/switch approach there is no `goto` statement, so it is
impossible to jump from a `getstate:re2c` block to an YYFILL label,
bypassing all the user-defined code in the middle (as it normally
happens with the goto/label approach).

Therefore `getstate:re2c` is forbidden with --loop-switch, and the
initial switch on storable state is merged into the `yystate` switch:

  - case -1 falls through to case 0 (the initial state)

  - transitions to YYFILL states are moved to cases that occupy
    contiguous numbers after the last regular DFA state

In order to make it possible to wrap the generated lexer in a
user-defined loop, an `YYSETSTATE(1)` statement is emitted in each final
state before the user-defined semantic action: if the action jumps to
the head of the outer loop, the next iteration will start from state -1,
as the user might expect. Note that `YYSETSTATE(1)` is not needed with
goto/label approach, because one can jump directly to the start label.
2021-11-28 16:46:56 +00:00
Ulya Trofimovich 28bc929bb6 Make --loop-switch and --eager-skip options non-configurable.
Having configuration for the --loop-switch option is only useful if one
needs to enable loop/switch approach on a per-block basis. Mixing the
two approaches (goto/label and loop/switch) would mean that some of the
blocks have start labels and can use cross-block transitions, while
others cannot. This would create confusion for whole-program directives
like `getstate:re2c` that cover multiple blocks.

With the loop/switch approach `getstate:re2c` should be forbidden, as it
requires a cross-block transition from the state switch to the lexer
entry, which is unsupported in the absence of the `goto` statement.
2021-11-28 16:46:52 +00:00
Ulya Trofimovich 031ddb7bb8 With --loop-switch, start state enumeration from zero in each block.
Normally with the goto/label approach re2c uses a program-wide state
enumeration that starts from zero and increases with each block. Since
each state has a label, global enumeration allows one to have multiple
blocks in the same function without the risk of label collision.
Moreover, different blocks can be connected with cross-block `goto`
transitions, so all state labels should have different numbers.

The situation is different with the loop/switch approach: there are no
labels and no cross-block `goto` transtions; instead every state has a
switch on the `yystate` variable. Since different block have different
switches, it makes sense to start state enumeration from zero in each
block (so that switch cases start from zero, and the zeroth case
corresponds to the start state of every block).
2021-11-28 16:41:17 +00:00
Ulya Trofimovich 8d219a6b27 Drop useless -c option in some of the Go examples.
These examples do not use conditions, so -c does nothing. It has been
accidentally copy-pasted from another example that uses conditions.
2021-11-28 16:41:17 +00:00
Ulya Trofimovich 1c244eb19b Add tests for the new --loop-switch option (for C and Go backends).
The added tests are copy-pasted from examples, but the generated code is
different: it uses loop/switch constructs instead of goto/label. All
tests except for conditions and storable state are valid programs that
can be compiled and run without errors.
2021-11-28 16:41:17 +00:00
Raekye c74080e656 Initial implementation of the --loop-switch option.
With this option, instead of the usual goto/label approach DFA is
wrapped in a loop with a `switch` statement on `yystate` variable. Each
DFA state is an individual `case`. Transitions between states are done
by setting the `yystate` variable to the numeric index of the target
state and executing `continue` that jumps to the head of the loop and
goes via the `switch` again. This is less efficient than direct jumps
with the goto/label approach, but it is the only way we can implement a
DFA for languages that do not have `goto` statement (such as Rust).

YYFILL labels are problematic for the loop/switch approach, because they
are normally in the middle of a DFA state (after the YYSKIP operation,
but before YYPEEK and transitions to other states). To fix this, we use
the --eager-skip option that moves YYSKIP operations from DFA states to
transitions.

The initial value of `yystate` is the numeric index (label) of the first
DFA state. It is _not_ the intiial label, because initial label does not
have a state (so there is no `case` in the `switch` for it), and it is
only needed to bypass YYSKIP operation in the first DFA state (which is
not there anyway because of the --eager-skip option).

Current limitations:
  - Conditions are not supported. We need a per-condition `yystate`, and
    ideally transitions between conditions should also use a loop/switch
    approach instead of goto/label (it will be required for Rust, but it
    is optional for C and Go).

  - Storable state is not supported. We need to rewrite user-defined
    code to use the same state variable as `yystate` and the one in
    `YYGETSTATE`/`YYSETSTATE`, as well as to put `getstate` block
    immediately before DFA entry (if there is any code between state
    dispatch and DFA entry, it needs to be bypassed when re-entering
    the lexer after YYFILL, which is easily done with goto/label
    approach in C and Go, but not in Rust that has no `goto`).

Test results with the --loop-switch option enabled by default:
  - Skeleton tests pass (320 soft errors).

  - Examples for C and Go compile and run without errors, except for
    conditions, storable state and cases when user-defined code needs to
    be rewritten (e.g. when it uses an outer loop and `continue`/`break`
    statements end up referring to the wrong loop).
2021-11-28 16:41:17 +00:00
Raekye cba165c27b Don't generate initial label if --eager-skip option is used.
The initial label is not needed in such cases as there is no need to
bypass YYSKIP statement (--eager-skip moves it from states to
transitions).
2021-11-28 16:41:17 +00:00
Raekye e73b93f61f Add stubs for --loop-switch option and related configurations.
The following has been added:
  - option --loop-switch
  - configuration `re2c:flags:loop-switch`
  - configuration `re2c:variable:yystate`

Currently they are no-ops.
2021-11-28 16:41:17 +00:00
Raekye 8011459a1e Move --eager-skip option from constant to mutable.
This is necessary to support the future --loop-switch option.

With --loop-switch we cannot have labels (goto targets) in the middle of
a state. This affects YYFILL labels which normally go after YYSKIP but
before YYPEEK. The --eager-skip option resolves the problem by moving
YYSKIP statements from states to transitions. The plan is to enforce it
automatically if --loop-switch is enabled, but since --loop-switch will
be a mutable option, --eager-skip also needs to be mutable.
2021-11-28 16:41:17 +00:00
Raekye 6695fcd3af Skeleton: use goto-loop instead of for-loop.
To support the future --loop-switch option, this change avoids
unexpected control flow with `continue`.

The skeleton tests are verified and updated.
2021-11-28 16:41:17 +00:00
Ulya Trofimovich 5ac98bc208 Correctly handle nested include files with identical paths.
The previous commit fixed bug #386 "#line directives around !include
contents" by reading every include directive twice: for the first time
on entry (when the file is included), and for the second time on exit
(when the file has been processed).

However that commit used a crude criterion to distinguish the first and
the second times: it compared the include file path (specified in the
include directive) to the path of the file on top of the stack. This
doesn't work for nested include files that have the same relative path.

This patch adds a test and fixes the problem by using a different
criterion: it checks if the parent file is topmost after popping all
finished files from stack (the comments in src/parse/scanner.cc explain
why this works in detail).
2021-11-28 11:29:41 +00:00
Ulya Trofimovich 48e83fcaab Mark start and end of included .re files with line directives.
This fixes bug #386 "#line directives around !include contents"
reported by Cyan Ogilvie.

It is easy to generate line directive at the beginning of the include
file, but much more difficult to find the end of it: file contents are
just a stream of bytes in the input buffer, and the continuation of the
parent file follows immediately after the end of the inlude file.

Therefore we use a hack and "unread" the include directive in the parent
file before filling the buffer with the contents of the include file (as
if the include directive appeared after the contens of include file).
This makes the lexer read the directive for the second time; at this
point we know it's the same include directive because the include file
is already on top of the file stack. So we ignore the directive and
simply generate line info.

The current implementation has a problem with nested includes that have
identical relative file paths. This will be fixed in a follow-up patch
by looking at the resolved paths when comparing files.
2021-11-27 12:16:48 +00:00
Ulya Trofimovich 7c6b5c955e Generate non-overlapping names for s-tag and m-tag variables.
This fixes bug #385 "mtag/stag automatic variable generation collision"
reported by Cyan Ogilvie.

Previously s-tag and m-tag variables used non-overlapping numbers
within a single DFA. With start conditions this is insufficient, as
variables in different conditions (DFAs) may have identical numbers.

If both tag variables are single-valued, or if they are both
multi-valued, having one variable is fine: there are no transitions to
or from the middle of DFA, so tag variables in different conditions are
never used at the same time.

However if one of the variables is single-valued and the other one
multi-valued (or vice versa), they cannot share the same tag variable.
To avoid collision in such cases, this patch gives m-tag variables an
extram "m" affix that makes them different from any s-tag variable.
S-tag variables do not get an "s" affix primarily to avoid updating over
600 tests. Tag variables are internal to re2c and the user should not
use them directly, so this change does not break user code.
2021-11-23 23:25:14 +00:00
Ulya Trofimovich 68e1ab7160 Correctly compute fixed tags in trailing context.
Tags in trailing context may be fixed on the rightmost cursor position.
Their values must be updated before cursor is reset to the position of
the trailing context, otherwise the values would be incorrect.
Previously this was not so, which resulted in incorrect tag values.

This fixes bug #380 "Tags incorrectly set with lookahead" reported by
Terry Sanders .
2021-11-04 23:51:01 +00:00
Ryan Mast 8920ef895b Setup Java for the benchmarks workflow using actions/setup-java 2021-11-02 07:25:00 +00:00
Perry E. Metzger 73dc6295a7 minor fixes to interface.rst_
Improve grammar, make some small style improvements, and keep the
lines consistently under 80 columns. Also update boostrap docs for
resulting changes.
2021-10-31 20:30:35 +00:00
Ulya Trofimovich 6d7c3cbb47 Small fixes in distcheck script.
Changes:
  - use 'sh' instead of 'bash' as interpreter
  - split build into stages 1 and 2 and rebuild lexers at stage 2
  - double-quote shell variables to make shellcheck happy
2021-10-24 13:10:47 +01:00
Ulya Trofimovich 072d49e59c Autotools: link google-benchmark binaries with pthread. 2021-10-22 16:52:36 +01:00
Ulya Trofimovich eb8720d5ea Use unsigned integers for register versions in TDFA states.
Previously we used negative numbers for register versions that were
allocated for transitions on negative tags. This is pointless, because
state mapping may biject positive versions to negative ones or vice
versa, erasing the distinction. And it wasn't used anyway.
2021-09-15 22:42:55 +01:00
Ulya Trofimovich b90b78c79c Mark each register as not interfering with itself.
Exclude diagonal pairs from interference table. This does not affect
subsequent register allocation, because the algorithm that partitions
registers into non-interfering classes does not check is a register
interferes with itself. So the fix does not affect the generated code,
except for one test that draws the interference table.
2021-09-04 09:41:08 +01:00
Ulya Trofimovich 6b434e934c run_tests.py: make tests fast again by fixing Wine check.
Commit ec1dc2b3ec incorrectly compared
Wine path against `None` to determine if the tests run under Wine. That
doesn't work as expected because the default value is empty string, not
`None`, so the checks always succeeded and as a result the script did
unnecessary work (patched newlines in the generated output). That made
it a few times slower.
2021-09-04 09:16:04 +01:00
Biswapriyo Nath 15376f4393 Define _POSIX_SOURCE for fdopen in cygwin
This fixes the error:
error: ‘fdopen’ was not declared in this scope; did you mean ‘fopen’?
2021-09-03 16:35:42 +01:00
Serghei Iakovlev dff1b6cd36 Provide support of CMake Presets
Since 3.19.8 CMake looks in the top source directory of a project for files
named CMakePresets.json and CMakeUserPresets.json. Neither file is required
to be present, but if the user tries to list or use presets, at least one of
the files must exist. If both files are present, they will effectively be
merged by reading the CMakePresets.json file first and then the
CMakeUserPresets.json file.

CMakePresets.json can be used to define presets for things like continuous
integration jobs or cross-compilation setups using toolchains provided as
part of the project. In general this feature allows us to simplify CI
configuration phase by taking out all the logic into presets-file and helps
us to make reproducible builds. From now on, you no longer need to carefully
read and copy all the flags locally in order to reproduce CI configuration or
build. Simple use the same one line command as at CI.

As a bonus, users of modern CMake can use a cross-platform and portable way
instead of build/__cmake*.sh scripts.

To see the list of available presets use:
    cmake --list-presets

To configure re2c use:
    cmake --preset=<NAME>

To build re2c use:
    cmake --build --preset=<NAME>

To test re2c use:
    cmake --build --preset=<NAME> --target tests

References:

- https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html
- https://gitlab.kitware.com/cmake/cmake/-/issues/21164
- https://cmake.org/cmake/help/latest/guide/user-interaction/index.html#presets
2021-08-12 12:30:44 +01:00
1796 changed files with 772003 additions and 741833 deletions
+2 -1
View File
@@ -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
View File
@@ -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
+3
View File
@@ -12,6 +12,9 @@
/test_*
/.build*
# Ignore user defined CMake presets
CMakeUserPresets.json
# The files autogenerated by automake.
Makefile.in
aclocal.m4
+25 -24
View File
@@ -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.
+112
View File
@@ -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
View File
@@ -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
+483
View File
@@ -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
View File
@@ -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
+6 -5
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+2278 -2313
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+109 -109
View File
@@ -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
View File
@@ -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
+3 -1
View File
@@ -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 */
+40 -40
View File
@@ -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
View File
@@ -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"
;
+71 -71
View File
@@ -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"
File diff suppressed because it is too large Load Diff
+2592 -2302
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -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_
File diff suppressed because it is too large Load Diff
+74 -84
View File
@@ -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
+3 -1
View File
@@ -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 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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"
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+66 -54
View File
@@ -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``).
+18
View File
@@ -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.
+63 -38
View File
@@ -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*/``.
+317 -293
View File
@@ -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``.
+7 -4
View File
@@ -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.
+42 -36
View File
@@ -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.
+12 -13
View File
@@ -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.
+20 -19
View File
@@ -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``.
+18 -24
View File
@@ -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>`_.
+11 -12
View File
@@ -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
View File
@@ -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.
+3 -3
View File
@@ -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
+1 -1
View File
@@ -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).
+5 -5
View File
@@ -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 -1
View File
@@ -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
+7 -10
View File
@@ -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``).
+2 -2
View File
@@ -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
View File
@@ -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).
+1 -1
View File
@@ -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
View File
@@ -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.
+4 -4
View File
@@ -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.
+7
View File
@@ -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
View File
@@ -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.
+28 -25
View File
@@ -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
+31 -27
View File
@@ -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
+53
View File
@@ -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); };
+6
View File
@@ -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.
+14 -20
View File
@@ -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
+21 -21
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+2 -1
View File
@@ -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
+161 -167
View File
@@ -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;
}
+28 -33
View File
@@ -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;
}
+166 -174
View File
@@ -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;
}
+24 -28
View File
@@ -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;
}
File diff suppressed because it is too large Load Diff
+12 -16
View File
@@ -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;
}
+74 -74
View File
@@ -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);
+13 -14
View File
@@ -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);
+61 -60
View File
@@ -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;
}
+29 -26
View File
@@ -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;
}
+48 -49
View File
@@ -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);
+14 -14
View File
@@ -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);
+94 -99
View File
@@ -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);
+24 -31
View File
@@ -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);
+57 -62
View File
@@ -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);
+29 -33
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+22 -23
View File
@@ -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";
+10 -11
View File
@@ -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
View File
@@ -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]
+20 -24
View File
@@ -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
View File
@@ -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;
+8 -10
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -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