]> granicus.if.org Git - re2c/commitdiff
Finally separated parsing, consistensy checking and after-parse transformation.
authorUlya Trofimovich <skvadrik@gmail.com>
Tue, 27 Dec 2016 17:00:09 +0000 (17:00 +0000)
committerUlya Trofimovich <skvadrik@gmail.com>
Tue, 27 Dec 2016 17:09:21 +0000 (17:09 +0000)
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.

22 files changed:
re2c/bootstrap/src/parse/lex.cc
re2c/bootstrap/src/parse/parser.cc
re2c/bootstrap/src/parse/y.tab.h
re2c/src/ir/compile.cc
re2c/src/ir/compile.h
re2c/src/ir/nfa/counters.cc
re2c/src/ir/nfa/init_rules.cc
re2c/src/ir/nfa/nfa.cc
re2c/src/ir/nfa/nfa.h
re2c/src/ir/nfa/regexps2nfa.cc
re2c/src/ir/regexp/nullable.cc
re2c/src/ir/regexp/regexp.cc
re2c/src/ir/regexp/regexp.h
re2c/src/ir/regexp/split_charset.cc
re2c/src/parse/parser.h
re2c/src/parse/parser.ypp
re2c/test/cond_error_09.c.c
re2c/test/php20150211_zend_ini_scanner.c--emit-dot--flex-syntax--case-inverted.c
re2c/test/php20150211_zend_ini_scanner.igcd--flex-syntax--case-inverted.c
re2c/test/php20150211_zend_ini_scanner.igcd--skeleton--flex-syntax--case-inverted.c
re2c/test/php20150211_zend_ini_scanner_trimmed.ic--flex-syntax.c
re2c/test/php20150211_zend_ini_scanner_trimmed.icwb--flex-syntax.c

index 724c47cdec76a0d5c1c51dc1ecb237804a337f6e..2ba20d90c06b0646235420e69ffe27437c8a0960 100644 (file)
@@ -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 <stddef.h>
index 6ebed3c3a230c8fa14834cbeea9bd52edefc3b53..db5eee846a378df398a9376c3bc79394674c3835 100644 (file)
@@ -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 &in;
     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 &in;
     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 &in;
     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 &in;
     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 &in;
+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<uint32_t>::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<std::string>::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
index 2d512327df299f9ad4151b96764c566685fa13aa..6f9bebf6af8ed78763b04f16aaff21921d88ad26 100644 (file)
@@ -61,7 +61,6 @@ typedef union YYSTYPE
        re2c::ExtOp extop;
        std::string * str;
        re2c::CondList * clist;
-       re2c::RegExpRule *rule;
 
 
 
index c913a250a8decca3b9055c6868c7f55c2149103e..9238f50d78d34b91d4247c319aa44c5f0be68606 100644 (file)
@@ -27,16 +27,21 @@ static std::string make_name(const std::string &cond, uint32_t line)
        return name;
 }
 
-smart_ptr<DFA> compile(const Spec &rules, Output &output,
-       const std::string &cond, const std::string &setup)
+smart_ptr<DFA> 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<RegExpRule> &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);
 
index 896a46d4f833b27b8084420dc922d4deb0108318..d268d7a65ea77fec732e77eb965fcc08eb90af5a 100644 (file)
@@ -1,20 +1,14 @@
 #ifndef _RE2C_IR_COMPILE_
 #define _RE2C_IR_COMPILE_
 
-#include "src/util/c99_stdint.h"
-#include <string>
-
 #include "src/parse/parser.h"
-#include "src/util/smart_ptr.h"
 
 namespace re2c
 {
 
-class DFA;
 struct Output;
 
-smart_ptr<DFA> compile(const Spec &spec, Output &output,
-       const std::string &cond, const std::string &setup);
+smart_ptr<DFA> compile(const spec_t &spec, Output &output);
 
 } // namespace re2c
 
