From a27e6e232faf8c4321402012a5214f26520560dc Mon Sep 17 00:00:00 2001 From: Ulya Trofimovich Date: Sat, 25 Feb 2017 17:00:49 +0000 Subject: [PATCH] Added yet another intermediate representation (after AST, before NFA). Rationale: AST must be immutable, because it is shared among different regexps, rules, conditions and blocks. NFA is mutable, but inconvenient for some transformations (adding fixed and default tags, rewriting parts of regexp, etc.). Before this commit all these transformations were done in one pass (during convertion of AST to NFA) which made the code rather complex. In order to add POSIX captures we'll need to add even more complexity (tracking captures, creating tags for them, maintaining tag order, etc.). --- re2c/Makefile.am | 10 +- re2c/bootstrap/src/parse/lex.cc | 2 +- re2c/bootstrap/src/parse/parser.cc | 47 ++---- re2c/src/ir/compile.cc | 6 +- re2c/src/ir/dfa/determinization.cc | 17 ++- re2c/src/ir/nfa/counters.cc | 43 ------ re2c/src/ir/nfa/estimate_size.cc | 38 +++++ re2c/src/ir/nfa/init_rules.cc | 46 ------ re2c/src/ir/nfa/nfa.cc | 27 ---- re2c/src/ir/nfa/nfa.h | 9 +- re2c/src/ir/nfa/re_to_nfa.cc | 87 +++++++++++ re2c/src/ir/nfa/regexps2nfa.cc | 136 ------------------ re2c/src/ir/re/ast_to_re.cc | 117 +++++++++++++++ re2c/src/ir/re/default_tags.cc | 54 +++++++ re2c/src/ir/re/fixed_tags.cc | 74 ++++++++++ re2c/src/ir/re/re.h | 115 +++++++++++++++ re2c/src/ir/regexp/nullable.cc | 6 +- re2c/src/ir/regexp/regexp.cc | 40 +----- re2c/src/ir/regexp/regexp.h | 18 ++- re2c/src/ir/regexp/split_charset.cc | 2 +- re2c/src/ir/tag.h | 1 - re2c/src/parse/parser.ypp | 48 ++----- re2c/test/tags/conf1.i--tags--input(custom).c | 28 ++-- re2c/test/tags/conf1.i--tags.c | 28 ++-- re2c/test/tags/conf2.i--tags--input(custom).c | 16 +-- re2c/test/tags/conf2.i--tags.c | 16 +-- re2c/test/tags/conf3.i--tags--input(custom).c | 28 ++-- re2c/test/tags/conf3.i--tags.c | 28 ++-- re2c/test/tags/copy_coalescing1.i--tags.c | 24 ++-- re2c/test/tags/dedup4.i--tags.c | 28 ++-- re2c/test/tags/exponential_bottoms.i--tags.c | 20 +-- re2c/test/tags/fix2.i--tags.c | 8 +- .../tags/fix2_trail.i--tags--input(custom).c | 16 +-- re2c/test/tags/fix2_trail.i--tags.c | 8 +- re2c/test/tags/fix3.i--tags.c | 40 +++--- .../tags/fix3_trail.i--tags--input(custom).c | 52 +++---- re2c/test/tags/fix3_trail.i--tags.c | 40 +++--- re2c/test/tags/fix4.i--tags.c | 16 +-- .../tags/fix4_trail.i--tags--input(custom).c | 22 +-- re2c/test/tags/fix4_trail.i--tags.c | 16 +-- re2c/test/tags/fix5.i--tags.c | 12 +- .../tags/fix5_trail.i--tags--input(custom).c | 20 +-- re2c/test/tags/fix5_trail.i--tags.c | 12 +- re2c/test/tags/interference.i--tags.c | 8 +- ...tag.i--tags--no-lookahead--input(custom).c | 2 +- re2c/test/tags/tags_in_trail.i--tags.c | 10 +- re2c/test/tags/twopass.i--tags.c | 28 ++-- re2c/test/tags/uniq.i--tags.c | 20 +-- 48 files changed, 820 insertions(+), 669 deletions(-) delete mode 100644 re2c/src/ir/nfa/counters.cc create mode 100644 re2c/src/ir/nfa/estimate_size.cc delete mode 100644 re2c/src/ir/nfa/init_rules.cc delete mode 100644 re2c/src/ir/nfa/nfa.cc create mode 100644 re2c/src/ir/nfa/re_to_nfa.cc delete mode 100644 re2c/src/ir/nfa/regexps2nfa.cc create mode 100644 re2c/src/ir/re/ast_to_re.cc create mode 100644 re2c/src/ir/re/default_tags.cc create mode 100644 re2c/src/ir/re/fixed_tags.cc create mode 100644 re2c/src/ir/re/re.h diff --git a/re2c/Makefile.am b/re2c/Makefile.am index fdf5ec13..c84d11ef 100644 --- a/re2c/Makefile.am +++ b/re2c/Makefile.am @@ -29,6 +29,7 @@ SRC_HDR = \ src/ir/dfa/find_state.h \ src/ir/dfa/tagpool.h \ src/ir/nfa/nfa.h \ + src/ir/re/re.h \ src/ir/regexp/encoding/case.h \ src/ir/regexp/encoding/enc.h \ src/ir/regexp/encoding/range_suffix.h \ @@ -85,11 +86,12 @@ SRC = \ src/conf/msg.cc \ src/conf/opt.cc \ src/conf/warn.cc \ - src/ir/nfa/counters.cc \ src/ir/nfa/dump.cc \ - src/ir/nfa/init_rules.cc \ - src/ir/nfa/nfa.cc \ - src/ir/nfa/regexps2nfa.cc \ + src/ir/nfa/estimate_size.cc \ + src/ir/nfa/re_to_nfa.cc \ + src/ir/re/ast_to_re.cc \ + src/ir/re/default_tags.cc \ + src/ir/re/fixed_tags.cc \ src/ir/adfa/adfa.cc \ src/ir/adfa/dump.cc \ src/ir/adfa/prepare.cc \ diff --git a/re2c/bootstrap/src/parse/lex.cc b/re2c/bootstrap/src/parse/lex.cc index d2505289..ee3a04e1 100644 --- a/re2c/bootstrap/src/parse/lex.cc +++ b/re2c/bootstrap/src/parse/lex.cc @@ -1,4 +1,4 @@ -/* Generated by re2c 0.16 on Mon Feb 13 14:29:09 2017 */ +/* Generated by re2c 0.16 on Sat Feb 25 16:26:09 2017 */ #line 1 "../src/parse/lex.re" #include "src/util/c99_stdint.h" #include diff --git a/re2c/bootstrap/src/parse/parser.cc b/re2c/bootstrap/src/parse/parser.cc index a8b1e5f7..2e34df88 100644 --- a/re2c/bootstrap/src/parse/parser.cc +++ b/re2c/bootstrap/src/parse/parser.cc @@ -606,8 +606,8 @@ static const yytype_uint16 yyrline[] = 0, 199, 199, 201, 202, 203, 207, 214, 219, 222, 226, 226, 229, 233, 237, 244, 251, 258, 263, 265, 271, 278, 279, 285, 291, 298, 299, 304, 308, 315, - 319, 326, 330, 337, 341, 358, 377, 378, 382, 383, - 384, 388, 397, 401 + 319, 326, 330, 337, 338, 344, 349, 350, 354, 355, + 356, 360, 369, 373 }; #endif @@ -1617,52 +1617,23 @@ yyreduce: break; - case 33: - - { - (yyval.regexp) = (yyvsp[0].regexp); - } - - break; - case 34: { - // see note [Kleene star is expressed in terms of plus] - switch((yyvsp[0].op)) - { - case '*': - (yyval.regexp) = RegExp::make_alt(RegExp::make_iter((yyvsp[-1].regexp)), - RegExp::make_nil()); - break; - case '+': - (yyval.regexp) = RegExp::make_iter((yyvsp[-1].regexp)); - break; - case '?': - (yyval.regexp) = mkAlt((yyvsp[-1].regexp), RegExp::make_nil()); - break; - } + switch((yyvsp[0].op)) { + case '*': (yyval.regexp) = RegExp::make_iter((yyvsp[-1].regexp), 0, RegExp::MANY); break; + case '+': (yyval.regexp) = RegExp::make_iter((yyvsp[-1].regexp), 1, RegExp::MANY); break; + case '?': (yyval.regexp) = RegExp::make_iter((yyvsp[-1].regexp), 0, 1); break; } + } break; case 35: { - if ((yyvsp[0].extop).max == std::numeric_limits::max()) - { - (yyval.regexp) = repeat_from ((yyvsp[-1].regexp), (yyvsp[0].extop).min); - } - else if ((yyvsp[0].extop).min == (yyvsp[0].extop).max) - { - (yyval.regexp) = repeat ((yyvsp[-1].regexp), (yyvsp[0].extop).min); - } - else - { - (yyval.regexp) = repeat_from_to ((yyvsp[-1].regexp), (yyvsp[0].extop).min, (yyvsp[0].extop).max); - } - (yyval.regexp) = (yyval.regexp) ? (yyval.regexp) : RegExp::make_nil(); - } + (yyval.regexp) = RegExp::make_iter((yyvsp[-1].regexp), (yyvsp[0].extop).min, (yyvsp[0].extop).max); + } break; diff --git a/re2c/src/ir/compile.cc b/re2c/src/ir/compile.cc index 5c805c48..f2aad600 100644 --- a/re2c/src/ir/compile.cc +++ b/re2c/src/ir/compile.cc @@ -61,7 +61,11 @@ smart_ptr compile(const spec_t &spec, Output &output) cs.push_back(*i); } - nfa_t nfa(rules, opts->input_api); + RESpec re(rules); + find_fixed_tags(re, opts); + insert_default_tags(re); + + nfa_t nfa(re); if (opts->dump_nfa) dump_nfa(nfa); dfa_t dfa(nfa, cs, opts, cond, warn); diff --git a/re2c/src/ir/dfa/determinization.cc b/re2c/src/ir/dfa/determinization.cc index 4038e041..48bd7789 100644 --- a/re2c/src/ir/dfa/determinization.cc +++ b/re2c/src/ir/dfa/determinization.cc @@ -109,13 +109,16 @@ void warn_nondeterministic_tags(const size_t *nondet, const std::vector &tags, const std::valarray &rules, const std::string &cond, Warn &warn) { - const size_t ntag = tags.size(); - for (size_t t = 0; t < ntag; ++t) { - const size_t m = nondet[t]; - if (m > 1) { - const Tag &tag = tags[t]; - const uint32_t line = rules[tag.rule].code->fline; - warn.nondeterministic_tags(line, cond, tag.name, m); + const size_t nrule = rules.size(); + for (size_t r = 0; r < nrule; ++r) { + const Rule &rule = rules[r]; + for (size_t t = rule.ltag; t < rule.htag; ++t) { + const size_t m = nondet[t]; + if (m > 1) { + const Tag &tag = tags[t]; + const uint32_t line = rule.code->fline; + warn.nondeterministic_tags(line, cond, tag.name, m); + } } } } diff --git a/re2c/src/ir/nfa/counters.cc b/re2c/src/ir/nfa/counters.cc deleted file mode 100644 index d77edc86..00000000 --- a/re2c/src/ir/nfa/counters.cc +++ /dev/null @@ -1,43 +0,0 @@ -#include "src/ir/nfa/nfa.h" - -namespace re2c { - -static size_t count(const RegExp *re, size_t &ntags) -{ - switch (re->type) { - case RegExp::NIL: - return 0; - case RegExp::SYM: - return 1; - case RegExp::ALT: { - const size_t n = ntags; - return count(re->alt.re1, ntags) - + count(re->alt.re2, ntags) - + 1 /* alternative */ - + (ntags - n + 1); /* default tags */ - } - case RegExp::CAT: - return count(re->cat.re1, ntags) - + count(re->cat.re2, ntags); - case RegExp::ITER: - return count(re->iter, ntags) - + 1; - case RegExp::TAG: - ++ntags; - return 1; - default: - assert(false); - } -} - -size_t counters(const std::vector ®exps, size_t &ntags) -{ - const size_t nregexps = regexps.size(); - size_t size = nregexps - 1; - for (size_t i = 0; i < nregexps; ++i) { - size += count(regexps[i].re, ntags) + 1; - } - return size; -} - -} // namespace re2c diff --git a/re2c/src/ir/nfa/estimate_size.cc b/re2c/src/ir/nfa/estimate_size.cc new file mode 100644 index 00000000..90c2d6b3 --- /dev/null +++ b/re2c/src/ir/nfa/estimate_size.cc @@ -0,0 +1,38 @@ +#include "src/ir/nfa/nfa.h" + +namespace re2c { + +static size_t estimate(const RE *re) +{ + switch (re->type) { + default: assert(false); + case RE::NIL: return 0; + case RE::SYM: return 1; + case RE::TAG: return 1; + case RE::ALT: + return estimate(re->alt.re1) + + estimate(re->alt.re2) + + 1; + case RE::CAT: + return estimate(re->cat.re1) + + estimate(re->cat.re2); + case RE::ITER: + return estimate(re->iter) + + 1; + case RE::REPEAT: + return estimate(re->repeat.re) * (re->repeat.upto + 1) + + re->repeat.upto; + } +} + +size_t estimate_size(const std::vector &res) +{ + const size_t nre = res.size(); + size_t size = nre - 1; + for (size_t i = 0; i < nre; ++i) { + size += estimate(res[i]) + 1; + } + return size; +} + +} // namespace re2c diff --git a/re2c/src/ir/nfa/init_rules.cc b/re2c/src/ir/nfa/init_rules.cc deleted file mode 100644 index 140f355e..00000000 --- a/re2c/src/ir/nfa/init_rules.cc +++ /dev/null @@ -1,46 +0,0 @@ -#include - -#include "src/conf/msg.h" -#include "src/ir/nfa/nfa.h" - -namespace re2c { - -static void assert_tags_used_once(const Rule &rule, - const std::vector &tags) -{ - std::set names; - const std::string *name = NULL; - - for (size_t t = rule.ltag; t < rule.htag; ++t) { - name = tags[t].name; - if (name && !names.insert(*name).second) { - error("line %u: tag '%s' is used multiple times in the same rule", - rule.code->fline, name->c_str()); - exit(1); - } - } -} - -void init_rules(const std::vector ®exps, - std::valarray &rules, const std::vector &tags) -{ - const size_t - nr = rules.size(), - nt = tags.size(); - - for (size_t r = 0, t = 0; r < nr; ++r) { - Rule &rule = rules[r]; - rule.code = regexps[r].code; - - rule.ltag = t; - for (; t < nt && tags[t].rule == r; ++t); - rule.htag = t; - - rule.ttag = rule.htag; - if (rule.ltag < rule.ttag && tags[rule.ttag - 1].name == NULL) --rule.ttag; - - assert_tags_used_once(rule, tags); - } -} - -} // namespace re2c diff --git a/re2c/src/ir/nfa/nfa.cc b/re2c/src/ir/nfa/nfa.cc deleted file mode 100644 index 6053b5f8..00000000 --- a/re2c/src/ir/nfa/nfa.cc +++ /dev/null @@ -1,27 +0,0 @@ -#include "src/ir/nfa/nfa.h" - -namespace re2c { - -nfa_t::nfa_t(const std::vector ®exps, input_api_t input) - : max_size(0) - , size(0) - , states(NULL) - , rules(*new std::valarray(regexps.size())) - , tags(*new std::vector()) - , root(NULL) -{ - size_t ntags = 0; - max_size = counters(regexps, ntags); - - states = new nfa_state_t[max_size]; - regexps2nfa(regexps, *this, input); - - init_rules(regexps, rules, tags); -} - -nfa_t::~nfa_t() -{ - delete[] states; -} - -} // namespace re2c diff --git a/re2c/src/ir/nfa/nfa.h b/re2c/src/ir/nfa/nfa.h index 5c57bef4..d949ac78 100644 --- a/re2c/src/ir/nfa/nfa.h +++ b/re2c/src/ir/nfa/nfa.h @@ -7,6 +7,7 @@ #include #include "src/codegen/input_api.h" +#include "src/ir/re/re.h" #include "src/ir/regexp/regexp.h" #include "src/ir/rule.h" #include "src/ir/tag.h" @@ -93,17 +94,13 @@ struct nfa_t std::vector &tags; nfa_state_t *root; - nfa_t(const std::vector &rs, input_api_t input); + nfa_t(const RESpec &spec); ~nfa_t(); FORBID_COPY(nfa_t); }; -size_t counters(const std::vector ®exps, size_t &ntags); -void regexps2nfa(const std::vector ®exps, nfa_t &nfa, input_api_t input); -bool nullable_rule(const RegExpRule &rule); -void init_rules(const std::vector ®exps, std::valarray &rules, - const std::vector &tags); +size_t estimate_size(const std::vector &res); void dump_nfa(const nfa_t &nfa); } // namespace re2c diff --git a/re2c/src/ir/nfa/re_to_nfa.cc b/re2c/src/ir/nfa/re_to_nfa.cc new file mode 100644 index 00000000..29372e14 --- /dev/null +++ b/re2c/src/ir/nfa/re_to_nfa.cc @@ -0,0 +1,87 @@ +#include "src/ir/nfa/nfa.h" + +namespace re2c { + +static nfa_state_t *re_to_nfa(nfa_t &nfa, size_t nrule, const RE *re, nfa_state_t *t) +{ + nfa_state_t *s = NULL; + switch (re->type) { + case RE::NIL: + s = t; + break; + case RE::SYM: + s = &nfa.states[nfa.size++]; + s->make_ran(nrule, t, re->sym); + break; + case RE::ALT: { + nfa_state_t + *s1 = re_to_nfa(nfa, nrule, re->alt.re1, t), + *s2 = re_to_nfa(nfa, nrule, re->alt.re2, t); + s = &nfa.states[nfa.size++]; + s->make_alt(nrule, s1, s2); + break; + } + case RE::CAT: + s = re_to_nfa(nfa, nrule, re->cat.re2, t); + s = re_to_nfa(nfa, nrule, re->cat.re1, s); + break; + case RE::ITER: { + // see note [Kleene star is expressed in terms of plus] + nfa_state_t *q = &nfa.states[nfa.size++]; + s = re_to_nfa(nfa, nrule, re->iter, q); + q->make_alt(nrule, s, t); + break; + } + case RE::REPEAT: + s = re_to_nfa(nfa, nrule, re->repeat.re, t); + for (uint32_t i = 0; i < re->repeat.upto; ++i) { + nfa_state_t *q = &nfa.states[nfa.size++]; + q->make_alt(nrule, s, t); + s = re_to_nfa(nfa, nrule, re->repeat.re, q); + } + break; + case RE::TAG: + if (fixed(nfa.tags[re->tag.idx])) { + s = t; + } else { + s = &nfa.states[nfa.size++]; + s->make_tag(nrule, t, re->tag.idx, re->tag.bottom); + } + break; + } + return s; +} + +nfa_t::nfa_t(const RESpec &spec) + : max_size(estimate_size(spec.res)) + , size(0) + , states(new nfa_state_t[max_size]) + , rules(spec.rules) + , tags(spec.tags) + , root(NULL) +{ + const size_t nre = spec.res.size(); + + if (nre == 0) return; + + for (size_t i = 0; i < nre; ++i) { + nfa_state_t *s = &states[size++]; + s->make_fin(i); + s = re_to_nfa(*this, i, spec.res[i], s); + + if (root) { + nfa_state_t *t = &states[size++]; + t->make_alt(i, root, s); + root = t; + } else { + root = s; + } + } +} + +nfa_t::~nfa_t() +{ + delete[] states; +} + +} // namespace re2c diff --git a/re2c/src/ir/nfa/regexps2nfa.cc b/re2c/src/ir/nfa/regexps2nfa.cc deleted file mode 100644 index bf8d8610..00000000 --- a/re2c/src/ir/nfa/regexps2nfa.cc +++ /dev/null @@ -1,136 +0,0 @@ -#include - -#include "src/ir/nfa/nfa.h" - -namespace re2c { - -/* note [fixed and variable tags] - * - * If distance between two tags is constant (equal for all strings that - * match the given regexp), then lexer only needs to track one of them: - * the second tag equals the first tag plus static offset. - * - * However, this optimization is applied only to tags in top-level - * concatenation, because other tags may be uninitialized and we don't - * want to mess with conditional calculation of fixed tags. - * - * Furthermore, fixed tags are fobidden with generic API because it cannot - * express fixed offsets. - */ - -// We have to insert default tags during NFA construction: before it, -// we have AST and which is immutable (it may be shared by different -// regexps); after it, we have NFA where join points of alternatives -// are lost. -// We also compute fixed / variable tags during NFA construction, because -// the order of regexp traversal determines the order in which tags are -// assigned indices. Splitting this in two passes would require maintaining -// exactly the same order of traversal, which is fragile. -static nfa_state_t *regexp2nfa(nfa_t &nfa, size_t nrule, size_t &dist, - size_t &base, bool toplevel, const RegExp *re, nfa_state_t *t) -{ - nfa_state_t *s = NULL; - switch (re->type) { - case RegExp::NIL: - s = t; - break; - case RegExp::SYM: - s = &nfa.states[nfa.size++]; - s->make_ran(nrule, t, re->sym); - - if (dist != Tag::VARDIST) ++dist; - break; - case RegExp::ALT: { - nfa_state_t *s1, *s2, *t0, *t1, *t2, *q; - size_t d1 = dist, d2 = dist, i = nfa.tags.size(); - - t0 = &nfa.states[nfa.size++]; - s1 = regexp2nfa(nfa, nrule, d1, base, false, re->alt.re1, t0); - for (t2 = t; i < nfa.tags.size(); ++i) { - q = &nfa.states[nfa.size++]; - q->make_tag(nrule, t2, i, true); - t2 = q; - } - - s2 = regexp2nfa(nfa, nrule, d2, base, false, re->alt.re2, t2); - for (t1 = t; i < nfa.tags.size(); ++i) { - q = &nfa.states[nfa.size++]; - q->make_tag(nrule, t1, i, true); - t1 = q; - } - t0->make_nil(nrule, t1); - - s = &nfa.states[nfa.size++]; - s->make_alt(nrule, s1, s2); - - dist = (d1 == d2) ? d1 : Tag::VARDIST; - break; - } - case RegExp::CAT: - s = regexp2nfa(nfa, nrule, dist, base, toplevel, re->cat.re2, t); - s = regexp2nfa(nfa, nrule, dist, base, toplevel, re->cat.re1, s); - break; - case RegExp::ITER: { - // see note [Kleene star is expressed in terms of plus] - nfa_state_t *q = &nfa.states[nfa.size++]; - s = regexp2nfa(nfa, nrule, dist, base, false, re->iter, q); - q->make_alt(nrule, s, t); - - dist = Tag::VARDIST; - break; - } - case RegExp::TAG: { - const std::string *name = re->tag; - if (toplevel && dist != Tag::VARDIST) { - Tag fix = {name, nrule, base, dist}; - nfa.tags.push_back(fix); - s = t; - } else { - const size_t ntag = nfa.tags.size(); - Tag var = {name, nrule, ntag, Tag::VARDIST}; - nfa.tags.push_back(var); - if (toplevel) { - base = ntag; - dist = 0; - } - s = &nfa.states[nfa.size++]; - s->make_tag(nrule, t, ntag, false); - } - if (name == NULL) dist = 0; - break; - } - } - return s; -} - -static nfa_state_t *regexp2nfa_rule(nfa_t &nfa, size_t nrule, - const RegExp *re, input_api_t input) -{ - const bool generic = input == INPUT_CUSTOM; - size_t base = Tag::RIGHTMOST, dist = 0; - - nfa_state_t *s = &nfa.states[nfa.size++]; - s->make_fin(nrule); - - return regexp2nfa(nfa, nrule, dist, base, !generic, re, s); -} - -void regexps2nfa(const std::vector ®exps, - nfa_t &nfa, input_api_t input) -{ - const size_t nregexps = regexps.size(); - - if (nregexps == 0) { - return; - } - - nfa_state_t *s = regexp2nfa_rule(nfa, 0, regexps[0].re, input); - for (size_t i = 1; i < nregexps; ++i) { - nfa_state_t *t = &nfa.states[nfa.size++]; - t->make_alt(i, s, regexp2nfa_rule(nfa, i, regexps[i].re, input)); - s = t; - } - nfa.root = s; -} - -} // namespace re2c diff --git a/re2c/src/ir/re/ast_to_re.cc b/re2c/src/ir/re/ast_to_re.cc new file mode 100644 index 00000000..b5f2eaed --- /dev/null +++ b/re2c/src/ir/re/ast_to_re.cc @@ -0,0 +1,117 @@ +#include "src/conf/msg.h" +#include "src/ir/re/re.h" + +namespace re2c { + +/* note [Kleene star is expressed in terms of plus] + * + * In literature Kleene star 'r*' (zero or more repetitions of 'r') + * is the basic operation. In practice it is more convenient to use + * 'r+' (one or more repetitions of 'r'), because expansion 'r+ ::= r r*' + * duplicates 'r', while expansion 'r* = r+ | ' allows to + * avoid duplication. This is more efficient in general and crucial + * in cases when duplication of 'r' is forbidden (e.g. if 'r' has tags). + */ + +/* + * note [counted repetition expansion] + * + * r{0} ;;= + * r{n} ::= r{n-1} r + * r{n,m} ::= r{n} (r{0} | ... | r{m-n}) + * r{n,} ::= r{n} r* + */ + +static RE *ast_to_re(RESpec &spec, const RegExp *ast) +{ + RE::alc_t &alc = spec.alc; + switch (ast->type) { + default: assert(false); + case RegExp::NIL: + return re_nil(alc); + case RegExp::SYM: + return re_sym(alc, ast->sym); + case RegExp::ALT: { + RE *x = ast_to_re(spec, ast->alt.re1); + RE *y = ast_to_re(spec, ast->alt.re2); + return re_alt(alc, x, y); + } + case RegExp::CAT: { + RE *x = ast_to_re(spec, ast->cat.re1); + RE *y = ast_to_re(spec, ast->cat.re2); + return re_cat(alc, x, y); + } + case RegExp::TAG: { + const size_t ntag = spec.tags.size(); + Tag tag = {ast->tag, ntag, Tag::VARDIST}; + spec.tags.push_back(tag); + return re_tag(alc, ntag, false); + } + case RegExp::ITER: { + const uint32_t + n = ast->iter.min, + m = ast->iter.max; + const RegExp *x = ast->iter.re; + + if (n == 0 && m == 0) { + return re_nil(alc); + } + + RE *y = ast_to_re(spec, x); + if (m == RegExp::MANY) { + y = re_iter(alc, y); + } else if (n == 0) { + y = re_repeat(alc, y, m - 1); + } else if (m > n) { + y = re_repeat(alc, y, m - n); + } + if (n == 0) { + y = re_alt(alc, y, re_nil(alc)); + } else { + for (uint32_t i = 1; i < n; ++i) { + y = re_cat(alc, ast_to_re(spec, x), y); + } + } + return y; + } + } +} + +static void assert_tags_used_once(const Rule &rule, const std::vector &tags) +{ + std::set names; + const std::string *name = NULL; + + for (size_t t = rule.ltag; t < rule.htag; ++t) { + name = tags[t].name; + if (name && !names.insert(*name).second) { + error("line %u: tag '%s' is used multiple times in the same rule", + rule.code->fline, name->c_str()); + exit(1); + } + } +} + +static void init_rule(Rule &rule, const Code *code, const std::vector &tags, size_t ltag) +{ + rule.code = code; + rule.ltag = ltag; + rule.htag = tags.size(); + for (rule.ttag = ltag; rule.ttag < rule.htag && tags[rule.ttag].name; ++rule.ttag); + assert_tags_used_once(rule, tags); +} + +RESpec::RESpec(const std::vector &ast) + : alc() + , res() + , tags(*new std::vector) + , rules(*new std::valarray(ast.size())) +{ + for (size_t i = 0, t; i < ast.size(); ++i) { + t = tags.size(); + res.push_back(ast_to_re(*this, ast[i].re)); + init_rule(rules[i], ast[i].code, tags, t); + } +} + +} // namespace re2c diff --git a/re2c/src/ir/re/default_tags.cc b/re2c/src/ir/re/default_tags.cc new file mode 100644 index 00000000..e943500b --- /dev/null +++ b/re2c/src/ir/re/default_tags.cc @@ -0,0 +1,54 @@ +#include "src/ir/re/re.h" + +namespace re2c { + +static void insert_default_tags(RESpec &spec, RE *re, size_t &tidx) +{ + RE::alc_t &alc = spec.alc; + switch (re->type) { + case RE::NIL: break; + case RE::SYM: break; + case RE::ALT: { + size_t i = tidx; + RE *x = re_nil(alc), *y = re_nil(alc); + insert_default_tags(spec, re->alt.re1, tidx); + for (; i < tidx; ++i) { + x = re_cat(alc, x, re_tag(alc, i, true)); + } + insert_default_tags(spec, re->alt.re2, tidx); + for (; i < tidx; ++i) { + y = re_cat(alc, y, re_tag(alc, i, true)); + } + re->alt.re1 = re_cat(alc, re->alt.re1, y); + re->alt.re2 = re_cat(alc, re->alt.re2, x); + break; + } + case RE::CAT: + insert_default_tags(spec, re->cat.re1, tidx); + insert_default_tags(spec, re->cat.re2, tidx); + break; + case RE::ITER: + insert_default_tags(spec, re->iter, tidx); + break; + case RE::REPEAT: + insert_default_tags(spec, re->repeat.re, tidx); + break; + case RE::TAG: + assert(re->tag.idx == tidx); + ++tidx; + break; + } +} + +void insert_default_tags(RESpec &spec) +{ + size_t tidx = 0; + std::vector::iterator + i = spec.res.begin(), + e = spec.res.end(); + for (; i != e; ++i) { + insert_default_tags(spec, *i, tidx); + } +} + +} // namespace re2c diff --git a/re2c/src/ir/re/fixed_tags.cc b/re2c/src/ir/re/fixed_tags.cc new file mode 100644 index 00000000..2918bd39 --- /dev/null +++ b/re2c/src/ir/re/fixed_tags.cc @@ -0,0 +1,74 @@ +#include "src/ir/re/re.h" + +namespace re2c { + +/* note [fixed and variable tags] + * + * If distance between two tags is constant (equal for all strings that + * match the given regexp), then lexer only needs to track one of them: + * the second tag equals the first tag plus static offset. + * + * However, this optimization is applied only to tags in top-level + * concatenation, because other tags may be uninitialized and we don't + * want to mess with conditional calculation of fixed tags. + * + * Furthermore, fixed tags are fobidden with generic API because it cannot + * express fixed offsets. + */ + +static void find_fixed_tags(RE *re, std::vector &tags, + size_t &dist, size_t &base, bool toplevel) +{ + switch (re->type) { + case RE::NIL: break; + case RE::SYM: + if (dist != Tag::VARDIST) ++dist; + break; + case RE::ALT: { + size_t d1 = dist, d2 = dist; + find_fixed_tags(re->alt.re1, tags, d1, base, false); + find_fixed_tags(re->alt.re2, tags, d2, base, false); + dist = (d1 == d2) ? d1 : Tag::VARDIST; + break; + } + case RE::CAT: + find_fixed_tags(re->cat.re2, tags, dist, base, toplevel); + find_fixed_tags(re->cat.re1, tags, dist, base, toplevel); + break; + case RE::ITER: + find_fixed_tags(re->iter, tags, dist, base, false); + dist = Tag::VARDIST; + break; + case RE::REPEAT: + find_fixed_tags(re->repeat.re, tags, dist, base, false); + dist = Tag::VARDIST; + break; + case RE::TAG: + if (toplevel && dist != Tag::VARDIST) { + Tag &tag = tags[re->tag.idx]; + tag.base = base; + tag.dist = dist; + } else { + if (toplevel) { + base = re->tag.idx; + dist = 0; + } + } + if (tags[re->tag.idx].name == NULL) dist = 0; + break; + } +} + +void find_fixed_tags(RESpec &spec, const opt_t *opts) +{ + const bool generic = opts->input_api == INPUT_CUSTOM; + std::vector::iterator + i = spec.res.begin(), + e = spec.res.end(); + for (; i != e; ++i) { + size_t base = Tag::RIGHTMOST, dist = 0; + find_fixed_tags(*i, spec.tags, dist, base, !generic); + } +} + +} // namespace re2c diff --git a/re2c/src/ir/re/re.h b/re2c/src/ir/re/re.h new file mode 100644 index 00000000..daac8c92 --- /dev/null +++ b/re2c/src/ir/re/re.h @@ -0,0 +1,115 @@ +#ifndef _RE2C_IR_RE_RE_ +#define _RE2C_IR_RE_RE_ + +#include "src/util/c99_stdint.h" + +#include "src/conf/opt.h" +#include "src/ir/rule.h" +#include "src/ir/regexp/regexp.h" +#include "src/util/range.h" +#include "src/util/slab_allocator.h" + +namespace re2c +{ + +struct RE +{ + typedef slab_allocator_t<~0u, 4096> alc_t; + enum type_t {NIL, SYM, ALT, CAT, ITER, REPEAT, TAG} type; + union { + const Range *sym; + struct { + RE *re1; + RE *re2; + } alt; + struct { + RE *re1; + RE *re2; + } cat; + RE *iter; + struct { + RE *re; + uint32_t upto; + } repeat; + struct { + size_t idx; + bool bottom; + } tag; + }; +}; + +struct RESpec +{ + RE::alc_t alc; + std::vector res; + std::vector &tags; + std::valarray &rules; + + explicit RESpec(const std::vector &ast); +}; + +void find_fixed_tags(RESpec &spec, const opt_t *opts); +void insert_default_tags(RESpec &spec); + +inline RE *re_nil(RE::alc_t &alc) +{ + RE *x = alc.alloct(1); + x->type = RE::NIL; + return x; +} + +inline RE *re_sym(RE::alc_t &alc, const Range *r) +{ + RE *x = alc.alloct(1); + x->type = RE::SYM; + x->sym = r; + return x; +} + +inline RE *re_alt(RE::alc_t &alc, RE *x, RE *y) +{ + RE *z = alc.alloct(1); + z->type = RE::ALT; + z->alt.re1 = x; + z->alt.re2 = y; + return z; +} + +inline RE *re_cat(RE::alc_t &alc, RE *x, RE *y) +{ + RE *z = alc.alloct(1); + z->type = RE::CAT; + z->cat.re1 = x; + z->cat.re2 = y; + return z; +} + +inline RE *re_iter(RE::alc_t &alc, RE *x) +{ + RE *y = alc.alloct(1); + y->type = RE::ITER; + y->iter = x; + return y; +} + +inline RE *re_repeat(RE::alc_t &alc, RE *x, uint32_t n) +{ + RE *y = alc.alloct(1); + y->type = RE::REPEAT; + y->repeat.re = x; + y->repeat.upto = n; + return y; +} + +inline RE *re_tag(RE::alc_t &alc, size_t i, bool b) +{ + RE *x = alc.alloct(1); + x->type = RE::TAG; + x->tag.idx = i; + x->tag.bottom = b; + return x; +} + +} // namespace re2c + +#endif // _RE2C_IR_RE_RE_ diff --git a/re2c/src/ir/regexp/nullable.cc b/re2c/src/ir/regexp/nullable.cc index 5481692d..2ce6e2f4 100644 --- a/re2c/src/ir/regexp/nullable.cc +++ b/re2c/src/ir/regexp/nullable.cc @@ -10,8 +10,10 @@ static bool nullable(const RegExp *re, bool &trail) switch (re->type) { default: assert(false); case RegExp::NIL: return true; - case RegExp::SYM: - case RegExp::ITER: return false; + case RegExp::SYM: return false; + case RegExp::ITER: + return re->iter.min == 0 + || nullable(re->iter.re, trail); case RegExp::TAG: if (re->tag == NULL) { trail = true; diff --git a/re2c/src/ir/regexp/regexp.cc b/re2c/src/ir/regexp/regexp.cc index 530f1c47..82b5b843 100644 --- a/re2c/src/ir/regexp/regexp.cc +++ b/re2c/src/ir/regexp/regexp.cc @@ -15,6 +15,8 @@ namespace re2c free_list RegExp::flist; +const uint32_t RegExp::MANY = std::numeric_limits::max(); + const RegExp *doAlt(const RegExp *re1, const RegExp *re2) { if (!re1) { @@ -129,42 +131,4 @@ const RegExp *Scanner::mkDefault() const opts->encoding.nCodeUnits())); } -/* - * note [counted repetition expansion] - * - * r{0} ;;= - * r{n} ::= r{n-1} r - * r{n,m} ::= r{n} (r{0} | ... | r{m-n}) - * r{n,} ::= r{n} r* - */ - -// see note [counted repetition expansion] -const RegExp *repeat(const RegExp *re, uint32_t n) -{ - const RegExp *r = NULL; - for (uint32_t i = 0; i < n; ++i) { - r = doCat(r, re); - } - return r; -} - -// see note [counted repetition expansion] -const RegExp *repeat_from_to(const RegExp *re, uint32_t n, uint32_t m) -{ - const RegExp *r1 = repeat(re, n); - const RegExp *r2 = NULL; - for (uint32_t i = n; i < m; ++i) { - r2 = mkAlt(doCat(re, r2), RegExp::make_nil()); - } - return doCat(r1, r2); -} - -// see note [counted repetition expansion] -const RegExp *repeat_from(const RegExp *re, uint32_t n) -{ - // see note [Kleene star is expressed in terms of plus] - return doCat(repeat(re, n), - RegExp::make_alt(RegExp::make_iter(re), RegExp::make_nil())); -} - } // namespace re2c diff --git a/re2c/src/ir/regexp/regexp.h b/re2c/src/ir/regexp/regexp.h index 92e2f613..9dba340f 100644 --- a/re2c/src/ir/regexp/regexp.h +++ b/re2c/src/ir/regexp/regexp.h @@ -32,7 +32,7 @@ typedef std::vector charset_t; struct RegExp { static free_list flist; - static const size_t NO_TAG; + static const uint32_t MANY; enum type_t {NIL, SYM, ALT, CAT, ITER, TAG} type; union @@ -48,7 +48,12 @@ struct RegExp const RegExp *re1; const RegExp *re2; } cat; - const RegExp *iter; + struct + { + const RegExp *re; + uint32_t min; + uint32_t max; + } iter; const std::string *tag; }; @@ -76,10 +81,12 @@ struct RegExp re->cat.re2 = r2; return re; } - static const RegExp *make_iter(const RegExp *r) + static const RegExp *make_iter(const RegExp *r, uint32_t n, uint32_t m) { RegExp *re = new RegExp(ITER); - re->iter = r; + re->iter.re = r; + re->iter.min = n; + re->iter.max = m; return re; } static const RegExp *make_tag(const std::string *t) @@ -118,9 +125,6 @@ void split(const std::vector &rs, std::set &cs); const RegExp *mkAlt(const RegExp *re1, const RegExp *re2); const RegExp *doAlt(const RegExp *re1, const RegExp *re2); const RegExp *doCat(const RegExp *re1, const RegExp *re2); -const RegExp *repeat(const RegExp *re, uint32_t n); -const RegExp *repeat_from_to(const RegExp *re, uint32_t n, uint32_t m); -const RegExp *repeat_from(const RegExp *re, uint32_t n); void warn_nullable(const std::vector ®exps, const std::string &cond, Warn &warn); diff --git a/re2c/src/ir/regexp/split_charset.cc b/re2c/src/ir/regexp/split_charset.cc index f2eaa9f0..f3e3424b 100644 --- a/re2c/src/ir/regexp/split_charset.cc +++ b/re2c/src/ir/regexp/split_charset.cc @@ -27,7 +27,7 @@ static void split(const RegExp* re, std::set &cs) split(re->cat.re2, cs); break; case RegExp::ITER: - split(re->iter, cs); + split(re->iter.re, cs); break; } } diff --git a/re2c/src/ir/tag.h b/re2c/src/ir/tag.h index a9ab7992..50875224 100644 --- a/re2c/src/ir/tag.h +++ b/re2c/src/ir/tag.h @@ -21,7 +21,6 @@ struct Tag static const size_t VARDIST; const std::string *name; - size_t rule; size_t base; size_t dist; }; diff --git a/re2c/src/parse/parser.ypp b/re2c/src/parse/parser.ypp index e53107a7..87d09c3c 100644 --- a/re2c/src/parse/parser.ypp +++ b/re2c/src/parse/parser.ypp @@ -333,45 +333,17 @@ term: } ; -factor: - primary - { - $$ = $1; - } - | primary closes - { - // see note [Kleene star is expressed in terms of plus] - switch($2) - { - case '*': - $$ = RegExp::make_alt(RegExp::make_iter($1), - RegExp::make_nil()); - break; - case '+': - $$ = RegExp::make_iter($1); - break; - case '?': - $$ = mkAlt($1, RegExp::make_nil()); - break; - } - } - | primary TOKEN_CLOSESIZE - { - if ($2.max == std::numeric_limits::max()) - { - $$ = repeat_from ($1, $2.min); - } - else if ($2.min == $2.max) - { - $$ = repeat ($1, $2.min); - } - else - { - $$ = repeat_from_to ($1, $2.min, $2.max); - } - $$ = $$ ? $$ : RegExp::make_nil(); +factor + : primary + | primary closes { + switch($2) { + case '*': $$ = RegExp::make_iter($1, 0, RegExp::MANY); break; + case '+': $$ = RegExp::make_iter($1, 1, RegExp::MANY); break; + case '?': $$ = RegExp::make_iter($1, 0, 1); break; } -; + } | primary TOKEN_CLOSESIZE { + $$ = RegExp::make_iter($1, $2.min, $2.max); + }; closes : close diff --git a/re2c/test/tags/conf1.i--tags--input(custom).c b/re2c/test/tags/conf1.i--tags--input(custom).c index 9cb08e4e..6780a378 100644 --- a/re2c/test/tags/conf1.i--tags--input(custom).c +++ b/re2c/test/tags/conf1.i--tags--input(custom).c @@ -37,7 +37,7 @@ static void lex(const char *s) case '7': case '8': case '9': - ZZBT (zz_4); + ZZBT (zz_1); goto yy4; default: goto yy2; } @@ -51,7 +51,7 @@ yy4: yych = YYPEEK (); switch (yych) { case '.': - ZZBT (zz_3); + ZZBT (zz_2); goto yy5; case '0': case '1': @@ -89,7 +89,7 @@ yy7: yych = YYPEEK (); switch (yych) { case '.': - ZZBT (zz_3); + ZZBT (zz_2); goto yy5; case '0': case '1': @@ -108,7 +108,7 @@ yy8: yych = YYPEEK (); switch (yych) { case '.': - ZZBT (zz_2); + ZZBT (zz_3); goto yy10; case '0': case '1': @@ -127,7 +127,7 @@ yy9: yych = YYPEEK (); switch (yych) { case '.': - ZZBT (zz_3); + ZZBT (zz_2); goto yy5; default: goto yy6; } @@ -152,7 +152,7 @@ yy11: yych = YYPEEK (); switch (yych) { case '.': - ZZBT (zz_2); + ZZBT (zz_3); goto yy10; case '0': case '1': @@ -171,7 +171,7 @@ yy12: yych = YYPEEK (); switch (yych) { case '.': - ZZBT (zz_1); + ZZBT (zz_4); goto yy14; case '0': case '1': @@ -190,7 +190,7 @@ yy13: yych = YYPEEK (); switch (yych) { case '.': - ZZBT (zz_2); + ZZBT (zz_3); goto yy10; default: goto yy6; } @@ -215,7 +215,7 @@ yy15: yych = YYPEEK (); switch (yych) { case '.': - ZZBT (zz_1); + ZZBT (zz_4); goto yy14; case '0': case '1': @@ -246,10 +246,10 @@ yy16: default: goto yy17; } yy17: - ZZCT (p3, zz_1); - ZZCT (p2, zz_2); - ZZCT (p1, zz_3); - ZZCT (p0, zz_4); + ZZCT (p0, zz_1); + ZZCT (p1, zz_2); + ZZCT (p2, zz_3); + ZZCT (p3, zz_4); { printf("%u.%u.%u.%u\n", parse_oct(p0, p1), @@ -263,7 +263,7 @@ yy18: yych = YYPEEK (); switch (yych) { case '.': - ZZBT (zz_1); + ZZBT (zz_4); goto yy14; default: goto yy6; } diff --git a/re2c/test/tags/conf1.i--tags.c b/re2c/test/tags/conf1.i--tags.c index fb9f63f2..57228b2e 100644 --- a/re2c/test/tags/conf1.i--tags.c +++ b/re2c/test/tags/conf1.i--tags.c @@ -30,7 +30,7 @@ static void lex(const char *YYCURSOR) case '7': case '8': case '9': - zz_4 = YYCURSOR; + zz_1 = YYCURSOR; goto yy4; default: goto yy2; } @@ -42,7 +42,7 @@ yy4: yych = *(YYMARKER = ++YYCURSOR); switch (yych) { case '.': - zz_3 = YYCURSOR; + zz_2 = YYCURSOR; goto yy5; case '0': case '1': @@ -78,7 +78,7 @@ yy7: yych = *++YYCURSOR; switch (yych) { case '.': - zz_3 = YYCURSOR; + zz_2 = YYCURSOR; goto yy5; case '0': case '1': @@ -96,7 +96,7 @@ yy8: yych = *++YYCURSOR; switch (yych) { case '.': - zz_2 = YYCURSOR; + zz_3 = YYCURSOR; goto yy10; case '0': case '1': @@ -114,7 +114,7 @@ yy9: yych = *++YYCURSOR; switch (yych) { case '.': - zz_3 = YYCURSOR; + zz_2 = YYCURSOR; goto yy5; default: goto yy6; } @@ -137,7 +137,7 @@ yy11: yych = *++YYCURSOR; switch (yych) { case '.': - zz_2 = YYCURSOR; + zz_3 = YYCURSOR; goto yy10; case '0': case '1': @@ -155,7 +155,7 @@ yy12: yych = *++YYCURSOR; switch (yych) { case '.': - zz_1 = YYCURSOR; + zz_4 = YYCURSOR; goto yy14; case '0': case '1': @@ -173,7 +173,7 @@ yy13: yych = *++YYCURSOR; switch (yych) { case '.': - zz_2 = YYCURSOR; + zz_3 = YYCURSOR; goto yy10; default: goto yy6; } @@ -196,7 +196,7 @@ yy15: yych = *++YYCURSOR; switch (yych) { case '.': - zz_1 = YYCURSOR; + zz_4 = YYCURSOR; goto yy14; case '0': case '1': @@ -226,10 +226,10 @@ yy16: default: goto yy17; } yy17: - p3 = zz_1; - p2 = zz_2; - p1 = zz_3; - p0 = zz_4; + p0 = zz_1; + p1 = zz_2; + p2 = zz_3; + p3 = zz_4; { printf("%u.%u.%u.%u\n", parse_oct(p0, p1), @@ -242,7 +242,7 @@ yy18: yych = *++YYCURSOR; switch (yych) { case '.': - zz_1 = YYCURSOR; + zz_4 = YYCURSOR; goto yy14; default: goto yy6; } diff --git a/re2c/test/tags/conf2.i--tags--input(custom).c b/re2c/test/tags/conf2.i--tags--input(custom).c index eda9c013..9b6c6994 100644 --- a/re2c/test/tags/conf2.i--tags--input(custom).c +++ b/re2c/test/tags/conf2.i--tags--input(custom).c @@ -107,7 +107,7 @@ yy6: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (in.yyt3); + YYBACKUPTAG (in.yyt1); goto yy7; case '0': case '1': @@ -145,7 +145,7 @@ yy9: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (in.yyt3); + YYBACKUPTAG (in.yyt1); goto yy7; case '0': case '1': @@ -183,7 +183,7 @@ yy11: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (in.yyt3); + YYBACKUPTAG (in.yyt1); goto yy7; default: goto yy8; } @@ -227,7 +227,7 @@ yy14: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (in.yyt1); + YYBACKUPTAG (in.yyt3); goto yy16; case '0': case '1': @@ -271,7 +271,7 @@ yy17: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (in.yyt1); + YYBACKUPTAG (in.yyt3); goto yy16; case '0': case '1': @@ -307,15 +307,15 @@ yy19: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (in.yyt1); + YYBACKUPTAG (in.yyt3); goto yy16; default: goto yy8; } yy20: YYSKIP (); - YYCOPYTAG (p3, in.yyt1); + YYCOPYTAG (p1, in.yyt1); YYCOPYTAG (p2, in.yyt2); - YYCOPYTAG (p1, in.yyt3); + YYCOPYTAG (p3, in.yyt3); { printf("> %u.%u.%u.%u\n", parse_oct(in.tok, p1), diff --git a/re2c/test/tags/conf2.i--tags.c b/re2c/test/tags/conf2.i--tags.c index 4448e78a..97c2313f 100644 --- a/re2c/test/tags/conf2.i--tags.c +++ b/re2c/test/tags/conf2.i--tags.c @@ -97,7 +97,7 @@ yy6: yych = *(in.mar = ++in.cur); switch (yych) { case '.': - in.yyt3 = in.cur; + in.yyt1 = in.cur; goto yy7; case '0': case '1': @@ -133,7 +133,7 @@ yy9: yych = *++in.cur; switch (yych) { case '.': - in.yyt3 = in.cur; + in.yyt1 = in.cur; goto yy7; case '0': case '1': @@ -169,7 +169,7 @@ yy11: yych = *++in.cur; switch (yych) { case '.': - in.yyt3 = in.cur; + in.yyt1 = in.cur; goto yy7; default: goto yy8; } @@ -210,7 +210,7 @@ yy14: yych = *++in.cur; switch (yych) { case '.': - in.yyt1 = in.cur; + in.yyt3 = in.cur; goto yy16; case '0': case '1': @@ -251,7 +251,7 @@ yy17: yych = *++in.cur; switch (yych) { case '.': - in.yyt1 = in.cur; + in.yyt3 = in.cur; goto yy16; case '0': case '1': @@ -285,15 +285,15 @@ yy19: yych = *++in.cur; switch (yych) { case '.': - in.yyt1 = in.cur; + in.yyt3 = in.cur; goto yy16; default: goto yy8; } yy20: ++in.cur; - p3 = in.yyt1; + p1 = in.yyt1; p2 = in.yyt2; - p1 = in.yyt3; + p3 = in.yyt3; { printf("> %u.%u.%u.%u\n", parse_oct(in.tok, p1), diff --git a/re2c/test/tags/conf3.i--tags--input(custom).c b/re2c/test/tags/conf3.i--tags--input(custom).c index fe8ebf6f..96527949 100644 --- a/re2c/test/tags/conf3.i--tags--input(custom).c +++ b/re2c/test/tags/conf3.i--tags--input(custom).c @@ -46,7 +46,7 @@ static void lex(const char *s) case '7': case '8': case '9': - YYBACKUPTAG (tags.yyt4); + YYBACKUPTAG (tags.yyt1); goto yy4; default: goto yy2; } @@ -60,7 +60,7 @@ yy4: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (tags.yyt3); + YYBACKUPTAG (tags.yyt2); goto yy5; case '0': case '1': @@ -98,7 +98,7 @@ yy7: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (tags.yyt3); + YYBACKUPTAG (tags.yyt2); goto yy5; case '0': case '1': @@ -117,7 +117,7 @@ yy8: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (tags.yyt2); + YYBACKUPTAG (tags.yyt3); goto yy10; case '0': case '1': @@ -136,7 +136,7 @@ yy9: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (tags.yyt3); + YYBACKUPTAG (tags.yyt2); goto yy5; default: goto yy6; } @@ -161,7 +161,7 @@ yy11: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (tags.yyt2); + YYBACKUPTAG (tags.yyt3); goto yy10; case '0': case '1': @@ -180,7 +180,7 @@ yy12: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (tags.yyt1); + YYBACKUPTAG (tags.yyt4); goto yy14; case '0': case '1': @@ -199,7 +199,7 @@ yy13: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (tags.yyt2); + YYBACKUPTAG (tags.yyt3); goto yy10; default: goto yy6; } @@ -224,7 +224,7 @@ yy15: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (tags.yyt1); + YYBACKUPTAG (tags.yyt4); goto yy14; case '0': case '1': @@ -255,10 +255,10 @@ yy16: default: goto yy17; } yy17: - YYCOPYTAG (p3, tags.yyt1); - YYCOPYTAG (p2, tags.yyt2); - YYCOPYTAG (p1, tags.yyt3); - YYCOPYTAG (p0, tags.yyt4); + YYCOPYTAG (p0, tags.yyt1); + YYCOPYTAG (p1, tags.yyt2); + YYCOPYTAG (p2, tags.yyt3); + YYCOPYTAG (p3, tags.yyt4); { printf("%u.%u.%u.%u\n", parse_oct(p0, p1), @@ -272,7 +272,7 @@ yy18: yych = YYPEEK (); switch (yych) { case '.': - YYBACKUPTAG (tags.yyt1); + YYBACKUPTAG (tags.yyt4); goto yy14; default: goto yy6; } diff --git a/re2c/test/tags/conf3.i--tags.c b/re2c/test/tags/conf3.i--tags.c index d7050485..dd225ca0 100644 --- a/re2c/test/tags/conf3.i--tags.c +++ b/re2c/test/tags/conf3.i--tags.c @@ -39,7 +39,7 @@ static void lex(const char *YYCURSOR) case '7': case '8': case '9': - tags.yyt4 = YYCURSOR; + tags.yyt1 = YYCURSOR; goto yy4; default: goto yy2; } @@ -51,7 +51,7 @@ yy4: yych = *(YYMARKER = ++YYCURSOR); switch (yych) { case '.': - tags.yyt3 = YYCURSOR; + tags.yyt2 = YYCURSOR; goto yy5; case '0': case '1': @@ -87,7 +87,7 @@ yy7: yych = *++YYCURSOR; switch (yych) { case '.': - tags.yyt3 = YYCURSOR; + tags.yyt2 = YYCURSOR; goto yy5; case '0': case '1': @@ -105,7 +105,7 @@ yy8: yych = *++YYCURSOR; switch (yych) { case '.': - tags.yyt2 = YYCURSOR; + tags.yyt3 = YYCURSOR; goto yy10; case '0': case '1': @@ -123,7 +123,7 @@ yy9: yych = *++YYCURSOR; switch (yych) { case '.': - tags.yyt3 = YYCURSOR; + tags.yyt2 = YYCURSOR; goto yy5; default: goto yy6; } @@ -146,7 +146,7 @@ yy11: yych = *++YYCURSOR; switch (yych) { case '.': - tags.yyt2 = YYCURSOR; + tags.yyt3 = YYCURSOR; goto yy10; case '0': case '1': @@ -164,7 +164,7 @@ yy12: yych = *++YYCURSOR; switch (yych) { case '.': - tags.yyt1 = YYCURSOR; + tags.yyt4 = YYCURSOR; goto yy14; case '0': case '1': @@ -182,7 +182,7 @@ yy13: yych = *++YYCURSOR; switch (yych) { case '.': - tags.yyt2 = YYCURSOR; + tags.yyt3 = YYCURSOR; goto yy10; default: goto yy6; } @@ -205,7 +205,7 @@ yy15: yych = *++YYCURSOR; switch (yych) { case '.': - tags.yyt1 = YYCURSOR; + tags.yyt4 = YYCURSOR; goto yy14; case '0': case '1': @@ -235,10 +235,10 @@ yy16: default: goto yy17; } yy17: - p3 = tags.yyt1; - p2 = tags.yyt2; - p1 = tags.yyt3; - p0 = tags.yyt4; + p0 = tags.yyt1; + p1 = tags.yyt2; + p2 = tags.yyt3; + p3 = tags.yyt4; { printf("%u.%u.%u.%u\n", parse_oct(p0, p1), @@ -251,7 +251,7 @@ yy18: yych = *++YYCURSOR; switch (yych) { case '.': - tags.yyt1 = YYCURSOR; + tags.yyt4 = YYCURSOR; goto yy14; default: goto yy6; } diff --git a/re2c/test/tags/copy_coalescing1.i--tags.c b/re2c/test/tags/copy_coalescing1.i--tags.c index 1092039d..220db09b 100644 --- a/re2c/test/tags/copy_coalescing1.i--tags.c +++ b/re2c/test/tags/copy_coalescing1.i--tags.c @@ -29,10 +29,10 @@ yy4: yych = *++YYCURSOR; switch (yych) { case 'c': - yyt2 = YYCURSOR; + yyt1 = YYCURSOR; goto yy5; case 'd': - yyt2 = YYCURSOR; + yyt1 = YYCURSOR; goto yy7; default: goto yy3; } @@ -44,12 +44,12 @@ yy5: switch (yych) { case 'a': goto yy9; default: - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy6; } yy6: - q = yyt1; - p = yyt2; + p = yyt1; + q = yyt2; { p q } yy7: yyaccept = 1; @@ -59,12 +59,12 @@ yy7: switch (yych) { case 'a': goto yy11; default: - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy8; } yy8: - s = yyt1; - r = yyt2; + r = yyt1; + s = yyt2; { r s } yy9: ++YYCURSOR; @@ -72,17 +72,17 @@ yy9: yych = *YYCURSOR; switch (yych) { case 'c': - yyt2 = YYCURSOR; + yyt1 = YYCURSOR; goto yy5; default: goto yy10; } yy10: YYCURSOR = YYMARKER; if (yyaccept == 0) { - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy6; } else { - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy8; } yy11: @@ -91,7 +91,7 @@ yy11: yych = *YYCURSOR; switch (yych) { case 'd': - yyt2 = YYCURSOR; + yyt1 = YYCURSOR; goto yy7; default: goto yy10; } diff --git a/re2c/test/tags/dedup4.i--tags.c b/re2c/test/tags/dedup4.i--tags.c index e649c9ed..09d343d1 100644 --- a/re2c/test/tags/dedup4.i--tags.c +++ b/re2c/test/tags/dedup4.i--tags.c @@ -15,7 +15,7 @@ yy4: yych = *++YYCURSOR; switch (yych) { case 'b': - yyt2 = YYCURSOR; + yyt1 = YYCURSOR; goto yy6; case 'c': yyt1 = yyt2 = YYCURSOR; @@ -28,8 +28,8 @@ yy4: goto yy5; } yy5: - YYCURSOR = yyt1; - p = yyt2; + p = yyt1; + YYCURSOR = yyt2; { 1 p } yy6: ++YYCURSOR; @@ -38,13 +38,13 @@ yy6: switch (yych) { case 'b': goto yy6; case 'c': - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy8; case 'd': - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy11; default: - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy5; } yy8: @@ -56,8 +56,8 @@ yy8: default: goto yy10; } yy10: - YYCURSOR = yyt1; - p = yyt2; + p = yyt1; + YYCURSOR = yyt2; { 2 p } yy11: ++YYCURSOR; @@ -86,7 +86,7 @@ yy17: yych = *++YYCURSOR; switch (yych) { case 'b': - yyt1 = yyt2 = YYCURSOR; + yyt1 = YYCURSOR; goto yy19; case 'c': yyt1 = yyt2 = YYCURSOR; @@ -105,7 +105,7 @@ yy19: switch (yych) { case 'b': goto yy19; case 'c': - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy21; default: goto yy18; } @@ -118,8 +118,8 @@ yy21: default: goto yy23; } yy23: - YYCURSOR = yyt1; - p = yyt2; + p = yyt1; + YYCURSOR = yyt2; { 2 p } } @@ -193,8 +193,8 @@ yy34: default: goto yy35; } yy35: - YYCURSOR = yyt2; p = yyt1; + YYCURSOR = yyt2; { 2 p } } @@ -261,8 +261,8 @@ yy46: default: goto yy47; } yy47: - YYCURSOR = yyt2; p = yyt1; + YYCURSOR = yyt2; { 2 p } } diff --git a/re2c/test/tags/exponential_bottoms.i--tags.c b/re2c/test/tags/exponential_bottoms.i--tags.c index 597a2bad..23cd564d 100644 --- a/re2c/test/tags/exponential_bottoms.i--tags.c +++ b/re2c/test/tags/exponential_bottoms.i--tags.c @@ -10,33 +10,33 @@ switch (yych) { case 'a': goto yy3; case 'b': - yyt3 = YYCURSOR; + yyt1 = YYCURSOR; goto yy4; case 'c': - yyt2 = yyt3 = YYCURSOR; + yyt1 = yyt2 = YYCURSOR; goto yy5; default: yyt1 = yyt2 = yyt3 = YYCURSOR; goto yy2; } yy2: - z = yyt1; + p = yyt1; q = yyt2; - p = yyt3; + z = yyt3; {} yy3: yych = *++YYCURSOR; switch (yych) { case 'b': - yyt3 = NULL; + yyt1 = NULL; goto yy4; case 'c': - yyt3 = NULL; + yyt1 = NULL; yyt2 = YYCURSOR; goto yy5; default: - yyt3 = NULL; - yyt1 = yyt2 = YYCURSOR; + yyt1 = NULL; + yyt2 = yyt3 = YYCURSOR; goto yy2; } yy4: @@ -47,12 +47,12 @@ yy4: goto yy5; default: yyt2 = NULL; - yyt1 = YYCURSOR; + yyt3 = YYCURSOR; goto yy2; } yy5: ++YYCURSOR; - yyt1 = NULL; + yyt3 = NULL; goto yy2; } diff --git a/re2c/test/tags/fix2.i--tags.c b/re2c/test/tags/fix2.i--tags.c index 585fb606..ca26c22c 100644 --- a/re2c/test/tags/fix2.i--tags.c +++ b/re2c/test/tags/fix2.i--tags.c @@ -107,11 +107,11 @@ yy18: } yy19: ++YYCURSOR; - p4 = YYCURSOR - 5; - p3 = YYCURSOR - 9; - p2 = YYCURSOR - 12; - p1 = YYCURSOR - 14; p0 = YYCURSOR - 15; + p1 = YYCURSOR - 14; + p2 = YYCURSOR - 12; + p3 = YYCURSOR - 9; + p4 = YYCURSOR - 5; { printf("'%.*s', '%.*s', '%.*s', '%.*s', '%.*s'\n", p1 - p0, p0, diff --git a/re2c/test/tags/fix2_trail.i--tags--input(custom).c b/re2c/test/tags/fix2_trail.i--tags--input(custom).c index 2d472b04..7614445b 100644 --- a/re2c/test/tags/fix2_trail.i--tags--input(custom).c +++ b/re2c/test/tags/fix2_trail.i--tags--input(custom).c @@ -19,7 +19,7 @@ static void lex(const char *s) yych = YYPEEK (); switch (yych) { case '0': - YYBACKUPTAG (yyt5); + YYBACKUPTAG (yyt1); goto yy4; default: goto yy2; } @@ -33,7 +33,7 @@ yy4: yych = YYPEEK (); switch (yych) { case '1': - YYBACKUPTAG (yyt4); + YYBACKUPTAG (yyt2); goto yy5; default: goto yy3; } @@ -75,7 +75,7 @@ yy10: yych = YYPEEK (); switch (yych) { case '3': - YYBACKUPTAG (yyt2); + YYBACKUPTAG (yyt4); goto yy11; default: goto yy6; } @@ -105,7 +105,7 @@ yy14: yych = YYPEEK (); switch (yych) { case '4': - YYBACKUPTAG (yyt1); + YYBACKUPTAG (yyt5); goto yy15; default: goto yy6; } @@ -139,11 +139,11 @@ yy18: } yy19: YYSKIP (); - YYRESTORETAG (yyt1); - YYCOPYTAG (p3, yyt2); + YYCOPYTAG (p0, yyt1); + YYCOPYTAG (p1, yyt2); YYCOPYTAG (p2, yyt3); - YYCOPYTAG (p1, yyt4); - YYCOPYTAG (p0, yyt5); + YYCOPYTAG (p3, yyt4); + YYRESTORETAG (yyt5); { printf("'%.*s', '%.*s', '%.*s', '%.*s', '%s'\n", p1 - p0, p0, diff --git a/re2c/test/tags/fix2_trail.i--tags.c b/re2c/test/tags/fix2_trail.i--tags.c index 822c582c..c6380278 100644 --- a/re2c/test/tags/fix2_trail.i--tags.c +++ b/re2c/test/tags/fix2_trail.i--tags.c @@ -107,11 +107,11 @@ yy18: } yy19: ++YYCURSOR; - YYCURSOR -= 5; - p3 = YYCURSOR - 4; - p2 = YYCURSOR - 7; - p1 = YYCURSOR - 9; p0 = YYCURSOR - 10; + p1 = YYCURSOR - 9; + p2 = YYCURSOR - 7; + p3 = YYCURSOR - 4; + YYCURSOR -= 5; { printf("'%.*s', '%.*s', '%.*s', '%.*s', '%s'\n", p1 - p0, p0, diff --git a/re2c/test/tags/fix3.i--tags.c b/re2c/test/tags/fix3.i--tags.c index bb1c808e..14cb1c73 100644 --- a/re2c/test/tags/fix3.i--tags.c +++ b/re2c/test/tags/fix3.i--tags.c @@ -12,16 +12,16 @@ static void lex(const char *YYCURSOR) yych = *YYCURSOR; switch (yych) { case '0': - yyt5 = YYCURSOR; + yyt1 = YYCURSOR; goto yy4; case '1': - yyt4 = yyt5 = YYCURSOR; + yyt1 = yyt2 = YYCURSOR; goto yy7; case '2': - yyt3 = yyt4 = yyt5 = YYCURSOR; + yyt1 = yyt2 = yyt3 = YYCURSOR; goto yy9; case '3': - yyt2 = yyt3 = yyt4 = yyt5 = YYCURSOR; + yyt1 = yyt2 = yyt3 = yyt4 = YYCURSOR; goto yy11; case '4': yyt1 = yyt2 = yyt3 = yyt4 = yyt5 = YYCURSOR; @@ -36,27 +36,27 @@ yy4: switch (yych) { case '0': goto yy4; case '1': - yyt4 = YYCURSOR; + yyt2 = YYCURSOR; goto yy7; case '2': - yyt3 = yyt4 = YYCURSOR; + yyt2 = yyt3 = YYCURSOR; goto yy9; case '3': yyt2 = yyt3 = yyt4 = YYCURSOR; goto yy11; case '4': - yyt1 = yyt2 = yyt3 = yyt4 = YYCURSOR; + yyt2 = yyt3 = yyt4 = yyt5 = YYCURSOR; goto yy13; default: - yyt1 = yyt2 = yyt3 = yyt4 = YYCURSOR; + yyt2 = yyt3 = yyt4 = yyt5 = YYCURSOR; goto yy6; } yy6: - p4 = yyt1; - p3 = yyt2; + p0 = yyt1; + p1 = yyt2; p2 = yyt3; - p1 = yyt4; - p0 = yyt5; + p3 = yyt4; + p4 = yyt5; { printf("'%.*s', '%.*s', '%.*s', '%.*s', '%.*s'\n", p1 - p0, p0, @@ -74,13 +74,13 @@ yy7: yyt3 = YYCURSOR; goto yy9; case '3': - yyt2 = yyt3 = YYCURSOR; + yyt3 = yyt4 = YYCURSOR; goto yy11; case '4': - yyt1 = yyt2 = yyt3 = YYCURSOR; + yyt3 = yyt4 = yyt5 = YYCURSOR; goto yy13; default: - yyt1 = yyt2 = yyt3 = YYCURSOR; + yyt3 = yyt4 = yyt5 = YYCURSOR; goto yy6; } yy9: @@ -88,13 +88,13 @@ yy9: switch (yych) { case '2': goto yy9; case '3': - yyt2 = YYCURSOR; + yyt4 = YYCURSOR; goto yy11; case '4': - yyt1 = yyt2 = YYCURSOR; + yyt4 = yyt5 = YYCURSOR; goto yy13; default: - yyt1 = yyt2 = YYCURSOR; + yyt4 = yyt5 = YYCURSOR; goto yy6; } yy11: @@ -102,10 +102,10 @@ yy11: switch (yych) { case '3': goto yy11; case '4': - yyt1 = YYCURSOR; + yyt5 = YYCURSOR; goto yy13; default: - yyt1 = YYCURSOR; + yyt5 = YYCURSOR; goto yy6; } yy13: diff --git a/re2c/test/tags/fix3_trail.i--tags--input(custom).c b/re2c/test/tags/fix3_trail.i--tags--input(custom).c index 5f3ee4af..28daf222 100644 --- a/re2c/test/tags/fix3_trail.i--tags--input(custom).c +++ b/re2c/test/tags/fix3_trail.i--tags--input(custom).c @@ -19,22 +19,22 @@ static void lex(const char *s) yych = YYPEEK (); switch (yych) { case '0': - YYBACKUPTAG (yyt5); + YYBACKUPTAG (yyt1); goto yy4; case '1': - YYBACKUPTAG (yyt4); - YYBACKUPTAG (yyt5); + YYBACKUPTAG (yyt1); + YYBACKUPTAG (yyt2); goto yy7; case '2': + YYBACKUPTAG (yyt1); + YYBACKUPTAG (yyt2); YYBACKUPTAG (yyt3); - YYBACKUPTAG (yyt4); - YYBACKUPTAG (yyt5); goto yy9; case '3': + YYBACKUPTAG (yyt1); YYBACKUPTAG (yyt2); YYBACKUPTAG (yyt3); YYBACKUPTAG (yyt4); - YYBACKUPTAG (yyt5); goto yy11; case '4': YYBACKUPTAG (yyt1); @@ -54,11 +54,11 @@ yy4: switch (yych) { case '0': goto yy4; case '1': - YYBACKUPTAG (yyt4); + YYBACKUPTAG (yyt2); goto yy7; case '2': + YYBACKUPTAG (yyt2); YYBACKUPTAG (yyt3); - YYBACKUPTAG (yyt4); goto yy9; case '3': YYBACKUPTAG (yyt2); @@ -66,24 +66,24 @@ yy4: YYBACKUPTAG (yyt4); goto yy11; case '4': - YYBACKUPTAG (yyt1); YYBACKUPTAG (yyt2); YYBACKUPTAG (yyt3); YYBACKUPTAG (yyt4); + YYBACKUPTAG (yyt5); goto yy13; default: - YYBACKUPTAG (yyt1); YYBACKUPTAG (yyt2); YYBACKUPTAG (yyt3); YYBACKUPTAG (yyt4); + YYBACKUPTAG (yyt5); goto yy6; } yy6: - YYRESTORETAG (yyt1); - YYCOPYTAG (p3, yyt2); + YYCOPYTAG (p0, yyt1); + YYCOPYTAG (p1, yyt2); YYCOPYTAG (p2, yyt3); - YYCOPYTAG (p1, yyt4); - YYCOPYTAG (p0, yyt5); + YYCOPYTAG (p3, yyt4); + YYRESTORETAG (yyt5); { printf("'%.*s', '%.*s', '%.*s', '%.*s', '%s'\n", p1 - p0, p0, @@ -102,18 +102,18 @@ yy7: YYBACKUPTAG (yyt3); goto yy9; case '3': - YYBACKUPTAG (yyt2); YYBACKUPTAG (yyt3); + YYBACKUPTAG (yyt4); goto yy11; case '4': - YYBACKUPTAG (yyt1); - YYBACKUPTAG (yyt2); YYBACKUPTAG (yyt3); + YYBACKUPTAG (yyt4); + YYBACKUPTAG (yyt5); goto yy13; default: - YYBACKUPTAG (yyt1); - YYBACKUPTAG (yyt2); YYBACKUPTAG (yyt3); + YYBACKUPTAG (yyt4); + YYBACKUPTAG (yyt5); goto yy6; } yy9: @@ -122,15 +122,15 @@ yy9: switch (yych) { case '2': goto yy9; case '3': - YYBACKUPTAG (yyt2); + YYBACKUPTAG (yyt4); goto yy11; case '4': - YYBACKUPTAG (yyt1); - YYBACKUPTAG (yyt2); + YYBACKUPTAG (yyt4); + YYBACKUPTAG (yyt5); goto yy13; default: - YYBACKUPTAG (yyt1); - YYBACKUPTAG (yyt2); + YYBACKUPTAG (yyt4); + YYBACKUPTAG (yyt5); goto yy6; } yy11: @@ -139,10 +139,10 @@ yy11: switch (yych) { case '3': goto yy11; case '4': - YYBACKUPTAG (yyt1); + YYBACKUPTAG (yyt5); goto yy13; default: - YYBACKUPTAG (yyt1); + YYBACKUPTAG (yyt5); goto yy6; } yy13: diff --git a/re2c/test/tags/fix3_trail.i--tags.c b/re2c/test/tags/fix3_trail.i--tags.c index 46afdc95..fd58cb28 100644 --- a/re2c/test/tags/fix3_trail.i--tags.c +++ b/re2c/test/tags/fix3_trail.i--tags.c @@ -12,16 +12,16 @@ static void lex(const char *YYCURSOR) yych = *YYCURSOR; switch (yych) { case '0': - yyt5 = YYCURSOR; + yyt1 = YYCURSOR; goto yy4; case '1': - yyt4 = yyt5 = YYCURSOR; + yyt1 = yyt2 = YYCURSOR; goto yy7; case '2': - yyt3 = yyt4 = yyt5 = YYCURSOR; + yyt1 = yyt2 = yyt3 = YYCURSOR; goto yy9; case '3': - yyt2 = yyt3 = yyt4 = yyt5 = YYCURSOR; + yyt1 = yyt2 = yyt3 = yyt4 = YYCURSOR; goto yy11; case '4': yyt1 = yyt2 = yyt3 = yyt4 = yyt5 = YYCURSOR; @@ -36,27 +36,27 @@ yy4: switch (yych) { case '0': goto yy4; case '1': - yyt4 = YYCURSOR; + yyt2 = YYCURSOR; goto yy7; case '2': - yyt3 = yyt4 = YYCURSOR; + yyt2 = yyt3 = YYCURSOR; goto yy9; case '3': yyt2 = yyt3 = yyt4 = YYCURSOR; goto yy11; case '4': - yyt1 = yyt2 = yyt3 = yyt4 = YYCURSOR; + yyt2 = yyt3 = yyt4 = yyt5 = YYCURSOR; goto yy13; default: - yyt1 = yyt2 = yyt3 = yyt4 = YYCURSOR; + yyt2 = yyt3 = yyt4 = yyt5 = YYCURSOR; goto yy6; } yy6: - YYCURSOR = yyt1; - p3 = yyt2; + p0 = yyt1; + p1 = yyt2; p2 = yyt3; - p1 = yyt4; - p0 = yyt5; + p3 = yyt4; + YYCURSOR = yyt5; { printf("'%.*s', '%.*s', '%.*s', '%.*s', '%s'\n", p1 - p0, p0, @@ -74,13 +74,13 @@ yy7: yyt3 = YYCURSOR; goto yy9; case '3': - yyt2 = yyt3 = YYCURSOR; + yyt3 = yyt4 = YYCURSOR; goto yy11; case '4': - yyt1 = yyt2 = yyt3 = YYCURSOR; + yyt3 = yyt4 = yyt5 = YYCURSOR; goto yy13; default: - yyt1 = yyt2 = yyt3 = YYCURSOR; + yyt3 = yyt4 = yyt5 = YYCURSOR; goto yy6; } yy9: @@ -88,13 +88,13 @@ yy9: switch (yych) { case '2': goto yy9; case '3': - yyt2 = YYCURSOR; + yyt4 = YYCURSOR; goto yy11; case '4': - yyt1 = yyt2 = YYCURSOR; + yyt4 = yyt5 = YYCURSOR; goto yy13; default: - yyt1 = yyt2 = YYCURSOR; + yyt4 = yyt5 = YYCURSOR; goto yy6; } yy11: @@ -102,10 +102,10 @@ yy11: switch (yych) { case '3': goto yy11; case '4': - yyt1 = YYCURSOR; + yyt5 = YYCURSOR; goto yy13; default: - yyt1 = YYCURSOR; + yyt5 = YYCURSOR; goto yy6; } yy13: diff --git a/re2c/test/tags/fix4.i--tags.c b/re2c/test/tags/fix4.i--tags.c index c21b7b29..3e5bd20e 100644 --- a/re2c/test/tags/fix4.i--tags.c +++ b/re2c/test/tags/fix4.i--tags.c @@ -22,10 +22,10 @@ yy4: yych = *(YYMARKER = ++YYCURSOR); switch (yych) { case '1': - yyt2 = YYCURSOR; + yyt1 = YYCURSOR; goto yy5; case '2': - yyt2 = YYCURSOR; + yyt1 = YYCURSOR; goto yy8; default: goto yy3; } @@ -43,10 +43,10 @@ yy8: yych = *++YYCURSOR; switch (yych) { case '3': - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy9; case '4': - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy11; default: goto yy7; } @@ -59,11 +59,11 @@ yy9: } yy11: ++YYCURSOR; - p3 = yyt1; - p1 = yyt2; + p1 = yyt1; + p3 = yyt2; + p0 = yyt1 - 1; + p2 = yyt2 - 1; p4 = YYCURSOR - 1; - p2 = yyt1 - 1; - p0 = yyt2 - 1; { printf("'%.*s', '%.*s', '%.*s', '%.*s', '%.*s'\n", p1 - p0, p0, diff --git a/re2c/test/tags/fix4_trail.i--tags--input(custom).c b/re2c/test/tags/fix4_trail.i--tags--input(custom).c index c3774770..b5fab254 100644 --- a/re2c/test/tags/fix4_trail.i--tags--input(custom).c +++ b/re2c/test/tags/fix4_trail.i--tags--input(custom).c @@ -19,7 +19,7 @@ static void lex(const char *s) yych = YYPEEK (); switch (yych) { case '0': - YYBACKUPTAG (yyt5); + YYBACKUPTAG (yyt1); goto yy4; default: goto yy2; } @@ -33,11 +33,11 @@ yy4: yych = YYPEEK (); switch (yych) { case '1': - YYBACKUPTAG (yyt4); + YYBACKUPTAG (yyt2); goto yy5; case '2': + YYBACKUPTAG (yyt2); YYBACKUPTAG (yyt3); - YYBACKUPTAG (yyt4); goto yy8; default: goto yy3; } @@ -59,11 +59,11 @@ yy8: yych = YYPEEK (); switch (yych) { case '3': - YYBACKUPTAG (yyt2); + YYBACKUPTAG (yyt4); goto yy9; case '4': - YYBACKUPTAG (yyt1); - YYBACKUPTAG (yyt2); + YYBACKUPTAG (yyt4); + YYBACKUPTAG (yyt5); goto yy11; default: goto yy7; } @@ -73,17 +73,17 @@ yy9: switch (yych) { case '3': goto yy9; case '4': - YYBACKUPTAG (yyt1); + YYBACKUPTAG (yyt5); goto yy11; default: goto yy7; } yy11: YYSKIP (); - YYRESTORETAG (yyt1); - YYCOPYTAG (p3, yyt2); + YYCOPYTAG (p0, yyt1); + YYCOPYTAG (p1, yyt2); YYCOPYTAG (p2, yyt3); - YYCOPYTAG (p1, yyt4); - YYCOPYTAG (p0, yyt5); + YYCOPYTAG (p3, yyt4); + YYRESTORETAG (yyt5); { printf("'%.*s', '%.*s', '%.*s', '%.*s', '%s'\n", p1 - p0, p0, diff --git a/re2c/test/tags/fix4_trail.i--tags.c b/re2c/test/tags/fix4_trail.i--tags.c index 97e37032..a0db0bfb 100644 --- a/re2c/test/tags/fix4_trail.i--tags.c +++ b/re2c/test/tags/fix4_trail.i--tags.c @@ -22,10 +22,10 @@ yy4: yych = *(YYMARKER = ++YYCURSOR); switch (yych) { case '1': - yyt2 = YYCURSOR; + yyt1 = YYCURSOR; goto yy5; case '2': - yyt2 = YYCURSOR; + yyt1 = YYCURSOR; goto yy8; default: goto yy3; } @@ -43,10 +43,10 @@ yy8: yych = *++YYCURSOR; switch (yych) { case '3': - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy9; case '4': - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy11; default: goto yy7; } @@ -59,11 +59,11 @@ yy9: } yy11: ++YYCURSOR; - p3 = yyt1; - p1 = yyt2; + p1 = yyt1; + p3 = yyt2; + p0 = yyt1 - 1; + p2 = yyt2 - 1; YYCURSOR -= 1; - p2 = yyt1 - 1; - p0 = yyt2 - 1; { printf("'%.*s', '%.*s', '%.*s', '%.*s', '%s'\n", p1 - p0, p0, diff --git a/re2c/test/tags/fix5.i--tags.c b/re2c/test/tags/fix5.i--tags.c index 1acbb9b2..adeb04c6 100644 --- a/re2c/test/tags/fix5.i--tags.c +++ b/re2c/test/tags/fix5.i--tags.c @@ -12,10 +12,10 @@ static void lex(const char *YYCURSOR) yych = *YYCURSOR; switch (yych) { case '0': - yyt3 = YYCURSOR; + yyt1 = YYCURSOR; goto yy4; case '1': - yyt3 = YYCURSOR; + yyt1 = YYCURSOR; goto yy5; default: goto yy2; } @@ -72,14 +72,14 @@ yy10: } yy12: yych = *++YYCURSOR; - yyt1 = YYCURSOR; + yyt3 = YYCURSOR; goto yy15; yy13: - p4 = yyt1; + p0 = yyt1; p2 = yyt2; - p0 = yyt3; - p3 = yyt1 - 1; + p4 = yyt3; p1 = yyt2 - 1; + p3 = yyt3 - 1; { printf("'%.*s', '%.*s', '%.*s', '%.*s', '%.*s'\n", p1 - p0, p0, diff --git a/re2c/test/tags/fix5_trail.i--tags--input(custom).c b/re2c/test/tags/fix5_trail.i--tags--input(custom).c index 4e0d10f7..c2e3316b 100644 --- a/re2c/test/tags/fix5_trail.i--tags--input(custom).c +++ b/re2c/test/tags/fix5_trail.i--tags--input(custom).c @@ -19,11 +19,11 @@ static void lex(const char *s) yych = YYPEEK (); switch (yych) { case '0': - YYBACKUPTAG (yyt5); + YYBACKUPTAG (yyt2); goto yy4; case '1': YYBACKUPTAG (yyt1); - YYBACKUPTAG (yyt5); + YYBACKUPTAG (yyt2); goto yy5; default: goto yy2; } @@ -46,7 +46,7 @@ yy5: yych = YYPEEK (); switch (yych) { case '2': - YYBACKUPTAG (yyt4); + YYBACKUPTAG (yyt3); goto yy10; case '3': YYBACKUPTAG (yyt3); @@ -73,7 +73,7 @@ yy9: yych = YYPEEK (); switch (yych) { case '2': - YYBACKUPTAG (yyt4); + YYBACKUPTAG (yyt3); goto yy10; case '3': YYBACKUPTAG (yyt3); @@ -87,21 +87,21 @@ yy10: switch (yych) { case '2': goto yy10; case '3': - YYBACKUPTAG (yyt3); + YYBACKUPTAG (yyt4); goto yy12; default: goto yy8; } yy12: YYSKIP (); yych = YYPEEK (); - YYBACKUPTAG (yyt2); + YYBACKUPTAG (yyt5); goto yy15; yy13: - YYRESTORETAG (yyt2); - YYCOPYTAG (p3, yyt3); - YYCOPYTAG (p2, yyt4); + YYCOPYTAG (p0, yyt2); YYCOPYTAG (p1, yyt1); - YYCOPYTAG (p0, yyt5); + YYCOPYTAG (p2, yyt3); + YYCOPYTAG (p3, yyt4); + YYRESTORETAG (yyt5); { printf("'%.*s', '%.*s', '%.*s', '%.*s', '%s'\n", p1 - p0, p0, diff --git a/re2c/test/tags/fix5_trail.i--tags.c b/re2c/test/tags/fix5_trail.i--tags.c index c0f40af0..634eff2d 100644 --- a/re2c/test/tags/fix5_trail.i--tags.c +++ b/re2c/test/tags/fix5_trail.i--tags.c @@ -12,10 +12,10 @@ static void lex(const char *YYCURSOR) yych = *YYCURSOR; switch (yych) { case '0': - yyt3 = YYCURSOR; + yyt1 = YYCURSOR; goto yy4; case '1': - yyt3 = YYCURSOR; + yyt1 = YYCURSOR; goto yy5; default: goto yy2; } @@ -72,14 +72,14 @@ yy10: } yy12: yych = *++YYCURSOR; - yyt1 = YYCURSOR; + yyt3 = YYCURSOR; goto yy15; yy13: - YYCURSOR = yyt1; + p0 = yyt1; p2 = yyt2; - p0 = yyt3; - p3 = yyt1 - 1; + YYCURSOR = yyt3; p1 = yyt2 - 1; + p3 = yyt3 - 1; { printf("'%.*s', '%.*s', '%.*s', '%.*s', '%s'\n", p1 - p0, p0, diff --git a/re2c/test/tags/interference.i--tags.c b/re2c/test/tags/interference.i--tags.c index 420dc1d6..2567e19e 100644 --- a/re2c/test/tags/interference.i--tags.c +++ b/re2c/test/tags/interference.i--tags.c @@ -17,8 +17,8 @@ goto yy2; } yy2: - q = yyt1; - p = yyt2; + p = yyt1; + q = yyt2; {} yy3: ++YYCURSOR; @@ -26,8 +26,8 @@ yy3: yych = *YYCURSOR; switch (yych) { case 'b': - yyt4 = NULL; - yyt3 = YYCURSOR; + yyt3 = NULL; + yyt4 = YYCURSOR; goto yy5; default: goto yy4; } diff --git a/re2c/test/tags/lost_yybackuptag.i--tags--no-lookahead--input(custom).c b/re2c/test/tags/lost_yybackuptag.i--tags--no-lookahead--input(custom).c index ac61caf2..8eda6987 100644 --- a/re2c/test/tags/lost_yybackuptag.i--tags--no-lookahead--input(custom).c +++ b/re2c/test/tags/lost_yybackuptag.i--tags--no-lookahead--input(custom).c @@ -16,8 +16,8 @@ goto yy2; } yy2: - YYCOPYTAG (b, yyt2); YYCOPYTAG (a, yyt1); + YYCOPYTAG (b, yyt2); {} } diff --git a/re2c/test/tags/tags_in_trail.i--tags.c b/re2c/test/tags/tags_in_trail.i--tags.c index c291dd92..7d9687b5 100644 --- a/re2c/test/tags/tags_in_trail.i--tags.c +++ b/re2c/test/tags/tags_in_trail.i--tags.c @@ -11,7 +11,7 @@ yy0: switch (yych) { case 'a': goto yy1; case 'b': - yyt2 = YYCURSOR; + yyt1 = YYCURSOR; goto yy4; case 'c': yyt1 = yyt2 = YYCURSOR; @@ -21,8 +21,8 @@ yy0: goto yy3; } yy3: - p = yyt1; - YYCURSOR = yyt2; + YYCURSOR = yyt1; + p = yyt2; {} yy4: ++YYCURSOR; @@ -31,10 +31,10 @@ yy4: switch (yych) { case 'b': goto yy4; case 'c': - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy6; default: - yyt1 = YYCURSOR; + yyt2 = YYCURSOR; goto yy3; } yy6: diff --git a/re2c/test/tags/twopass.i--tags.c b/re2c/test/tags/twopass.i--tags.c index 5e2e616a..6d0f796b 100644 --- a/re2c/test/tags/twopass.i--tags.c +++ b/re2c/test/tags/twopass.i--tags.c @@ -20,8 +20,8 @@ goto yy3; } yy2: - s = yyt4; r = yyt1; + s = yyt4; {} yy3: yyaccept = 1; @@ -76,9 +76,9 @@ yy6: goto yy8; } yy7: - y = yyt2; - q = yyt3; p = yyt1; + q = yyt2; + y = yyt3; {} yy8: yyaccept = 3; @@ -125,12 +125,12 @@ yy13: switch (yych) { case 'a': goto yy17; case 'b': - yyt3 = NULL; - yyt2 = YYCURSOR; + yyt2 = NULL; + yyt3 = YYCURSOR; goto yy18; default: - yyt3 = NULL; - yyt2 = YYCURSOR; + yyt2 = NULL; + yyt3 = YYCURSOR; goto yy15; } yy14: @@ -192,19 +192,19 @@ yy21: switch (yych) { case 'a': goto yy5; case 'b': - yyt3 = NULL; - yyt2 = YYCURSOR; + yyt2 = NULL; + yyt3 = YYCURSOR; goto yy18; default: - yyt3 = NULL; - yyt2 = YYCURSOR; + yyt2 = NULL; + yyt3 = YYCURSOR; goto yy15; } } re2c: warning: line 7: rule matches empty string [-Wmatch-empty-string] -re2c: warning: line 6: tag 'y' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] -re2c: warning: line 6: tag 'q' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] re2c: warning: line 6: tag 'p' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] -re2c: warning: line 7: tag 's' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] +re2c: warning: line 6: tag 'q' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] +re2c: warning: line 6: tag 'y' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] re2c: warning: line 7: tag 'r' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] +re2c: warning: line 7: tag 's' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] diff --git a/re2c/test/tags/uniq.i--tags.c b/re2c/test/tags/uniq.i--tags.c index 6a8be080..f209235d 100644 --- a/re2c/test/tags/uniq.i--tags.c +++ b/re2c/test/tags/uniq.i--tags.c @@ -25,12 +25,12 @@ yy3: default: goto yy4; } yy4: - z = yyt1; - y = yyt1; - x = yyt1; - w = yyt1; - v = yyt1; u = yyt1; + v = yyt1; + w = yyt1; + x = yyt1; + y = yyt1; + z = yyt1; {} yy5: ++YYCURSOR; @@ -48,9 +48,9 @@ yy6: } re2c: warning: line 6: rule matches empty string [-Wmatch-empty-string] -re2c: warning: line 5: tag 'z' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] -re2c: warning: line 5: tag 'y' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] -re2c: warning: line 5: tag 'x' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] -re2c: warning: line 5: tag 'w' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] -re2c: warning: line 5: tag 'v' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] re2c: warning: line 5: tag 'u' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] +re2c: warning: line 5: tag 'v' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] +re2c: warning: line 5: tag 'w' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] +re2c: warning: line 5: tag 'x' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] +re2c: warning: line 5: tag 'y' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] +re2c: warning: line 5: tag 'z' is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] -- 2.40.0