From 455a6e00352261dcf1fbe8de4da9e260a8eb71d5 Mon Sep 17 00:00:00 2001 From: Ulya Trofimovich Date: Tue, 27 Dec 2016 17:00:09 +0000 Subject: [PATCH] Finally separated parsing, consistensy checking and after-parse transformation. Updates in test results are caused by the changed order of condition compilation, see commit b7bbbf471778b487d0717c85a5e586b595e495ec. Changes do not affect code generation, only the error messages. --- re2c/bootstrap/src/parse/lex.cc | 2 +- re2c/bootstrap/src/parse/parser.cc | 639 ++++++++---------- re2c/bootstrap/src/parse/y.tab.h | 1 - re2c/src/ir/compile.cc | 19 +- re2c/src/ir/compile.h | 8 +- re2c/src/ir/nfa/counters.cc | 4 +- re2c/src/ir/nfa/init_rules.cc | 4 +- re2c/src/ir/nfa/nfa.cc | 2 +- re2c/src/ir/nfa/nfa.h | 10 +- re2c/src/ir/nfa/regexps2nfa.cc | 10 +- re2c/src/ir/regexp/nullable.cc | 8 +- re2c/src/ir/regexp/regexp.cc | 1 - re2c/src/ir/regexp/regexp.h | 23 +- re2c/src/ir/regexp/split_charset.cc | 4 +- re2c/src/parse/parser.h | 50 +- re2c/src/parse/parser.ypp | 397 +++++------ re2c/test/cond_error_09.c.c | 2 +- ....c--emit-dot--flex-syntax--case-inverted.c | 4 +- ...scanner.igcd--flex-syntax--case-inverted.c | 4 +- ...cd--skeleton--flex-syntax--case-inverted.c | 4 +- ...zend_ini_scanner_trimmed.ic--flex-syntax.c | 4 +- ...nd_ini_scanner_trimmed.icwb--flex-syntax.c | 4 +- 22 files changed, 536 insertions(+), 668 deletions(-) diff --git a/re2c/bootstrap/src/parse/lex.cc b/re2c/bootstrap/src/parse/lex.cc index 724c47cd..2ba20d90 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 Sun Dec 25 18:10:05 2016 */ +/* Generated by re2c 0.16 on Tue Dec 27 16:57:27 2016 */ #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 6ebed3c3..db5eee84 100644 --- a/re2c/bootstrap/src/parse/parser.cc +++ b/re2c/bootstrap/src/parse/parser.cc @@ -101,8 +101,8 @@ using namespace re2c; extern "C" { -int yylex(Scanner &in, context_t&); -void yyerror(Scanner &in, context_t&, const char*); +int yylex(context_t &context); +void yyerror(context_t &context, const char*); } // extern "C" @@ -113,157 +113,122 @@ void yyerror(Scanner &in, context_t&, const char*); #define __attribute__(x) #endif -static void parse_cleanup(re2c::context_t &context) +static void check(const specs_t &specs, bool cflag) { - RegExp::flist.clear(); - Code::flist.clear(); - Range::vFreeList.clear(); - RangeSuffix::freeList.clear(); - context.clear(); -} - -static void check_default(const Spec &spec, const std::string &cond) -{ - Spec::const_iterator - e = spec.end(), - i = std::find_if(spec.begin(), e, RegExpRule::is_def), - j = std::find_if(i + 1, e, RegExpRule::is_def); - if (j != e) { - error("line %u: code to default rule %sis already defined at line %u", - (*j)->code->fline, incond(cond).c_str(), (*i)->code->fline); - exit(1); - } -} - -static void check(const context_t &context, bool cflag) -{ - const SpecMap &specs = context.specMap; - const SetupMap &setups = context.ruleSetupMap; - const size_t nspec = specs.size(); - - for (SpecMap::const_iterator i = specs.begin(); i != specs.end(); ++i) { - check_default(i->second, i->first); + specs_t::const_iterator i, + b = specs.begin(), + e = specs.end(); + + for (i = b; i != e; ++i) { + if (i->defs.size() > 1) { + error("line %u: code to default rule %sis already defined at line %u", + i->defs[1]->fline, incond(i->name).c_str(), i->defs[0]->fline); + exit(1); + } } - check_default(context.spec_all, "*"); if (!cflag) { - static const uint32_t NOL = ~0u; - uint32_t l = NOL; - for (SpecMap::const_iterator i = specs.begin(); i != specs.end(); ++i) { - if (i->first != "") { - l = std::min(l, i->second[0]->code->fline); + for (i = b; i != e; ++i) { + if (i->name != "") { + error("line %u: conditions are only allowed" + " with '-c', '--conditions' option", + i->rules[0].code->fline); + exit(1); } } - if (!context.spec_all.empty()) { - l = std::min(l, context.spec_all[0]->code->fline); - } - if (!setups.empty()) { - l = std::min(l, setups.begin()->second->fline); - } - if (context.startup) { - l = std::min(l, context.startup->fline); - } - if (l != NOL) { - error("line %u: conditions are only allowed with '-c', '--conditions' option", l); - exit(1); - } } else { - SpecMap::const_iterator i = specs.find(""); - if (i != specs.end()) { - error("line %u: non-conditional rules are not allowed with '-c', '--conditions' option", - i->second[0]->code->fline); - exit(1); + for (i = b; i != e; ++i) { + if (i->name == "") { + error("line %u: non-conditional rules are not allowed" + " with '-c', '--conditions' option", + i->rules[0].code->fline); + exit(1); + } } - for (SetupMap::const_iterator i = setups.begin(); i != setups.end(); ++i) { - const std::string c = i->first; - if (c != "*" && specs.find(c) == specs.end()) { + + for (i = b; i != e; ++i) { + if (i->setup.size() > 1) { + error("line %u: code to setup rule '%s' is already defined at line %u", + i->setup[1]->fline, i->name.c_str(), i->setup[0]->fline); + exit(1); + } + } + + for (i = b; i != e; ++i) { + if (i->name != "*" && !i->setup.empty() && i->rules.empty()) { error("line %u: setup for non existing condition '%s' found", - i->second->fline, c.c_str()); + i->setup[0]->fline, i->name.c_str()); exit(1); } } - if (setups.size() > nspec) { - SetupMap::const_iterator i = setups.find("*"); - if (i != setups.end()) { - error("line %u: setup for all conditions '' is illegal " - "if setup for each condition is defined explicitly", - i->second->fline); + + for (i = b; i != e && !i->setup.empty(); ++i); + if (i == e) { + for (i = b; i != e; ++i) { + if (i->name == "*") { + error("line %u: setup for all conditions '' is illegal " + "if setup for each condition is defined explicitly", + i->setup[0]->fline); + exit(1); + } + } + } + + for (i = b; i != e; ++i) { + if (i->name == "0" && i->rules.size() > 1) { + error("line %u: startup code is already defined at line %u", + i->rules[1].code->fline, i->rules[0].code->fline); exit(1); } } } } -static void delay_default(Spec &spec) +static void prepare(specs_t &specs, const Scanner &in) { - // default rule(s) should go last - std::stable_partition(spec.begin(), spec.end(), RegExpRule::isnt_def); -} + specs_t::iterator i, b = specs.begin(), e = specs.end(); -static void make_rule(context_t &context, RegExpRule *rule, const Code *code) -{ - rule->code = code; - context.specMap[""].push_back(rule); -} + // merge <*> rules and setup to all conditions except "0" + // star rules must have lower priority than normal rules + for (i = b; i != e && i->name != "*"; ++i); + if (i != e) { + const specs_t::iterator star = i; -static void make_cond(context_t &context, CondList *clist, - RegExpRule *rule, const Code *code) -{ - rule->code = code; - for(CondList::const_iterator i = clist->begin(); i != clist->end(); ++i) { - const std::string &cond = *i; - if (context.specMap.find(cond) == context.specMap.end()) { - context.condnames.push_back(cond); - } - context.specMap[cond].push_back(rule); - } - delete clist; -} + for (i = b; i != e; ++i) { + if (i == star || i->name == "0") continue; -static void make_star(context_t &context, RegExpRule *rule, const Code *code) -{ - rule->code = code; - context.spec_all.push_back(rule); -} + i->rules.insert(i->rules.end(), star->rules.begin(), star->rules.end()); + i->defs.insert(i->defs.end(), star->defs.begin(), star->defs.end()); + i->setup.insert(i->setup.end(), star->setup.begin(), star->setup.end()); + } -static void make_zero(context_t &context, const Code *code) -{ - if (context.startup) { - error("line %u: startup code is already defined at line %u", - code->fline, context.startup->fline); - exit(1); + specs.erase(star); + e = specs.end(); } - context.startup = code; -} -static void make_setup(Scanner &in, SetupMap &ruleSetupMap, - CondList *clist, const Code *code) -{ - if (!clist) { - clist = new CondList; - clist->insert("*"); - } - assert(code); - for (CondList::const_iterator i = clist->begin(); i != clist->end(); ++i) { - if (ruleSetupMap.find(*i) != ruleSetupMap.end()) { - in.fatalf_at(code->fline, "code to setup rule '%s' is already defined", i->c_str()); + // merge default rule with the lowest priority + for (i = b; i != e; ++i) { + if (!i->defs.empty()) { + i->rules.push_back(RegExpRule(in.mkDefault(), i->defs[0])); } - ruleSetupMap[*i] = code; } - delete clist; + + // "0" condition must be the first one + for (i = b; i != e && i->name != "0"; ++i); + if (i != e && i != b) { + const spec_t zero = *i; + specs.erase(i); + specs.insert(specs.begin(), zero); + } } -static std::string find_setup_rule(const SetupMap &map, const std::string &key) +static spec_t &find(specs_t &specs, const std::string &name) { - SetupMap::const_iterator e = map.end(), i; - - i = map.find(key); - if (i != e) return i->second->text; - - i = map.find("*"); - if (i != e) return i->second->text; - - return ""; + for (specs_t::iterator i = specs.begin(); i != specs.end(); ++i) { + if (i->name == name) return *i; + } + specs.push_back(spec_t(name)); + return specs.back(); } @@ -317,7 +282,6 @@ typedef union YYSTYPE re2c::ExtOp extop; std::string * str; re2c::CondList * clist; - re2c::RegExpRule *rule; @@ -545,16 +509,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 71 +#define YYLAST 66 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 25 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 16 +#define YYNNTS 17 /* YYNRULES -- Number of rules. */ -#define YYNRULES 42 +#define YYNRULES 43 /* YYNRULES -- Number of states. */ -#define YYNSTATES 72 +#define YYNSTATES 70 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 @@ -570,9 +534,9 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, - 23, 24, 15, 21, 18, 2, 2, 10, 2, 2, + 23, 24, 13, 21, 18, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 12, - 13, 11, 14, 22, 2, 2, 2, 2, 2, 2, + 14, 11, 15, 22, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 20, 2, 2, 2, 2, 2, 2, 2, @@ -601,39 +565,38 @@ static const yytype_uint8 yytranslate[] = static const yytype_uint8 yyprhs[] = { 0, 0, 3, 4, 7, 10, 13, 17, 21, 24, - 26, 28, 30, 33, 39, 45, 49, 55, 61, 63, - 68, 73, 75, 79, 81, 85, 87, 89, 93, 95, - 99, 101, 104, 106, 109, 112, 114, 117, 119, 121, - 123, 125, 127 + 26, 28, 30, 33, 36, 42, 48, 54, 58, 60, + 65, 70, 72, 74, 76, 80, 82, 86, 88, 92, + 94, 98, 100, 103, 105, 108, 111, 113, 116, 118, + 120, 122, 124, 126 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 26, 0, -1, -1, 26, 5, -1, 26, 27, -1, - 26, 30, -1, 28, 34, 29, -1, 28, 34, 10, + 26, 30, -1, 28, 35, 29, -1, 28, 35, 10, -1, 6, 11, -1, 7, -1, 12, -1, 8, -1, - 33, 4, -1, 13, 32, 14, 33, 31, -1, 13, - 15, 14, 33, 31, -1, 13, 14, 31, -1, 13, - 16, 32, 14, 4, -1, 13, 16, 15, 14, 4, - -1, 4, -1, 11, 14, 6, 4, -1, 17, 11, - 14, 6, -1, 6, -1, 32, 18, 6, -1, 34, - -1, 34, 10, 34, -1, 15, -1, 35, -1, 34, - 19, 35, -1, 36, -1, 35, 20, 36, -1, 37, - -1, 36, 37, -1, 40, -1, 40, 38, -1, 40, - 3, -1, 39, -1, 38, 39, -1, 15, -1, 21, - -1, 22, -1, 6, -1, 9, -1, 23, 34, 24, - -1 + 34, 4, -1, 13, 4, -1, 14, 32, 15, 34, + 31, -1, 14, 32, 15, 13, 31, -1, 14, 16, + 32, 15, 4, -1, 14, 15, 31, -1, 4, -1, + 11, 15, 6, 4, -1, 17, 11, 15, 6, -1, + 33, -1, 13, -1, 6, -1, 33, 18, 6, -1, + 35, -1, 35, 10, 35, -1, 36, -1, 35, 19, + 36, -1, 37, -1, 36, 20, 37, -1, 38, -1, + 37, 38, -1, 41, -1, 41, 39, -1, 41, 3, + -1, 40, -1, 39, 40, -1, 13, -1, 21, -1, + 22, -1, 6, -1, 9, -1, 23, 35, 24, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 238, 238, 240, 241, 242, 246, 253, 258, 261, - 265, 265, 268, 272, 276, 280, 284, 288, 293, 295, - 301, 308, 314, 321, 325, 330, 335, 339, 346, 350, - 357, 361, 368, 372, 389, 408, 409, 413, 414, 415, - 419, 429, 433 + 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 }; #endif @@ -644,10 +607,10 @@ static const char *const yytname[] = { "$end", "error", "$undefined", "TOKEN_CLOSESIZE", "TOKEN_CODE", "TOKEN_CONF", "TOKEN_ID", "TOKEN_FID", "TOKEN_FID_END", "TOKEN_REGEXP", - "'/'", "'='", "';'", "'<'", "'>'", "'*'", "'!'", "':'", "','", "'|'", + "'/'", "'='", "';'", "'*'", "'<'", "'>'", "'!'", "':'", "','", "'|'", "'\\\\'", "'+'", "'?'", "'('", "')'", "$accept", "spec", "def", "name", - "enddef", "rule", "ccode", "clist", "trailexpr", "expr", "diff", "term", - "factor", "closes", "close", "primary", 0 + "enddef", "rule", "ccode", "clist", "conds", "trailexpr", "expr", "diff", + "term", "factor", "closes", "close", "primary", 0 }; #endif @@ -657,7 +620,7 @@ static const char *const yytname[] = static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 47, 61, 59, 60, 62, 42, 33, 58, 44, 124, + 47, 61, 59, 42, 60, 62, 33, 58, 44, 124, 92, 43, 63, 40, 41 }; # endif @@ -667,19 +630,19 @@ static const yytype_uint8 yyr1[] = { 0, 25, 26, 26, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 30, 30, 30, 30, 31, 31, - 31, 32, 32, 33, 33, 33, 34, 34, 35, 35, - 36, 36, 37, 37, 37, 38, 38, 39, 39, 39, - 40, 40, 40 + 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, + 36, 37, 37, 38, 38, 38, 39, 39, 40, 40, + 40, 41, 41, 41 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 0, 2, 2, 2, 3, 3, 2, 1, - 1, 1, 2, 5, 5, 3, 5, 5, 1, 4, - 4, 1, 3, 1, 3, 1, 1, 3, 1, 3, - 1, 2, 1, 2, 2, 1, 2, 1, 1, 1, - 1, 1, 3 + 1, 1, 2, 2, 5, 5, 5, 3, 1, 4, + 4, 1, 1, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 2, 1, 2, 2, 1, 2, 1, 1, + 1, 1, 1, 3 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -687,21 +650,20 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 2, 0, 1, 3, 40, 9, 41, 0, 25, 0, - 4, 0, 5, 0, 23, 26, 28, 30, 32, 8, - 21, 0, 0, 0, 0, 40, 0, 0, 12, 0, - 0, 0, 31, 34, 37, 38, 39, 33, 35, 18, - 0, 0, 15, 0, 0, 0, 0, 0, 42, 11, - 7, 10, 6, 24, 27, 29, 36, 0, 0, 0, - 0, 0, 0, 22, 0, 0, 14, 17, 16, 13, - 19, 20 + 2, 0, 1, 3, 41, 9, 42, 0, 0, 0, + 4, 0, 5, 0, 25, 27, 29, 31, 33, 8, + 13, 23, 22, 0, 0, 0, 21, 41, 0, 0, + 12, 0, 0, 0, 32, 35, 38, 39, 40, 34, + 36, 18, 0, 0, 17, 0, 0, 0, 43, 11, + 7, 10, 6, 26, 28, 30, 37, 0, 0, 0, + 0, 0, 24, 0, 0, 16, 15, 14, 19, 20 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 1, 10, 11, 52, 12, 42, 24, 13, 14, - 15, 16, 17, 37, 38, 18 + -1, 1, 10, 11, 52, 12, 44, 25, 26, 13, + 14, 15, 16, 17, 39, 40, 18 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing @@ -709,21 +671,20 @@ static const yytype_int8 yydefgoto[] = #define YYPACT_NINF -17 static const yytype_int8 yypact[] = { - -17, 1, -17, -17, -8, -17, -17, 29, -17, 9, - -17, 9, -17, 7, 27, -15, 9, -17, 6, -17, - -17, 8, -1, 32, 35, -17, 17, 21, -17, 9, - 9, 9, -17, -17, -17, -17, -17, 33, -17, -17, - 16, 12, -17, 11, 28, 38, 11, 44, -17, -17, - -17, -17, -17, 40, -15, 9, -17, 45, 48, 8, - 59, 60, 8, -17, 61, 62, -17, -17, -17, -17, - -17, -17 + -17, 1, -17, -17, -2, -17, -17, 14, 29, 20, + -17, 20, -17, 23, 3, 30, 20, -17, -1, -17, + -17, -17, -17, 0, 25, 34, 35, -17, 27, 22, + -17, 20, 20, 20, -17, -17, -17, -17, -17, 15, + -17, -17, 37, 43, -17, 40, 10, 50, -17, -17, + -17, -17, -17, 21, 30, 20, -17, 51, 44, 54, + 0, 0, -17, 56, 55, -17, -17, -17, -17, -17 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -17, -17, -17, -17, -17, -17, -2, 43, 15, -7, - 37, 39, -16, -17, 34, -17 + -17, -17, -17, -17, -17, -17, -13, 38, -17, 17, + -6, 32, 33, -16, -17, 26, -17 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -733,40 +694,37 @@ static const yytype_int8 yypgoto[] = #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { - 32, 2, 26, 19, 27, 31, 3, 4, 5, 33, - 6, 28, 39, 43, 7, 25, 8, 25, 6, 40, - 6, 34, 53, 58, 9, 41, 8, 35, 36, 49, - 57, 50, 9, 51, 9, 20, 30, 29, 20, 32, - 30, 48, 60, 21, 22, 23, 30, 44, 34, 46, - 63, 64, 61, 47, 35, 36, 47, 66, 59, 30, - 69, 62, 65, 67, 68, 70, 45, 54, 71, 0, - 55, 56 + 34, 2, 35, 28, 41, 29, 3, 4, 5, 19, + 6, 42, 36, 31, 7, 8, 27, 43, 20, 6, + 37, 38, 32, 60, 9, 53, 27, 30, 36, 6, + 49, 21, 50, 9, 51, 21, 37, 38, 22, 34, + 32, 32, 22, 9, 23, 24, 32, 66, 67, 46, + 33, 48, 57, 47, 58, 59, 62, 63, 65, 64, + 68, 69, 45, 61, 54, 56, 55 }; -static const yytype_int8 yycheck[] = +static const yytype_uint8 yycheck[] = { - 16, 0, 9, 11, 11, 20, 5, 6, 7, 3, - 9, 4, 4, 14, 13, 6, 15, 6, 9, 11, - 9, 15, 29, 11, 23, 17, 15, 21, 22, 8, - 14, 10, 23, 12, 23, 6, 19, 10, 6, 55, - 19, 24, 14, 14, 15, 16, 19, 15, 15, 14, - 6, 6, 14, 18, 21, 22, 18, 59, 43, 19, - 62, 46, 14, 4, 4, 4, 23, 30, 6, -1, - 31, 37 + 16, 0, 3, 9, 4, 11, 5, 6, 7, 11, + 9, 11, 13, 10, 13, 14, 6, 17, 4, 9, + 21, 22, 19, 13, 23, 31, 6, 4, 13, 9, + 8, 6, 10, 23, 12, 6, 21, 22, 13, 55, + 19, 19, 13, 23, 15, 16, 19, 60, 61, 15, + 20, 24, 15, 18, 11, 15, 6, 6, 4, 15, + 4, 6, 24, 46, 32, 39, 33 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 26, 0, 5, 6, 7, 9, 13, 15, 23, - 27, 28, 30, 33, 34, 35, 36, 37, 40, 11, - 6, 14, 15, 16, 32, 6, 34, 34, 4, 10, - 19, 20, 37, 3, 15, 21, 22, 38, 39, 4, - 11, 17, 31, 14, 15, 32, 14, 18, 24, 8, - 10, 12, 29, 34, 35, 36, 39, 14, 11, 33, - 14, 14, 33, 6, 6, 14, 31, 4, 4, 31, - 4, 6 + 0, 26, 0, 5, 6, 7, 9, 13, 14, 23, + 27, 28, 30, 34, 35, 36, 37, 38, 41, 11, + 4, 6, 13, 15, 16, 32, 33, 6, 35, 35, + 4, 10, 19, 20, 38, 3, 13, 21, 22, 39, + 40, 4, 11, 17, 31, 32, 15, 18, 24, 8, + 10, 12, 29, 35, 36, 37, 40, 15, 11, 15, + 13, 34, 6, 6, 15, 4, 31, 31, 4, 6 }; #define yyerrok (yyerrstatus = 0) @@ -808,7 +766,7 @@ do \ } \ else \ { \ - yyerror (in, context, YY_("syntax error: cannot back up")); \ + yyerror (context, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) @@ -865,7 +823,7 @@ while (YYID (0)) #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else -# define YYLEX yylex (in, context) +# define YYLEX yylex (context) #endif /* Enable debugging if requested. */ @@ -888,7 +846,7 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value, in, context); \ + Type, Value, context); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) @@ -902,20 +860,18 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, Scanner &in, context_t &context) +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, context_t &context) #else static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep, in, context) +yy_symbol_value_print (yyoutput, yytype, yyvaluep, context) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; - Scanner ∈ context_t &context; #endif { if (!yyvaluep) return; - YYUSE (in); YYUSE (context); # ifdef YYPRINT if (yytype < YYNTOKENS) @@ -938,14 +894,13 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, in, context) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, Scanner &in, context_t &context) +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, context_t &context) #else static void -yy_symbol_print (yyoutput, yytype, yyvaluep, in, context) +yy_symbol_print (yyoutput, yytype, yyvaluep, context) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; - Scanner ∈ context_t &context; #endif { @@ -954,7 +909,7 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, in, context) else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, in, context); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, context); YYFPRINTF (yyoutput, ")"); } @@ -997,13 +952,12 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule, Scanner &in, context_t &context) +yy_reduce_print (YYSTYPE *yyvsp, int yyrule, context_t &context) #else static void -yy_reduce_print (yyvsp, yyrule, in, context) +yy_reduce_print (yyvsp, yyrule, context) YYSTYPE *yyvsp; int yyrule; - Scanner ∈ context_t &context; #endif { @@ -1018,7 +972,7 @@ yy_reduce_print (yyvsp, yyrule, in, context) YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) - , in, context); + , context); YYFPRINTF (stderr, "\n"); } } @@ -1026,7 +980,7 @@ yy_reduce_print (yyvsp, yyrule, in, context) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyvsp, Rule, in, context); \ + yy_reduce_print (yyvsp, Rule, context); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that @@ -1277,19 +1231,17 @@ yysyntax_error (char *yyresult, int yystate, int yychar) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, Scanner &in, context_t &context) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, context_t &context) #else static void -yydestruct (yymsg, yytype, yyvaluep, in, context) +yydestruct (yymsg, yytype, yyvaluep, context) const char *yymsg; int yytype; YYSTYPE *yyvaluep; - Scanner ∈ context_t &context; #endif { YYUSE (yyvaluep); - YYUSE (in); YYUSE (context); if (!yymsg) @@ -1313,7 +1265,7 @@ int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus -int yyparse (Scanner &in, context_t &context); +int yyparse (context_t &context); #else int yyparse (); #endif @@ -1349,11 +1301,10 @@ yyparse (YYPARSE_PARAM) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int -yyparse (Scanner &in, context_t &context) +yyparse (context_t &context) #else int -yyparse (in, context) - Scanner ∈ +yyparse (context) context_t &context; #endif #endif @@ -1602,8 +1553,8 @@ yyreduce: case 6: { - if (!context.symbol_table.insert(std::make_pair(*(yyvsp[(1) - (3)].str), (yyvsp[(2) - (3)].regexp))).second) { - in.fatal("sym already defined"); + if (!context.symtab.insert(std::make_pair(*(yyvsp[(1) - (3)].str), (yyvsp[(2) - (3)].regexp))).second) { + context.input.fatal("sym already defined"); } delete (yyvsp[(1) - (3)].str); ;} @@ -1612,7 +1563,7 @@ yyreduce: case 7: { - in.fatal("trailing contexts are not allowed in named definitions"); + context.input.fatal("trailing contexts are not allowed in named definitions"); ;} break; @@ -1633,42 +1584,51 @@ yyreduce: case 12: { - make_rule(context, (yyvsp[(1) - (2)].rule), (yyvsp[(2) - (2)].code)); + find(context.specs, "").rules.push_back(RegExpRule((yyvsp[(1) - (2)].regexp), (yyvsp[(2) - (2)].code))); ;} break; case 13: { - make_cond(context, (yyvsp[(2) - (5)].clist), (yyvsp[(4) - (5)].rule), (yyvsp[(5) - (5)].code)); + find(context.specs, "").defs.push_back((yyvsp[(2) - (2)].code)); ;} break; case 14: { - make_star(context, (yyvsp[(4) - (5)].rule), (yyvsp[(5) - (5)].code)); + for(CondList::const_iterator i = (yyvsp[(2) - (5)].clist)->begin(); i != (yyvsp[(2) - (5)].clist)->end(); ++i) { + find(context.specs, *i).rules.push_back(RegExpRule((yyvsp[(4) - (5)].regexp), (yyvsp[(5) - (5)].code))); + } + delete (yyvsp[(2) - (5)].clist); ;} break; case 15: { - make_zero(context, (yyvsp[(3) - (3)].code)); + for(CondList::const_iterator i = (yyvsp[(2) - (5)].clist)->begin(); i != (yyvsp[(2) - (5)].clist)->end(); ++i) { + find(context.specs, *i).defs.push_back((yyvsp[(5) - (5)].code)); + } + delete (yyvsp[(2) - (5)].clist); ;} break; case 16: { - make_setup(in, context.ruleSetupMap, (yyvsp[(3) - (5)].clist), (yyvsp[(5) - (5)].code)); + for (CondList::const_iterator i = (yyvsp[(3) - (5)].clist)->begin(); i != (yyvsp[(3) - (5)].clist)->end(); ++i) { + find(context.specs, *i).setup.push_back((yyvsp[(5) - (5)].code)); + } + delete (yyvsp[(3) - (5)].clist); ;} break; case 17: { - make_setup(in, context.ruleSetupMap, NULL, (yyvsp[(5) - (5)].code)); + find(context.specs, "0").rules.push_back(RegExpRule(RegExp::make_nil(), (yyvsp[(3) - (3)].code))); ;} break; @@ -1684,102 +1644,95 @@ yyreduce: case 20: { - (yyval.code) = new Code(in.get_fname(), in.get_cline()); + (yyval.code) = new Code(context.input.get_fname(), context.input.get_cline()); (yyval.code)->cond = *(yyvsp[(4) - (4)].str); delete (yyvsp[(4) - (4)].str); ;} break; - case 21: - - { - (yyval.clist) = new CondList; - (yyval.clist)->insert(*(yyvsp[(1) - (1)].str)); - delete (yyvsp[(1) - (1)].str); - ;} - break; - case 22: { - (yyvsp[(1) - (3)].clist)->insert(*(yyvsp[(3) - (3)].str)); - delete (yyvsp[(3) - (3)].str); - (yyval.clist) = (yyvsp[(1) - (3)].clist); + (yyval.clist) = new CondList; + (yyval.clist)->insert("*"); ;} break; case 23: { - (yyval.rule) = new RegExpRule((yyvsp[(1) - (1)].regexp), false); + (yyval.clist) = new CondList; + (yyval.clist)->insert(*(yyvsp[(1) - (1)].str)); + delete (yyvsp[(1) - (1)].str); ;} break; case 24: { - (yyval.rule) = new RegExpRule(RegExp::make_cat((yyvsp[(1) - (3)].regexp), - RegExp::make_cat(RegExp::make_tag(NULL), (yyvsp[(3) - (3)].regexp))), false); + (yyvsp[(1) - (3)].clist)->insert(*(yyvsp[(3) - (3)].str)); + delete (yyvsp[(3) - (3)].str); + (yyval.clist) = (yyvsp[(1) - (3)].clist); ;} break; - case 25: + case 26: - { /* default rule */ - (yyval.rule) = new RegExpRule(in.mkDefault(), true); + { + (yyval.regexp) = RegExp::make_cat((yyvsp[(1) - (3)].regexp), RegExp::make_cat(RegExp::make_tag(NULL), (yyvsp[(3) - (3)].regexp))); ;} break; - case 26: + case 27: { (yyval.regexp) = (yyvsp[(1) - (1)].regexp); ;} break; - case 27: + case 28: { (yyval.regexp) = mkAlt((yyvsp[(1) - (3)].regexp), (yyvsp[(3) - (3)].regexp)); ;} break; - case 28: + case 29: { (yyval.regexp) = (yyvsp[(1) - (1)].regexp); ;} break; - case 29: + case 30: { - (yyval.regexp) = in.mkDiff((yyvsp[(1) - (3)].regexp), (yyvsp[(3) - (3)].regexp)); + (yyval.regexp) = context.input.mkDiff((yyvsp[(1) - (3)].regexp), (yyvsp[(3) - (3)].regexp)); ;} break; - case 30: + case 31: { (yyval.regexp) = (yyvsp[(1) - (1)].regexp); ;} break; - case 31: + case 32: { (yyval.regexp) = RegExp::make_cat((yyvsp[(1) - (2)].regexp), (yyvsp[(2) - (2)].regexp)); ;} break; - case 32: + case 33: { (yyval.regexp) = (yyvsp[(1) - (1)].regexp); ;} break; - case 33: + case 34: { // see note [Kleene star is expressed in terms of plus] @@ -1799,7 +1752,7 @@ yyreduce: ;} break; - case 34: + case 35: { if ((yyvsp[(2) - (2)].extop).max == std::numeric_limits::max()) @@ -1818,47 +1771,46 @@ yyreduce: ;} break; - case 36: + case 37: { (yyval.op) = ((yyvsp[(1) - (2)].op) == (yyvsp[(2) - (2)].op)) ? (yyvsp[(1) - (2)].op) : '*'; ;} break; - case 37: + case 38: { (yyval.op) = '*'; ;} break; - case 38: + case 39: { (yyval.op) = '+'; ;} break; - case 39: + case 40: { (yyval.op) = '?'; ;} break; - case 40: + case 41: { - symbol_table_t::iterator i = context.symbol_table.find (* (yyvsp[(1) - (1)].str)); + symtab_t::iterator i = context.symtab.find(*(yyvsp[(1) - (1)].str)); delete (yyvsp[(1) - (1)].str); - if (i == context.symbol_table.end ()) - { - in.fatal("can't find symbol"); + if (i == context.symtab.end()) { + context.input.fatal("can't find symbol"); } (yyval.regexp) = i->second; ;} break; - case 41: + case 42: { (yyval.regexp) = (yyvsp[(1) - (1)].regexp); ;} break; - case 42: + case 43: { (yyval.regexp) = (yyvsp[(2) - (3)].regexp); @@ -1901,7 +1853,7 @@ yyerrlab: { ++yynerrs; #if ! YYERROR_VERBOSE - yyerror (in, context, YY_("syntax error")); + yyerror (context, YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); @@ -1925,11 +1877,11 @@ yyerrlab: if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (in, context, yymsg); + yyerror (context, yymsg); } else { - yyerror (in, context, YY_("syntax error")); + yyerror (context, YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } @@ -1953,7 +1905,7 @@ yyerrlab: else { yydestruct ("Error: discarding", - yytoken, &yylval, in, context); + yytoken, &yylval, context); yychar = YYEMPTY; } } @@ -2009,7 +1961,7 @@ yyerrlab1: yydestruct ("Error: popping", - yystos[yystate], yyvsp, in, context); + yystos[yystate], yyvsp, context); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); @@ -2044,7 +1996,7 @@ yyabortlab: | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: - yyerror (in, context, YY_("memory exhausted")); + yyerror (context, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif @@ -2052,7 +2004,7 @@ yyexhaustedlab: yyreturn: if (yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, in, context); + yytoken, &yylval, context); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -2060,7 +2012,7 @@ yyreturn: while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, in, context); + yystos[*yyssp], yyvsp, context); YYPOPSTACK (1); } #ifndef yyoverflow @@ -2081,14 +2033,14 @@ yyreturn: extern "C" { -void yyerror(Scanner &in, context_t&, const char* s) +void yyerror(context_t &context, const char* s) { - in.fatal(s); + context.input.fatal(s); } -int yylex(Scanner &in, context_t&) +int yylex(context_t &context) { - return in.scan(); + return context.input.scan(); } } // extern "C" @@ -2096,111 +2048,97 @@ int yylex(Scanner &in, context_t&) namespace re2c { -void parse(Scanner &in, Output & o) +void parse(Scanner &input, Output & o) { - dfa_map_t dfa_map; - context_t context; + specs_t specs; + symtab_t symtab; + dfas_t dfas; ScannerState rules_state, curr_state; - Opt &opts = in.opts; + Opt &opts = input.opts; o.source.wversion_time () - .wline_info (in.get_cline (), in.get_fname ().c_str ()); + .wline_info (input.get_cline (), input.get_fname ().c_str ()); if (opts->target == opt_t::SKELETON) { emit_prolog (o.source); } Enc encodingOld = opts->encoding; - for (Scanner::ParseMode mode; (mode = in.echo()) != Scanner::Stop;) { + for (Scanner::ParseMode mode; (mode = input.echo()) != Scanner::Stop;) { o.source.new_block (); bool bPrologBrace = false; - in.save_state(curr_state); - if (opts->rFlag && mode == Scanner::Rules && dfa_map.size()) + input.save_state(curr_state); + if (opts->rFlag && mode == Scanner::Rules && !dfas.empty()) { - in.fatal("cannot have a second 'rules:re2c' block"); + input.fatal("cannot have a second 'rules:re2c' block"); } if (mode == Scanner::Reuse) { - if (dfa_map.empty()) + if (dfas.empty()) { - in.fatal("got 'use:re2c' without 'rules:re2c'"); + input.fatal("got 'use:re2c' without 'rules:re2c'"); } } else if (mode == Scanner::Rules) { - in.save_state(rules_state); + input.save_state(rules_state); } else { - dfa_map.clear(); + dfas.clear(); } - context.specMap.clear(); - yyparse(in, context); + + // parse next re2c block + context_t context = {input, specs, symtab}; + specs.clear(); + yyparse(context); if (opts->rFlag && mode == Scanner::Reuse) { - if (!context.specMap.empty() || opts->encoding != encodingOld) { + if (!specs.empty() || opts->encoding != encodingOld) { // Re-parse rules mode = Scanner::Parse; - in.restore_state(rules_state); - in.reuse(); - dfa_map.clear(); - parse_cleanup(context); - context.specMap.clear(); - yyparse(in, context); + input.restore_state(rules_state); + input.reuse(); + dfas.clear(); + specs.clear(); + symtab.clear(); + yyparse(context); // Now append potential new rules - in.restore_state(curr_state); + input.restore_state(curr_state); mode = Scanner::Parse; - yyparse(in, context); + yyparse(context); } encodingOld = opts->encoding; } - o.source.block().line = in.get_cline(); - // compile regular expressions to automata if (mode != Scanner::Reuse) { - check(context, opts->cFlag); - - // merge <*> rules to all conditions except "0" with lowest priority - for (SpecMap::iterator it = context.specMap.begin(); it != context.specMap.end(); ++it) { - it->second.insert(it->second.end(), context.spec_all.begin(), context.spec_all.end()); - } - - // insert "0" condition - if (context.startup) { - RegExpRule *zero = new RegExpRule(RegExp::make_nil(), false); - zero->code = context.startup; - context.condnames.insert(context.condnames.begin(), "0"); // first - context.specMap["0"].push_back(zero); + check(specs, opts->cFlag); + prepare(specs, input); + o.source.block().line = input.get_cline(); + for (specs_t::const_iterator i = specs.begin(); i != specs.end(); ++i) { + dfas.push_back(compile(*i, o)); } + } - for (SpecMap::iterator it = context.specMap.begin(); it != context.specMap.end(); ++it) { - delay_default(it->second); - const std::string &setup = find_setup_rule(context.ruleSetupMap, it->first); - dfa_map[it->first] = compile(it->second, o, it->first, setup); + for (dfas_t::const_iterator i = dfas.begin(); i != dfas.end(); ++i) { + const std::string &c = (*i)->cond; + if (c != "") { + o.source.block().types.push_back(c); } } - o.source.block().types = context.condnames; - // generate code if (mode != Scanner::Rules) { uint32_t ind = opts->topIndent; - size_t nCount = dfa_map.size(); - if (dfa_map.find("") != dfa_map.end()) { - dfa_map[""]->emit(o, ind, !--nCount, bPrologBrace); - } else { - std::vector::const_iterator - i = context.condnames.begin(), - e = context.condnames.end(); - for (; i != e; ++i) { - dfa_map[*i]->emit(o, ind, !--nCount, bPrologBrace); - } + size_t nCount = dfas.size(); + for (dfas_t::const_iterator i = dfas.begin(); i != dfas.end(); ++i) { + (*i)->emit(o, ind, !--nCount, bPrologBrace); } } - o.source.wline_info (in.get_cline (), in.get_fname ().c_str ()); + o.source.wline_info (input.get_cline (), input.get_fname ().c_str ()); /* restore original char handling mode*/ opts.reset_encoding (encodingOld); } @@ -2210,7 +2148,10 @@ void parse(Scanner &in, Output & o) emit_epilog (o.source, o.skeletons); } - parse_cleanup(context); + RegExp::flist.clear(); + Code::flist.clear(); + Range::vFreeList.clear(); + RangeSuffix::freeList.clear(); } } // end namespace re2c diff --git a/re2c/bootstrap/src/parse/y.tab.h b/re2c/bootstrap/src/parse/y.tab.h index 2d512327..6f9bebf6 100644 --- a/re2c/bootstrap/src/parse/y.tab.h +++ b/re2c/bootstrap/src/parse/y.tab.h @@ -61,7 +61,6 @@ typedef union YYSTYPE re2c::ExtOp extop; std::string * str; re2c::CondList * clist; - re2c::RegExpRule *rule; diff --git a/re2c/src/ir/compile.cc b/re2c/src/ir/compile.cc index c913a250..9238f50d 100644 --- a/re2c/src/ir/compile.cc +++ b/re2c/src/ir/compile.cc @@ -27,16 +27,21 @@ static std::string make_name(const std::string &cond, uint32_t line) return name; } -smart_ptr compile(const Spec &rules, Output &output, - const std::string &cond, const std::string &setup) +smart_ptr compile(const spec_t &spec, Output &output) { - const size_t defrule = !rules.empty() && RegExpRule::is_def(*rules.rbegin()) - ? rules.size() - 1 : Rule::NONE; - const uint32_t line = output.source.block().line; - const std::string name = make_name(cond, line); Opt &opts = output.source.opts; Warn &warn = output.source.warn; - const uint32_t cunits = opts->encoding.nCodeUnits(); + const std::vector &rules = spec.rules; + const size_t defrule = spec.defs.empty() + ? Rule::NONE + : rules.size() - 1; + const uint32_t + line = output.source.block().line, + cunits = opts->encoding.nCodeUnits(); + const std::string + &cond = spec.name, + name = make_name(cond, line), + &setup = spec.setup.empty() ? "" : spec.setup[0]->text; warn_nullable(rules, cond, warn); diff --git a/re2c/src/ir/compile.h b/re2c/src/ir/compile.h index 896a46d4..d268d7a6 100644 --- a/re2c/src/ir/compile.h +++ b/re2c/src/ir/compile.h @@ -1,20 +1,14 @@ #ifndef _RE2C_IR_COMPILE_ #define _RE2C_IR_COMPILE_ -#include "src/util/c99_stdint.h" -#include - #include "src/parse/parser.h" -#include "src/util/smart_ptr.h" namespace re2c { -class DFA; struct Output; -smart_ptr compile(const Spec &spec, Output &output, - const std::string &cond, const std::string &setup); +smart_ptr compile(const spec_t &spec, Output &output); } // namespace re2c diff --git a/re2c/src/ir/nfa/counters.cc b/re2c/src/ir/nfa/counters.cc index 48e863f1..d77edc86 100644 --- a/re2c/src/ir/nfa/counters.cc +++ b/re2c/src/ir/nfa/counters.cc @@ -30,12 +30,12 @@ static size_t count(const RegExp *re, size_t &ntags) } } -size_t counters(const std::vector ®exps, size_t &ntags) +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; + size += count(regexps[i].re, ntags) + 1; } return size; } diff --git a/re2c/src/ir/nfa/init_rules.cc b/re2c/src/ir/nfa/init_rules.cc index f1399b7d..09a31dcd 100644 --- a/re2c/src/ir/nfa/init_rules.cc +++ b/re2c/src/ir/nfa/init_rules.cc @@ -29,7 +29,7 @@ error: exit(1); } -void init_rules(const std::vector ®exps, +void init_rules(const std::vector ®exps, std::valarray &rules, const std::vector &vartags, const std::vector &fixtags) { @@ -40,7 +40,7 @@ void init_rules(const std::vector ®exps, for (size_t r = 0, v = 0, f = 0, t; r < nr; ++r) { Rule &rule = rules[r]; - rule.code = regexps[r]->code; + rule.code = regexps[r].code; rule.lvar = v; for (; v < nv && vartags[v].rule == r; ++v); diff --git a/re2c/src/ir/nfa/nfa.cc b/re2c/src/ir/nfa/nfa.cc index f3a08643..3924782c 100644 --- a/re2c/src/ir/nfa/nfa.cc +++ b/re2c/src/ir/nfa/nfa.cc @@ -2,7 +2,7 @@ namespace re2c { -nfa_t::nfa_t(const std::vector ®exps, InputAPI::type_t input) +nfa_t::nfa_t(const std::vector ®exps, InputAPI::type_t input) : max_size(0) , size(0) , states(NULL) diff --git a/re2c/src/ir/nfa/nfa.h b/re2c/src/ir/nfa/nfa.h index 3cf21e41..dba90f94 100644 --- a/re2c/src/ir/nfa/nfa.h +++ b/re2c/src/ir/nfa/nfa.h @@ -94,16 +94,16 @@ struct nfa_t std::vector &fixtags; nfa_state_t *root; - nfa_t(const std::vector &rs, InputAPI::type_t input); + nfa_t(const std::vector &rs, InputAPI::type_t input); ~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, InputAPI::type_t input); -bool nullable_rule(const RegExpRule *rule); -void init_rules(const std::vector ®exps, std::valarray &rules, +size_t counters(const std::vector ®exps, size_t &ntags); +void regexps2nfa(const std::vector ®exps, nfa_t &nfa, InputAPI::type_t input); +bool nullable_rule(const RegExpRule &rule); +void init_rules(const std::vector ®exps, std::valarray &rules, const std::vector &vartags, const std::vector &fixtags); } // namespace re2c diff --git a/re2c/src/ir/nfa/regexps2nfa.cc b/re2c/src/ir/nfa/regexps2nfa.cc index d286f9d6..62b0a7bb 100644 --- a/re2c/src/ir/nfa/regexps2nfa.cc +++ b/re2c/src/ir/nfa/regexps2nfa.cc @@ -106,7 +106,7 @@ static nfa_state_t *regexp2nfa(nfa_t &nfa, size_t nrule, size_t &dist, } static nfa_state_t *regexp2nfa_rule(nfa_t &nfa, size_t nrule, - const RegExpRule *rule, InputAPI::type_t input) + const RegExp *re, InputAPI::type_t input) { const bool generic = input == InputAPI::CUSTOM; size_t base = FixTag::RIGHTMOST, dist = 0; @@ -114,10 +114,10 @@ static nfa_state_t *regexp2nfa_rule(nfa_t &nfa, size_t nrule, nfa_state_t *s = &nfa.states[nfa.size++]; s->make_fin(nrule); - return regexp2nfa(nfa, nrule, dist, base, !generic, rule->re, s); + return regexp2nfa(nfa, nrule, dist, base, !generic, re, s); } -void regexps2nfa(const std::vector ®exps, +void regexps2nfa(const std::vector ®exps, nfa_t &nfa, InputAPI::type_t input) { const size_t nregexps = regexps.size(); @@ -126,10 +126,10 @@ void regexps2nfa(const std::vector ®exps, return; } - nfa_state_t *s = regexp2nfa_rule(nfa, 0, regexps[0], input); + 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], input)); + t->make_alt(i, s, regexp2nfa_rule(nfa, i, regexps[i].re, input)); s = t; } nfa.root = s; diff --git a/re2c/src/ir/regexp/nullable.cc b/re2c/src/ir/regexp/nullable.cc index 83b1e98b..5481692d 100644 --- a/re2c/src/ir/regexp/nullable.cc +++ b/re2c/src/ir/regexp/nullable.cc @@ -31,15 +31,15 @@ static bool nullable(const RegExp *re, bool &trail) * (including rules with nonempty trailing context) * false positives on partially self-shadowed rules like [^]? */ -void warn_nullable(const std::vector ®exps, +void warn_nullable(const std::vector ®exps, const std::string &cond, Warn &warn) { const size_t nregexps = regexps.size(); for (size_t i = 0; i < nregexps; ++i) { - const RegExpRule *r = regexps[i]; + const RegExpRule &r = regexps[i]; bool trail = false; - if (nullable(r->re, trail)) { - warn.match_empty_string(r->code->fline, cond); + if (nullable(r.re, trail)) { + warn.match_empty_string(r.code->fline, cond); } } } diff --git a/re2c/src/ir/regexp/regexp.cc b/re2c/src/ir/regexp/regexp.cc index d8992985..584b1f7f 100644 --- a/re2c/src/ir/regexp/regexp.cc +++ b/re2c/src/ir/regexp/regexp.cc @@ -14,7 +14,6 @@ namespace re2c { free_list RegExp::flist; -free_list RegExpRule::flist; const RegExp *doAlt(const RegExp *re1, const RegExp *re2) { diff --git a/re2c/src/ir/regexp/regexp.h b/re2c/src/ir/regexp/regexp.h index 94f86484..92e2f613 100644 --- a/re2c/src/ir/regexp/regexp.h +++ b/re2c/src/ir/regexp/regexp.h @@ -105,36 +105,23 @@ private: struct RegExpRule { - static free_list flist; - const RegExp *re; const Code *code; - bool def; - RegExpRule(const RegExp *r, bool d) + RegExpRule(const RegExp *r, const Code *c) : re(r) - , code(NULL) - , def(d) - { - flist.insert(this); - } - ~RegExpRule() - { - flist.erase(this); - } - static bool is_def(const RegExpRule *r) { return r->def; } - static bool isnt_def(const RegExpRule *r) { return !r->def; } - FORBID_COPY(RegExpRule); + , code(c) + {} }; -void split(const std::vector &rs, std::set &cs); +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, +void warn_nullable(const std::vector ®exps, const std::string &cond, Warn &warn); } // end namespace re2c diff --git a/re2c/src/ir/regexp/split_charset.cc b/re2c/src/ir/regexp/split_charset.cc index f900cc2a..f2eaa9f0 100644 --- a/re2c/src/ir/regexp/split_charset.cc +++ b/re2c/src/ir/regexp/split_charset.cc @@ -32,11 +32,11 @@ static void split(const RegExp* re, std::set &cs) } } -void split(const std::vector &rs, std::set &cs) +void split(const std::vector &rs, std::set &cs) { const size_t nrs = rs.size(); for (size_t i = 0; i < nrs; ++i) { - split(rs[i]->re, cs); + split(rs[i].re, cs); } } diff --git a/re2c/src/parse/parser.h b/re2c/src/parse/parser.h index 36524248..ec23cf4c 100644 --- a/re2c/src/parse/parser.h +++ b/re2c/src/parse/parser.h @@ -7,7 +7,6 @@ #include "src/codegen/output.h" #include "src/ir/regexp/regexp.h" #include "src/parse/scanner.h" -#include "src/util/forbid_copy.h" #include "src/util/smart_ptr.h" namespace re2c @@ -15,42 +14,29 @@ namespace re2c struct DFA; -void parse(Scanner &, Output &); +void parse(Scanner &input, Output &output); +struct spec_t +{ + std::string name; + std::vector rules; + std::vector defs; + std::vector setup; + + explicit spec_t(const std::string &n): + name(n), rules(), defs(), setup() {} +}; + +typedef std::vector specs_t; typedef std::set CondList; -typedef std::vector Spec; -typedef std::map SpecMap; -typedef std::map SetupMap; -typedef std::map symbol_table_t; -typedef std::map > dfa_map_t; +typedef std::map symtab_t; +typedef std::vector > dfas_t; struct context_t { - std::vector condnames; - SpecMap specMap; - Spec spec_all; - SetupMap ruleSetupMap; - const Code *startup; - symbol_table_t symbol_table; - - context_t() - : condnames() - , specMap() - , spec_all() - , ruleSetupMap() - , startup(NULL) - , symbol_table() - {} - void clear() - { - condnames.clear(); - specMap.clear(); - spec_all.clear(); - startup = NULL; - ruleSetupMap.clear(); - symbol_table.clear(); - } - FORBID_COPY(context_t); + Scanner &input; + specs_t &specs; + symtab_t &symtab; }; } // namespace re2c diff --git a/re2c/src/parse/parser.ypp b/re2c/src/parse/parser.ypp index 77e6544f..f5e0da8c 100644 --- a/re2c/src/parse/parser.ypp +++ b/re2c/src/parse/parser.ypp @@ -33,8 +33,8 @@ using namespace re2c; extern "C" { -int yylex(Scanner &in, context_t&); -void yyerror(Scanner &in, context_t&, const char*); +int yylex(context_t &context); +void yyerror(context_t &context, const char*); } // extern "C" @@ -45,165 +45,128 @@ void yyerror(Scanner &in, context_t&, const char*); #define __attribute__(x) #endif -static void parse_cleanup(re2c::context_t &context) +static void check(const specs_t &specs, bool cflag) { - RegExp::flist.clear(); - Code::flist.clear(); - Range::vFreeList.clear(); - RangeSuffix::freeList.clear(); - context.clear(); -} - -static void check_default(const Spec &spec, const std::string &cond) -{ - Spec::const_iterator - e = spec.end(), - i = std::find_if(spec.begin(), e, RegExpRule::is_def), - j = std::find_if(i + 1, e, RegExpRule::is_def); - if (j != e) { - error("line %u: code to default rule %sis already defined at line %u", - (*j)->code->fline, incond(cond).c_str(), (*i)->code->fline); - exit(1); - } -} - -static void check(const context_t &context, bool cflag) -{ - const SpecMap &specs = context.specMap; - const SetupMap &setups = context.ruleSetupMap; - const size_t nspec = specs.size(); - - for (SpecMap::const_iterator i = specs.begin(); i != specs.end(); ++i) { - check_default(i->second, i->first); + specs_t::const_iterator i, + b = specs.begin(), + e = specs.end(); + + for (i = b; i != e; ++i) { + if (i->defs.size() > 1) { + error("line %u: code to default rule %sis already defined at line %u", + i->defs[1]->fline, incond(i->name).c_str(), i->defs[0]->fline); + exit(1); + } } - check_default(context.spec_all, "*"); if (!cflag) { - static const uint32_t NOL = ~0u; - uint32_t l = NOL; - for (SpecMap::const_iterator i = specs.begin(); i != specs.end(); ++i) { - if (i->first != "") { - l = std::min(l, i->second[0]->code->fline); + for (i = b; i != e; ++i) { + if (i->name != "") { + error("line %u: conditions are only allowed" + " with '-c', '--conditions' option", + i->rules[0].code->fline); + exit(1); } } - if (!context.spec_all.empty()) { - l = std::min(l, context.spec_all[0]->code->fline); - } - if (!setups.empty()) { - l = std::min(l, setups.begin()->second->fline); - } - if (context.startup) { - l = std::min(l, context.startup->fline); - } - if (l != NOL) { - error("line %u: conditions are only allowed with '-c', '--conditions' option", l); - exit(1); - } } else { - SpecMap::const_iterator i = specs.find(""); - if (i != specs.end()) { - error("line %u: non-conditional rules are not allowed with '-c', '--conditions' option", - i->second[0]->code->fline); - exit(1); + for (i = b; i != e; ++i) { + if (i->name == "") { + error("line %u: non-conditional rules are not allowed" + " with '-c', '--conditions' option", + i->rules[0].code->fline); + exit(1); + } + } + + for (i = b; i != e; ++i) { + if (i->setup.size() > 1) { + error("line %u: code to setup rule '%s' is already defined at line %u", + i->setup[1]->fline, i->name.c_str(), i->setup[0]->fline); + exit(1); + } } - for (SetupMap::const_iterator i = setups.begin(); i != setups.end(); ++i) { - const std::string c = i->first; - if (c != "*" && specs.find(c) == specs.end()) { + + for (i = b; i != e; ++i) { + if (i->name != "*" && !i->setup.empty() && i->rules.empty()) { error("line %u: setup for non existing condition '%s' found", - i->second->fline, c.c_str()); + i->setup[0]->fline, i->name.c_str()); exit(1); } } - if (setups.size() > nspec) { - SetupMap::const_iterator i = setups.find("*"); - if (i != setups.end()) { - error("line %u: setup for all conditions '' is illegal " - "if setup for each condition is defined explicitly", - i->second->fline); + + for (i = b; i != e && !i->setup.empty(); ++i); + if (i == e) { + for (i = b; i != e; ++i) { + if (i->name == "*") { + error("line %u: setup for all conditions '' is illegal " + "if setup for each condition is defined explicitly", + i->setup[0]->fline); + exit(1); + } + } + } + + for (i = b; i != e; ++i) { + if (i->name == "0" && i->rules.size() > 1) { + error("line %u: startup code is already defined at line %u", + i->rules[1].code->fline, i->rules[0].code->fline); exit(1); } } } } -static void delay_default(Spec &spec) +static void prepare(specs_t &specs, const Scanner &in) { - // default rule(s) should go last - std::stable_partition(spec.begin(), spec.end(), RegExpRule::isnt_def); -} + specs_t::iterator i, b = specs.begin(), e = specs.end(); -static void make_rule(context_t &context, RegExpRule *rule, const Code *code) -{ - rule->code = code; - context.specMap[""].push_back(rule); -} + // merge <*> rules and setup to all conditions except "0" + // star rules must have lower priority than normal rules + for (i = b; i != e && i->name != "*"; ++i); + if (i != e) { + const specs_t::iterator star = i; -static void make_cond(context_t &context, CondList *clist, - RegExpRule *rule, const Code *code) -{ - rule->code = code; - for(CondList::const_iterator i = clist->begin(); i != clist->end(); ++i) { - const std::string &cond = *i; - if (context.specMap.find(cond) == context.specMap.end()) { - context.condnames.push_back(cond); - } - context.specMap[cond].push_back(rule); - } - delete clist; -} + for (i = b; i != e; ++i) { + if (i == star || i->name == "0") continue; -static void make_star(context_t &context, RegExpRule *rule, const Code *code) -{ - rule->code = code; - context.spec_all.push_back(rule); -} + i->rules.insert(i->rules.end(), star->rules.begin(), star->rules.end()); + i->defs.insert(i->defs.end(), star->defs.begin(), star->defs.end()); + i->setup.insert(i->setup.end(), star->setup.begin(), star->setup.end()); + } -static void make_zero(context_t &context, const Code *code) -{ - if (context.startup) { - error("line %u: startup code is already defined at line %u", - code->fline, context.startup->fline); - exit(1); + specs.erase(star); + e = specs.end(); } - context.startup = code; -} -static void make_setup(Scanner &in, SetupMap &ruleSetupMap, - CondList *clist, const Code *code) -{ - if (!clist) { - clist = new CondList; - clist->insert("*"); - } - assert(code); - for (CondList::const_iterator i = clist->begin(); i != clist->end(); ++i) { - if (ruleSetupMap.find(*i) != ruleSetupMap.end()) { - in.fatalf_at(code->fline, "code to setup rule '%s' is already defined", i->c_str()); + // merge default rule with the lowest priority + for (i = b; i != e; ++i) { + if (!i->defs.empty()) { + i->rules.push_back(RegExpRule(in.mkDefault(), i->defs[0])); } - ruleSetupMap[*i] = code; } - delete clist; + + // "0" condition must be the first one + for (i = b; i != e && i->name != "0"; ++i); + if (i != e && i != b) { + const spec_t zero = *i; + specs.erase(i); + specs.insert(specs.begin(), zero); + } } -static std::string find_setup_rule(const SetupMap &map, const std::string &key) +static spec_t &find(specs_t &specs, const std::string &name) { - SetupMap::const_iterator e = map.end(), i; - - i = map.find(key); - if (i != e) return i->second->text; - - i = map.find("*"); - if (i != e) return i->second->text; - - return ""; + for (specs_t::iterator i = specs.begin(); i != specs.end(); ++i) { + if (i->name == name) return *i; + } + specs.push_back(spec_t(name)); + return specs.back(); } %} %start spec -%lex-param {Scanner &in} -%parse-param {Scanner &in} %lex-param {context_t &context} %parse-param {context_t &context} @@ -214,7 +177,6 @@ static std::string find_setup_rule(const SetupMap &map, const std::string &key) re2c::ExtOp extop; std::string * str; re2c::CondList * clist; - re2c::RegExpRule *rule; }; %token TOKEN_CLOSESIZE @@ -228,10 +190,9 @@ static std::string find_setup_rule(const SetupMap &map, const std::string &key) %type close closes %type TOKEN_CLOSESIZE %type TOKEN_CODE ccode -%type TOKEN_REGEXP rule expr diff term factor primary +%type TOKEN_REGEXP trailexpr rule expr diff term factor primary %type TOKEN_ID TOKEN_FID name -%type clist -%type trailexpr +%type conds clist %% @@ -244,14 +205,14 @@ spec def : name expr enddef { - if (!context.symbol_table.insert(std::make_pair(*$1, $2)).second) { - in.fatal("sym already defined"); + if (!context.symtab.insert(std::make_pair(*$1, $2)).second) { + context.input.fatal("sym already defined"); } delete $1; } /* errors */ | name expr '/' { - in.fatal("trailing contexts are not allowed in named definitions"); + context.input.fatal("trailing contexts are not allowed in named definitions"); }; name @@ -266,27 +227,36 @@ enddef: ';' | TOKEN_FID_END; rule : trailexpr TOKEN_CODE { - make_rule(context, $1, $2); + find(context.specs, "").rules.push_back(RegExpRule($1, $2)); } - | '<' clist '>' trailexpr ccode { - make_cond(context, $2, $4, $5); + | '*' TOKEN_CODE { + find(context.specs, "").defs.push_back($2); } - | '<' '*' '>' trailexpr ccode { - make_star(context, $4, $5); + | '<' clist '>' trailexpr ccode { + for(CondList::const_iterator i = $2->begin(); i != $2->end(); ++i) { + find(context.specs, *i).rules.push_back(RegExpRule($4, $5)); + } + delete $2; } - | '<' '>' ccode { - make_zero(context, $3); + | '<' clist '>' '*' ccode { + for(CondList::const_iterator i = $2->begin(); i != $2->end(); ++i) { + find(context.specs, *i).defs.push_back($5); + } + delete $2; } | '<' '!' clist '>' TOKEN_CODE { - make_setup(in, context.ruleSetupMap, $3, $5); + for (CondList::const_iterator i = $3->begin(); i != $3->end(); ++i) { + find(context.specs, *i).setup.push_back($5); + } + delete $3; } - | '<' '!' '*' '>' TOKEN_CODE { - make_setup(in, context.ruleSetupMap, NULL, $5); + | '<' '>' ccode { + find(context.specs, "0").rules.push_back(RegExpRule(RegExp::make_nil(), $3)); }; ccode @@ -299,36 +269,35 @@ ccode } | ':' '=' '>' TOKEN_ID { - $$ = new Code(in.get_fname(), in.get_cline()); + $$ = new Code(context.input.get_fname(), context.input.get_cline()); $$->cond = *$4; delete $4; }; clist + : conds + | '*' { + $$ = new CondList; + $$->insert("*"); + }; + +conds : TOKEN_ID { $$ = new CondList; $$->insert(*$1); delete $1; } - | clist ',' TOKEN_ID { + | conds ',' TOKEN_ID { $1->insert(*$3); delete $3; $$ = $1; }; trailexpr - : expr { - $$ = new RegExpRule($1, false); - } - + : expr | expr '/' expr { - $$ = new RegExpRule(RegExp::make_cat($1, - RegExp::make_cat(RegExp::make_tag(NULL), $3)), false); - } - - | '*' { /* default rule */ - $$ = new RegExpRule(in.mkDefault(), true); + $$ = RegExp::make_cat($1, RegExp::make_cat(RegExp::make_tag(NULL), $3)); }; expr: @@ -349,7 +318,7 @@ diff: } | diff '\\' term { - $$ = in.mkDiff($1, $3); + $$ = context.input.mkDiff($1, $3); } ; @@ -418,11 +387,10 @@ close primary: TOKEN_ID { - symbol_table_t::iterator i = context.symbol_table.find (* $1); + symtab_t::iterator i = context.symtab.find(*$1); delete $1; - if (i == context.symbol_table.end ()) - { - in.fatal("can't find symbol"); + if (i == context.symtab.end()) { + context.input.fatal("can't find symbol"); } $$ = i->second; } @@ -440,14 +408,14 @@ primary: extern "C" { -void yyerror(Scanner &in, context_t&, const char* s) +void yyerror(context_t &context, const char* s) { - in.fatal(s); + context.input.fatal(s); } -int yylex(Scanner &in, context_t&) +int yylex(context_t &context) { - return in.scan(); + return context.input.scan(); } } // extern "C" @@ -455,111 +423,97 @@ int yylex(Scanner &in, context_t&) namespace re2c { -void parse(Scanner &in, Output & o) +void parse(Scanner &input, Output & o) { - dfa_map_t dfa_map; - context_t context; + specs_t specs; + symtab_t symtab; + dfas_t dfas; ScannerState rules_state, curr_state; - Opt &opts = in.opts; + Opt &opts = input.opts; o.source.wversion_time () - .wline_info (in.get_cline (), in.get_fname ().c_str ()); + .wline_info (input.get_cline (), input.get_fname ().c_str ()); if (opts->target == opt_t::SKELETON) { emit_prolog (o.source); } Enc encodingOld = opts->encoding; - for (Scanner::ParseMode mode; (mode = in.echo()) != Scanner::Stop;) { + for (Scanner::ParseMode mode; (mode = input.echo()) != Scanner::Stop;) { o.source.new_block (); bool bPrologBrace = false; - in.save_state(curr_state); - if (opts->rFlag && mode == Scanner::Rules && dfa_map.size()) + input.save_state(curr_state); + if (opts->rFlag && mode == Scanner::Rules && !dfas.empty()) { - in.fatal("cannot have a second 'rules:re2c' block"); + input.fatal("cannot have a second 'rules:re2c' block"); } if (mode == Scanner::Reuse) { - if (dfa_map.empty()) + if (dfas.empty()) { - in.fatal("got 'use:re2c' without 'rules:re2c'"); + input.fatal("got 'use:re2c' without 'rules:re2c'"); } } else if (mode == Scanner::Rules) { - in.save_state(rules_state); + input.save_state(rules_state); } else { - dfa_map.clear(); + dfas.clear(); } - context.specMap.clear(); - yyparse(in, context); + + // parse next re2c block + context_t context = {input, specs, symtab}; + specs.clear(); + yyparse(context); if (opts->rFlag && mode == Scanner::Reuse) { - if (!context.specMap.empty() || opts->encoding != encodingOld) { + if (!specs.empty() || opts->encoding != encodingOld) { // Re-parse rules mode = Scanner::Parse; - in.restore_state(rules_state); - in.reuse(); - dfa_map.clear(); - parse_cleanup(context); - context.specMap.clear(); - yyparse(in, context); + input.restore_state(rules_state); + input.reuse(); + dfas.clear(); + specs.clear(); + symtab.clear(); + yyparse(context); // Now append potential new rules - in.restore_state(curr_state); + input.restore_state(curr_state); mode = Scanner::Parse; - yyparse(in, context); + yyparse(context); } encodingOld = opts->encoding; } - o.source.block().line = in.get_cline(); - // compile regular expressions to automata if (mode != Scanner::Reuse) { - check(context, opts->cFlag); - - // merge <*> rules to all conditions except "0" with lowest priority - for (SpecMap::iterator it = context.specMap.begin(); it != context.specMap.end(); ++it) { - it->second.insert(it->second.end(), context.spec_all.begin(), context.spec_all.end()); - } - - // insert "0" condition - if (context.startup) { - RegExpRule *zero = new RegExpRule(RegExp::make_nil(), false); - zero->code = context.startup; - context.condnames.insert(context.condnames.begin(), "0"); // first - context.specMap["0"].push_back(zero); + check(specs, opts->cFlag); + prepare(specs, input); + o.source.block().line = input.get_cline(); + for (specs_t::const_iterator i = specs.begin(); i != specs.end(); ++i) { + dfas.push_back(compile(*i, o)); } + } - for (SpecMap::iterator it = context.specMap.begin(); it != context.specMap.end(); ++it) { - delay_default(it->second); - const std::string &setup = find_setup_rule(context.ruleSetupMap, it->first); - dfa_map[it->first] = compile(it->second, o, it->first, setup); + for (dfas_t::const_iterator i = dfas.begin(); i != dfas.end(); ++i) { + const std::string &c = (*i)->cond; + if (c != "") { + o.source.block().types.push_back(c); } } - o.source.block().types = context.condnames; - // generate code if (mode != Scanner::Rules) { uint32_t ind = opts->topIndent; - size_t nCount = dfa_map.size(); - if (dfa_map.find("") != dfa_map.end()) { - dfa_map[""]->emit(o, ind, !--nCount, bPrologBrace); - } else { - std::vector::const_iterator - i = context.condnames.begin(), - e = context.condnames.end(); - for (; i != e; ++i) { - dfa_map[*i]->emit(o, ind, !--nCount, bPrologBrace); - } + size_t nCount = dfas.size(); + for (dfas_t::const_iterator i = dfas.begin(); i != dfas.end(); ++i) { + (*i)->emit(o, ind, !--nCount, bPrologBrace); } } - o.source.wline_info (in.get_cline (), in.get_fname ().c_str ()); + o.source.wline_info (input.get_cline (), input.get_fname ().c_str ()); /* restore original char handling mode*/ opts.reset_encoding (encodingOld); } @@ -569,7 +523,10 @@ void parse(Scanner &in, Output & o) emit_epilog (o.source, o.skeletons); } - parse_cleanup(context); + RegExp::flist.clear(); + Code::flist.clear(); + Range::vFreeList.clear(); + RangeSuffix::freeList.clear(); } } // end namespace re2c diff --git a/re2c/test/cond_error_09.c.c b/re2c/test/cond_error_09.c.c index dde066b3..45646e19 100644 --- a/re2c/test/cond_error_09.c.c +++ b/re2c/test/cond_error_09.c.c @@ -1 +1 @@ -re2c: error: line 6, column 6: code to setup rule 'a' is already defined +re2c: error: line 6: code to setup rule 'a' is already defined at line 5 diff --git a/re2c/test/php20150211_zend_ini_scanner.c--emit-dot--flex-syntax--case-inverted.c b/re2c/test/php20150211_zend_ini_scanner.c--emit-dot--flex-syntax--case-inverted.c index 967b35da..57d14549 100644 --- a/re2c/test/php20150211_zend_ini_scanner.c--emit-dot--flex-syntax--case-inverted.c +++ b/re2c/test/php20150211_zend_ini_scanner.c--emit-dot--flex-syntax--case-inverted.c @@ -571,8 +571,8 @@ re2c: warning: line 384: column 32: escape has no effect: '\.' [-Wuseless-escape re2c: warning: line 391: column 27: escape has no effect: '\[' [-Wuseless-escape] re2c: warning: line 392: column 11: escape has no effect: '\[' [-Wuseless-escape] re2c: warning: line 648: unreachable rule in condition 'INITIAL' (shadowed by rules at lines 406, 481, 491, 555, 627, 632, 637) [-Wunreachable-rules] -re2c: warning: line 648: unreachable rule in condition 'ST_DOUBLE_QUOTES' (shadowed by rules at lines 582, 587) [-Wunreachable-rules] re2c: warning: line 623: unreachable rule in condition 'ST_OFFSET' (shadowed by rule at line 573) [-Wunreachable-rules] -re2c: warning: line 648: unreachable rule in condition 'ST_RAW' (shadowed by rules at lines 500, 541, 643) [-Wunreachable-rules] re2c: warning: line 623: unreachable rule in condition 'ST_SECTION_VALUE' (shadowed by rule at line 573) [-Wunreachable-rules] re2c: warning: line 648: unreachable rule in condition 'ST_VALUE' (shadowed by rules at lines 541, 547, 551, 559, 563, 569, 577, 623, 643) [-Wunreachable-rules] +re2c: warning: line 648: unreachable rule in condition 'ST_DOUBLE_QUOTES' (shadowed by rules at lines 582, 587) [-Wunreachable-rules] +re2c: warning: line 648: unreachable rule in condition 'ST_RAW' (shadowed by rules at lines 500, 541, 643) [-Wunreachable-rules] diff --git a/re2c/test/php20150211_zend_ini_scanner.igcd--flex-syntax--case-inverted.c b/re2c/test/php20150211_zend_ini_scanner.igcd--flex-syntax--case-inverted.c index 884d51c9..d76038f9 100644 --- a/re2c/test/php20150211_zend_ini_scanner.igcd--flex-syntax--case-inverted.c +++ b/re2c/test/php20150211_zend_ini_scanner.igcd--flex-syntax--case-inverted.c @@ -3807,9 +3807,9 @@ re2c: warning: line 384: column 32: escape has no effect: '\.' [-Wuseless-escape re2c: warning: line 391: column 27: escape has no effect: '\[' [-Wuseless-escape] re2c: warning: line 392: column 11: escape has no effect: '\[' [-Wuseless-escape] re2c: warning: line 648: unreachable rule in condition 'INITIAL' (shadowed by rules at lines 406, 481, 491, 555, 627, 632, 637) [-Wunreachable-rules] -re2c: warning: line 648: unreachable rule in condition 'ST_DOUBLE_QUOTES' (shadowed by rules at lines 582, 587) [-Wunreachable-rules] re2c: warning: line 623: unreachable rule in condition 'ST_OFFSET' (shadowed by rule at line 573) [-Wunreachable-rules] -re2c: warning: line 648: unreachable rule in condition 'ST_RAW' (shadowed by rules at lines 500, 541, 643) [-Wunreachable-rules] re2c: warning: line 623: unreachable rule in condition 'ST_SECTION_VALUE' (shadowed by rule at line 573) [-Wunreachable-rules] re2c: warning: line 648: unreachable rule in condition 'ST_VALUE' (shadowed by rules at lines 541, 547, 551, 559, 563, 569, 577, 623, 643) [-Wunreachable-rules] +re2c: warning: line 648: unreachable rule in condition 'ST_DOUBLE_QUOTES' (shadowed by rules at lines 582, 587) [-Wunreachable-rules] +re2c: warning: line 648: unreachable rule in condition 'ST_RAW' (shadowed by rules at lines 500, 541, 643) [-Wunreachable-rules] re2c: warning: line 652: looks like you use hardcoded numbers instead of autogenerated condition names: better add '/*!types:re2c*/' directive or '-t, --type-header' option and don't rely on fixed condition order. [-Wcondition-order] diff --git a/re2c/test/php20150211_zend_ini_scanner.igcd--skeleton--flex-syntax--case-inverted.c b/re2c/test/php20150211_zend_ini_scanner.igcd--skeleton--flex-syntax--case-inverted.c index 3da2e110..0d5ee7e4 100644 --- a/re2c/test/php20150211_zend_ini_scanner.igcd--skeleton--flex-syntax--case-inverted.c +++ b/re2c/test/php20150211_zend_ini_scanner.igcd--skeleton--flex-syntax--case-inverted.c @@ -20841,8 +20841,8 @@ re2c: warning: line 384: column 32: escape has no effect: '\.' [-Wuseless-escape re2c: warning: line 391: column 27: escape has no effect: '\[' [-Wuseless-escape] re2c: warning: line 392: column 11: escape has no effect: '\[' [-Wuseless-escape] re2c: warning: line 648: unreachable rule in condition 'INITIAL' (shadowed by rules at lines 406, 481, 491, 555, 627, 632, 637) [-Wunreachable-rules] -re2c: warning: line 648: unreachable rule in condition 'ST_DOUBLE_QUOTES' (shadowed by rules at lines 582, 587) [-Wunreachable-rules] re2c: warning: line 623: unreachable rule in condition 'ST_OFFSET' (shadowed by rule at line 573) [-Wunreachable-rules] -re2c: warning: line 648: unreachable rule in condition 'ST_RAW' (shadowed by rules at lines 500, 541, 643) [-Wunreachable-rules] re2c: warning: line 623: unreachable rule in condition 'ST_SECTION_VALUE' (shadowed by rule at line 573) [-Wunreachable-rules] re2c: warning: line 648: unreachable rule in condition 'ST_VALUE' (shadowed by rules at lines 541, 547, 551, 559, 563, 569, 577, 623, 643) [-Wunreachable-rules] +re2c: warning: line 648: unreachable rule in condition 'ST_DOUBLE_QUOTES' (shadowed by rules at lines 582, 587) [-Wunreachable-rules] +re2c: warning: line 648: unreachable rule in condition 'ST_RAW' (shadowed by rules at lines 500, 541, 643) [-Wunreachable-rules] diff --git a/re2c/test/php20150211_zend_ini_scanner_trimmed.ic--flex-syntax.c b/re2c/test/php20150211_zend_ini_scanner_trimmed.ic--flex-syntax.c index 6e101d26..a2c36d14 100644 --- a/re2c/test/php20150211_zend_ini_scanner_trimmed.ic--flex-syntax.c +++ b/re2c/test/php20150211_zend_ini_scanner_trimmed.ic--flex-syntax.c @@ -3290,8 +3290,8 @@ re2c: warning: line 4: column 32: escape has no effect: '\.' [-Wuseless-escape] re2c: warning: line 11: column 27: escape has no effect: '\[' [-Wuseless-escape] re2c: warning: line 12: column 11: escape has no effect: '\[' [-Wuseless-escape] re2c: warning: line 55: unreachable rule in condition 'INITIAL' (shadowed by rules at lines 24, 35, 36, 42, 51, 52, 53) [-Wunreachable-rules] -re2c: warning: line 55: unreachable rule in condition 'ST_DOUBLE_QUOTES' (shadowed by rules at lines 48, 49) [-Wunreachable-rules] re2c: warning: line 50: unreachable rule in condition 'ST_OFFSET' (shadowed by rule at line 46) [-Wunreachable-rules] -re2c: warning: line 55: unreachable rule in condition 'ST_RAW' (shadowed by rules at lines 37, 39, 54) [-Wunreachable-rules] re2c: warning: line 50: unreachable rule in condition 'ST_SECTION_VALUE' (shadowed by rule at line 46) [-Wunreachable-rules] re2c: warning: line 55: unreachable rule in condition 'ST_VALUE' (shadowed by rules at lines 39, 40, 41, 43, 44, 45, 47, 50, 54) [-Wunreachable-rules] +re2c: warning: line 55: unreachable rule in condition 'ST_DOUBLE_QUOTES' (shadowed by rules at lines 48, 49) [-Wunreachable-rules] +re2c: warning: line 55: unreachable rule in condition 'ST_RAW' (shadowed by rules at lines 37, 39, 54) [-Wunreachable-rules] diff --git a/re2c/test/php20150211_zend_ini_scanner_trimmed.icwb--flex-syntax.c b/re2c/test/php20150211_zend_ini_scanner_trimmed.icwb--flex-syntax.c index 24d09231..22f967dd 100644 --- a/re2c/test/php20150211_zend_ini_scanner_trimmed.icwb--flex-syntax.c +++ b/re2c/test/php20150211_zend_ini_scanner_trimmed.icwb--flex-syntax.c @@ -2842,9 +2842,9 @@ re2c: warning: line 4: column 32: escape has no effect: '\.' [-Wuseless-escape] re2c: warning: line 11: column 27: escape has no effect: '\[' [-Wuseless-escape] re2c: warning: line 12: column 11: escape has no effect: '\[' [-Wuseless-escape] re2c: warning: line 55: unreachable rule in condition 'INITIAL' (shadowed by rules at lines 24, 35, 36, 42, 51, 52, 53) [-Wunreachable-rules] -re2c: warning: line 55: unreachable rule in condition 'ST_DOUBLE_QUOTES' (shadowed by rules at lines 48, 49) [-Wunreachable-rules] re2c: warning: line 50: unreachable rule in condition 'ST_OFFSET' (shadowed by rule at line 46) [-Wunreachable-rules] -re2c: warning: line 55: unreachable rule in condition 'ST_RAW' (shadowed by rules at lines 37, 39, 54) [-Wunreachable-rules] re2c: warning: line 50: unreachable rule in condition 'ST_SECTION_VALUE' (shadowed by rule at line 46) [-Wunreachable-rules] re2c: warning: line 55: unreachable rule in condition 'ST_VALUE' (shadowed by rules at lines 39, 40, 41, 43, 44, 45, 47, 50, 54) [-Wunreachable-rules] +re2c: warning: line 55: unreachable rule in condition 'ST_DOUBLE_QUOTES' (shadowed by rules at lines 48, 49) [-Wunreachable-rules] +re2c: warning: line 55: unreachable rule in condition 'ST_RAW' (shadowed by rules at lines 37, 39, 54) [-Wunreachable-rules] re2c: warning: line 56: looks like you use hardcoded numbers instead of autogenerated condition names: better add '/*!types:re2c*/' directive or '-t, --type-header' option and don't rely on fixed condition order. [-Wcondition-order] -- 2.40.0