index 48e863f13163a38b812a5a8e1ffe780dc68e1fae..d77edc869aae30b677e4c534fca65a6405150464 100644 (file)
@@ -30,12 +30,12 @@ static size_t count(const RegExp *re, size_t &ntags)
        }
 }
 
-size_t counters(const std::vector<const RegExpRule*> &regexps, size_t &ntags)
+size_t counters(const std::vector<RegExpRule> &regexps, 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;
 }
index f1399b7d802c566247234ac851083a98fc34a2a1..09a31dcd2febc778898cda1be4fb9e6bce49f34c 100644 (file)
@@ -29,7 +29,7 @@ error:
        exit(1);
 }
 
-void init_rules(const std::vector<const RegExpRule*> &regexps,
+void init_rules(const std::vector<RegExpRule> &regexps,
        std::valarray<Rule> &rules, const std::vector<VarTag> &vartags,
        const std::vector<FixTag> &fixtags)
 {
@@ -40,7 +40,7 @@ void init_rules(const std::vector<const RegExpRule*> &regexps,
 
        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);
index f3a086431017f1a263d3a4b01e03b6368fc99913..3924782cbd7ff97b819726569f8504dc65f4c101 100644 (file)
@@ -2,7 +2,7 @@
 
 namespace re2c {
 
-nfa_t::nfa_t(const std::vector<const RegExpRule*> &regexps, InputAPI::type_t input)
+nfa_t::nfa_t(const std::vector<RegExpRule> &regexps, InputAPI::type_t input)
        : max_size(0)
        , size(0)
        , states(NULL)
index 3cf21e415dfb32261e05bc7fd678f8ebdfed6c8e..dba90f94edd56f1f12578854201f15e1f6d21c6e 100644 (file)
@@ -94,16 +94,16 @@ struct nfa_t
        std::vector<FixTag> &fixtags;
        nfa_state_t *root;
 
-       nfa_t(const std::vector<const RegExpRule*> &rs, InputAPI::type_t input);
+       nfa_t(const std::vector<RegExpRule> &rs, InputAPI::type_t input);
        ~nfa_t();
 
        FORBID_COPY(nfa_t);
 };
 
-size_t counters(const std::vector<const RegExpRule*> &regexps, size_t &ntags);
-void regexps2nfa(const std::vector<const RegExpRule*> &regexps, nfa_t &nfa, InputAPI::type_t input);
-bool nullable_rule(const RegExpRule *rule);
-void init_rules(const std::vector<const RegExpRule*> &regexps, std::valarray<Rule> &rules,
+size_t counters(const std::vector<RegExpRule> &regexps, size_t &ntags);
+void regexps2nfa(const std::vector<RegExpRule> &regexps, nfa_t &nfa, InputAPI::type_t input);
+bool nullable_rule(const RegExpRule &rule);
+void init_rules(const std::vector<RegExpRule> &regexps, std::valarray<Rule> &rules,
        const std::vector<VarTag> &vartags, const std::vector<FixTag> &fixtags);
 
 } // namespace re2c
index d286f9d62cfdd7e82c7bfad5d797853d5c52e65b..62b0a7bbca6aa456b0074eac928b45b76242281d 100644 (file)
@@ -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<const RegExpRule*> &regexps,
+void regexps2nfa(const std::vector<RegExpRule> &regexps,
        nfa_t &nfa, InputAPI::type_t input)
 {
        const size_t nregexps = regexps.size();
@@ -126,10 +126,10 @@ void regexps2nfa(const std::vector<const RegExpRule*> &regexps,
                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;
index 83b1e98bb1990b744a744651d3d848ed9ca29ba6..5481692df082824251560244e7f1b3130fd12b23 100644 (file)
@@ -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<const RegExpRule*> &regexps,
+void warn_nullable(const std::vector<RegExpRule> &regexps,
        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);
                }
        }
 }
index d8992985afa7b0b63d148483361ddbfc3170620b..584b1f7fb302eef966f98212b0387542632a5236 100644 (file)
@@ -14,7 +14,6 @@ namespace re2c
 {
 
 free_list<RegExp*> RegExp::flist;
-free_list<RegExpRule*> RegExpRule::flist;
 
 const RegExp *doAlt(const RegExp *re1, const RegExp *re2)
 {
index 94f864841b154c5e44663f92855ee0b00d5e7789..92e2f61348d5272e3b0a0fb22b6df9964539a80b 100644 (file)
@@ -105,36 +105,23 @@ private:
 
 struct RegExpRule
 {
-       static free_list<RegExpRule*> 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<const RegExpRule*> &rs, std::set<uint32_t> &cs);
+void split(const std::vector<RegExpRule> &rs, std::set<uint32_t> &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<const RegExpRule*> &regexps,
+void warn_nullable(const std::vector<RegExpRule> &regexps,
        const std::string &cond, Warn &warn);
 
 } // end namespace re2c
index f900cc2a01676b674a9cafe5926d2c3cd7d5f153..f2eaa9f08a22702fb5869d049c65714ed8f44ba6 100644 (file)
@@ -32,11 +32,11 @@ static void split(const RegExp* re, std::set<uint32_t> &cs)
        }
 }
 
-void split(const std::vector<const RegExpRule*> &rs, std::set<uint32_t> &cs)
+void split(const std::vector<RegExpRule> &rs, std::set<uint32_t> &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);
        }
 }
 
index 36524248116f1b18ebf6a70d548837e09b66e468..ec23cf4cf76b03fa388e66ea1004fcb291f9433b 100644 (file)
@@ -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<RegExpRule> rules;
+       std::vector<const Code*> defs;
+       std::vector<const Code*> setup;
+
+       explicit spec_t(const std::string &n):
+               name(n), rules(), defs(), setup() {}
+};
+
+typedef std::vector<spec_t> specs_t;
 typedef std::set<std::string> CondList;
-typedef std::vector<const RegExpRule*> Spec;
-typedef std::map<std::string, Spec> SpecMap;
-typedef std::map<std::string, const Code*> SetupMap;
-typedef std::map<std::string, const RegExp *> symbol_table_t;
-typedef std::map<std::string, smart_ptr<DFA> > dfa_map_t;
+typedef std::map<std::string, const RegExp *> symtab_t;
+typedef std::vector<smart_ptr<DFA> > dfas_t;
 
 struct context_t
 {
-       std::vector<std::string> 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
index 77e6544fe1b513f8b52542cc9c8190f142ef01c6..f5e0da8c890d5158580269e56d9bf120e6204b1a 100644 (file)
@@ -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 <op>      close closes
 %type <extop>   TOKEN_CLOSESIZE
 %type <code>    TOKEN_CODE ccode
-%type <regexp>  TOKEN_REGEXP rule expr diff term factor primary
+%type <regexp>  TOKEN_REGEXP trailexpr rule expr diff term factor primary
 %type <str>     TOKEN_ID TOKEN_FID name
-%type <clist>   clist
-%type <rule>    trailexpr
+%type <clist>   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<std::string>::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
index dde066b3887500c371b5d1bcfa6fd3678a4a8db5..45646e19157ee00859ae1ebb2d3cecd9ea1b0375 100644 (file)
@@ -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
index 967b35dafe64508e0ec5305898f9024ccb08e838..57d1454918aac1865e53b8e43236bab150fc5af8 100644 (file)
@@ -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]
index 884d51c95c3288a7b1012b0c30bbb0a4c0cffef9..d76038f9651fd4baaa93bb65e6223b4cee964c20 100644 (file)
@@ -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]
index 3da2e110e167dafcb15ad092cf979730daf4d9a5..0d5ee7e43d7eba29d35e1aab25b34da3be483e43 100644 (file)
@@ -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]
index 6e101d265eaf9736270cf1f17fd7daeb6169030e..a2c36d14a7151d2586e7908353a9169284a0c5e3 100644 (file)
@@ -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]
index 24d09231cee94f2468a506888da7b8207d1c9c59..22f967ddd324161b43693156a161f3f9dc4b7a2e 100644 (file)
@@ -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]