]> granicus.if.org Git - re2c/commitdiff
Moved the main driver out of parser grammar file.
authorUlya Trofimovich <skvadrik@gmail.com>
Wed, 8 Mar 2017 08:32:16 +0000 (08:32 +0000)
committerUlya Trofimovich <skvadrik@gmail.com>
Wed, 8 Mar 2017 08:32:16 +0000 (08:32 +0000)
re2c/Makefile.am
re2c/bootstrap/src/ast/lex.cc
re2c/bootstrap/src/ast/parser.cc
re2c/src/ast/ast.h
re2c/src/ast/normalize.cc [new file with mode: 0644]
re2c/src/ast/parser.h
re2c/src/ast/parser.ypp
re2c/src/ast/validate.cc [new file with mode: 0644]
re2c/src/compile.cc
re2c/src/compile.h
re2c/src/main.cc

index 3b491be8d6719f926762ec689701fea791a424ce..8b524279313f2e2d7b2e72fdfb9228a503887f9a 100644 (file)
@@ -136,8 +136,10 @@ SRC = \
        src/main.cc \
        src/ast/ast.cc \
        src/ast/input.cc \
+       src/ast/normalize.cc \
        src/ast/scanner.cc \
        src/ast/unescape.cc \
+       src/ast/validate.cc \
        src/util/s_to_n32_unsafe.cc \
        src/util/range.cc
 re2c_SOURCES = \
index dd4cfd8127dfa706dde565ef9d7613ed1c617ff9..b811e669a3fb65e640658a6f0a0ee92d46749889 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.16 on Tue Mar  7 21:23:28 2017 */
+/* Generated by re2c 0.16 on Tue Mar  7 22:52:18 2017 */
 #line 1 "../src/ast/lex.re"
 #include "src/util/c99_stdint.h"
 #include <stddef.h>
index b99e52a5d15ab30ed0a99880ea1a8ba17dbd98b3..e2e663ec3af096fc3edb36531ecf48c2effa1533 100644 (file)
 
 
 
-#include "src/util/c99_stdint.h"
-#include <assert.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <limits>
-#include <list>
-#include <map>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "src/conf/msg.h"
-#include "src/code/output.h"
-#include "src/compile.h"
-#include "src/adfa/adfa.h"
-#include "src/re/encoding/enc.h"
-#include "src/re/encoding/range_suffix.h"
-#include "src/skeleton/skeleton.h"
 #include "src/ast/parser.h"
-#include "src/ast/ast.h"
-#include "src/ast/scanner.h"
-#include "src/util/free_list.h"
-#include "src/util/range.h"
 
 #define YYMALLOC malloc
 #define YYFREE free
@@ -109,136 +86,6 @@ void yyerror(context_t &context, const char*);
 #define __attribute__(x)
 #endif
 
-static void check_mode(Scanner::ParseMode mode, bool rflag, bool rules, Scanner &input)
-{
-       if (mode == Scanner::Rules) {
-               if (!rflag) {
-                       input.fatal("found 'rules:re2c' block without -r flag");
-               } else if (rules) {
-                       input.fatal("cannot have a second 'rules:re2c' block");
-               }
-       } else if (mode == Scanner::Reuse) {
-               if (!rflag) {
-                       input.fatal("found 'use:re2c' block without -r flag");
-               } else if (!rules) {
-                       input.fatal("got 'use:re2c' without 'rules:re2c'");
-               }
-       } else if (rflag) {
-               input.fatal("found standard 're2c' block while using -r flag");
-       }
-}
-
-static void check_specs(const specs_t &specs, bool cflag)
-{
-       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);
-               }
-       }
-
-       if (!cflag) {
-               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);
-                       }
-               }
-       } else {
-               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 (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->setup[0]->fline, i->name.c_str());
-                               exit(1);
-                       }
-               }
-
-               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 prepare_specs(specs_t &specs)
-{
-       specs_t::iterator i, b = specs.begin(), e = specs.end();
-
-       // 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;
-
-               for (i = b; i != e; ++i) {
-                       if (i == star || i->name == "0") continue;
-
-                       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());
-               }
-
-               specs.erase(star);
-               e = specs.end();
-       }
-
-       // merge default rule with the lowest priority
-       for (i = b; i != e; ++i) {
-               if (!i->defs.empty()) {
-                       const Code *c = i->defs[0];
-                       const AST *r = ast_default(c->fline, 0);
-                       i->rules.push_back(ASTRule(r, c));
-               }
-       }
-
-       // "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 spec_t &find(specs_t &specs, const std::string &name)
 {
        for (specs_t::iterator i = specs.begin(); i != specs.end(); ++i) {
@@ -622,13 +469,13 @@ static const yytype_uint8 yytranslate[] =
 
 #if YYDEBUG
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] =
+static const yytype_uint8 yyrline[] =
 {
-       0,   220,   220,   222,   223,   224,   225,   229,   236,   241,
-     244,   248,   248,   251,   255,   259,   266,   273,   280,   286,
-     288,   294,   301,   302,   308,   314,   321,   323,   329,   333,
-     340,   344,   351,   355,   362,   363,   369,   374,   375,   379,
-     380,   381,   385,   386,   396
+       0,    67,    67,    69,    70,    71,    72,    76,    83,    88,
+      91,    95,    95,    98,   102,   106,   113,   120,   127,   133,
+     135,   141,   148,   149,   155,   161,   168,   170,   176,   180,
+     187,   191,   198,   202,   209,   210,   216,   221,   222,   226,
+     227,   228,   232,   233,   243
 };
 #endif
 
@@ -1977,76 +1824,10 @@ int yylex(context_t &context)
 namespace re2c
 {
 
-void parse(Scanner &input, Output &output, Opt &opts)
+void parse(Scanner &input, specs_t &specs, symtab_t &symtab, Opt &opts)
 {
-       specs_t rspecs;
-       symtab_t symtab;
-       const conopt_t *globopts = &opts.glob;
-       const opt_t *ropts = NULL;
-       OutputFile &o = output.source;
-
-       o.new_block(opts);
-       o.wversion_time().wline_info(input.get_cline(), input.get_fname().c_str());
-       if (globopts->target == TARGET_SKELETON) {
-               emit_prolog(o);
-       }
-
-       for (Scanner::ParseMode mode; (mode = input.echo(o)) != Scanner::Stop;) {
-
-               check_mode(mode, globopts->rFlag, ropts, input);
-
-               // parse next re2c block
-               specs_t specs;
-               context_t context = {input, specs, symtab, opts};
-               if (mode == Scanner::Reuse) {
-                       specs = rspecs;
-                       opts.restore(ropts);
-                       opts.reset_mapCodeName();
-                       o.label_counter.reset();
-                       o.fill_index = 0;
-                       o.state_goto = false;
-                       o.cond_goto = false;
-               }
-               yyparse(context);
-
-               // start new output block with accumulated options
-               o.new_block(opts);
-
-               if (mode == Scanner::Rules) {
-                       // save AST and options for future use
-                       rspecs = specs;
-                       ropts = o.block().opts;
-               } else {
-                       // validate and normalize AST
-                       check_specs(specs, globopts->cFlag);
-                       prepare_specs(specs);
-
-                       // compile AST to DFA
-                       o.block().line = input.get_cline();
-                       dfas_t dfas;
-                       for (specs_t::const_iterator i = specs.begin(); i != specs.end(); ++i) {
-                               dfas.push_back(compile(*i, output));
-                       }
-
-                       // compile DFA to code
-                       bool prolog = false;
-                       uint32_t ind = o.block().opts->topIndent;
-                       for (dfas_t::const_iterator i = dfas.begin(); i != dfas.end(); ++i) {
-                               (*i)->emit(output, ind, (i + 1) == dfas.end(), prolog);
-                       }
-               }
-
-               o.wline_info (input.get_cline (), input.get_fname ().c_str ());
-       }
-
-       if (globopts->target == TARGET_SKELETON) {
-               emit_epilog (o, output.skeletons);
-       }
-
-       AST::flist.clear();
-       Code::flist.clear();
-       Range::vFreeList.clear();
-       RangeSuffix::freeList.clear();
+    context_t context = {input, specs, symtab, opts};
+    yyparse(context);
 }
 
-} // end namespace re2c
+} // namespace re2c
index e5bd76890e6a9430e5dff1fb8e0d10fa6cdf42ff..7580a7f538c6c2386981b05de1e133bd463a0250 100644 (file)
@@ -2,9 +2,11 @@
 #define _RE2C_AST_AST_
 
 #include "src/util/c99_stdint.h"
+#include <map>
 #include <string>
 #include <vector>
 
+#include "src/ast/scanner.h"
 #include "src/rule.h"
 #include "src/util/free_list.h"
 #include "src/util/range.h"
@@ -95,6 +97,20 @@ struct ASTBounds
        uint32_t max;
 };
 
+struct spec_t
+{
+       std::string name;
+       std::vector<ASTRule> 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::map<std::string, const AST*> symtab_t;
+
 const AST *ast_nil(uint32_t l, uint32_t c);
 const AST *ast_str(uint32_t l, uint32_t c, std::vector<ASTChar> *chars, bool icase);
 const AST *ast_cls(uint32_t l, uint32_t c, std::vector<ASTRange> *ranges, bool negated);
@@ -109,6 +125,10 @@ const AST *ast_cap(const AST *r);
 const AST *ast_ref(const AST *r, const std::string &n);
 bool ast_need_wrap(const AST *ast);
 
+void validate_mode(Scanner::ParseMode mode, bool rflag, bool rules, Scanner &input);
+void validate_ast(const specs_t &specs, bool cflag);
+void normalize_ast(specs_t &specs);
+
 } // namespace re2c
 
 #endif // _RE2C_AST_AST_
diff --git a/re2c/src/ast/normalize.cc b/re2c/src/ast/normalize.cc
new file mode 100644 (file)
index 0000000..40e0232
--- /dev/null
@@ -0,0 +1,45 @@
+#include "src/ast/ast.h"
+
+namespace re2c {
+
+void normalize_ast(specs_t &specs)
+{
+       specs_t::iterator i, b = specs.begin(), e = specs.end();
+
+       // 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;
+
+               for (i = b; i != e; ++i) {
+                       if (i == star || i->name == "0") continue;
+
+                       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());
+               }
+
+               specs.erase(star);
+               e = specs.end();
+       }
+
+       // merge default rule with the lowest priority
+       for (i = b; i != e; ++i) {
+               if (!i->defs.empty()) {
+                       const Code *c = i->defs[0];
+                       const AST *r = ast_default(c->fline, 0);
+                       i->rules.push_back(ASTRule(r, c));
+               }
+       }
+
+       // "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);
+       }
+}
+
+} // namespace re2c
index 563441d0106151b1990fd490c7cfdcd8e141174d..d820fed17318d7d6ed2ae458fb63d82b4426103a 100644 (file)
@@ -1,36 +1,17 @@
 #ifndef _RE2C_AST_PARSER_
 #define _RE2C_AST_PARSER_
 
-#include <map>
+#include <set>
 #include <string>
 
-#include "src/code/output.h"
 #include "src/ast/ast.h"
+#include "src/conf/opt.h"
 #include "src/ast/scanner.h"
-#include "src/util/smart_ptr.h"
 
 namespace re2c
 {
 
-struct DFA;
-
-void parse(Scanner &input, Output &output, Opt &opts);
-
-struct spec_t
-{
-       std::string name;
-       std::vector<ASTRule> 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::map<std::string, const AST*> symtab_t;
-typedef std::vector<smart_ptr<DFA> > dfas_t;
 
 struct context_t
 {
@@ -40,6 +21,8 @@ struct context_t
        Opt &opts;
 };
 
+void parse(Scanner &input, specs_t &specs, symtab_t &symtab, Opt &opts);
+
 } // namespace re2c
 
 #endif // _RE2C_AST_PARSER_
index 75fbec77dde7ef79ea43e218b913477f6db6869c..e4b1f919d884cff8107156f60d2bb9661f4db4a1 100644 (file)
@@ -1,29 +1,6 @@
 %{
 
-#include "src/util/c99_stdint.h"
-#include <assert.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <limits>
-#include <list>
-#include <map>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "src/conf/msg.h"
-#include "src/code/output.h"
-#include "src/compile.h"
-#include "src/adfa/adfa.h"
-#include "src/re/encoding/enc.h"
-#include "src/re/encoding/range_suffix.h"
-#include "src/skeleton/skeleton.h"
 #include "src/ast/parser.h"
-#include "src/ast/ast.h"
-#include "src/ast/scanner.h"
-#include "src/util/free_list.h"
-#include "src/util/range.h"
 
 #define YYMALLOC malloc
 #define YYFREE free
@@ -44,136 +21,6 @@ void yyerror(context_t &context, const char*);
 #define __attribute__(x)
 #endif
 
-static void check_mode(Scanner::ParseMode mode, bool rflag, bool rules, Scanner &input)
-{
-       if (mode == Scanner::Rules) {
-               if (!rflag) {
-                       input.fatal("found 'rules:re2c' block without -r flag");
-               } else if (rules) {
-                       input.fatal("cannot have a second 'rules:re2c' block");
-               }
-       } else if (mode == Scanner::Reuse) {
-               if (!rflag) {
-                       input.fatal("found 'use:re2c' block without -r flag");
-               } else if (!rules) {
-                       input.fatal("got 'use:re2c' without 'rules:re2c'");
-               }
-       } else if (rflag) {
-               input.fatal("found standard 're2c' block while using -r flag");
-       }
-}
-
-static void check_specs(const specs_t &specs, bool cflag)
-{
-       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);
-               }
-       }
-
-       if (!cflag) {
-               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);
-                       }
-               }
-       } else {
-               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 (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->setup[0]->fline, i->name.c_str());
-                               exit(1);
-                       }
-               }
-
-               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 prepare_specs(specs_t &specs)
-{
-       specs_t::iterator i, b = specs.begin(), e = specs.end();
-
-       // 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;
-
-               for (i = b; i != e; ++i) {
-                       if (i == star || i->name == "0") continue;
-
-                       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());
-               }
-
-               specs.erase(star);
-               e = specs.end();
-       }
-
-       // merge default rule with the lowest priority
-       for (i = b; i != e; ++i) {
-               if (!i->defs.empty()) {
-                       const Code *c = i->defs[0];
-                       const AST *r = ast_default(c->fline, 0);
-                       i->rules.push_back(ASTRule(r, c));
-               }
-       }
-
-       // "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 spec_t &find(specs_t &specs, const std::string &name)
 {
        for (specs_t::iterator i = specs.begin(); i != specs.end(); ++i) {
@@ -416,76 +263,10 @@ int yylex(context_t &context)
 namespace re2c
 {
 
-void parse(Scanner &input, Output &output, Opt &opts)
+void parse(Scanner &input, specs_t &specs, symtab_t &symtab, Opt &opts)
 {
-       specs_t rspecs;
-       symtab_t symtab;
-       const conopt_t *globopts = &opts.glob;
-       const opt_t *ropts = NULL;
-       OutputFile &o = output.source;
-
-       o.new_block(opts);
-       o.wversion_time().wline_info(input.get_cline(), input.get_fname().c_str());
-       if (globopts->target == TARGET_SKELETON) {
-               emit_prolog(o);
-       }
-
-       for (Scanner::ParseMode mode; (mode = input.echo(o)) != Scanner::Stop;) {
-
-               check_mode(mode, globopts->rFlag, ropts, input);
-
-               // parse next re2c block
-               specs_t specs;
-               context_t context = {input, specs, symtab, opts};
-               if (mode == Scanner::Reuse) {
-                       specs = rspecs;
-                       opts.restore(ropts);
-                       opts.reset_mapCodeName();
-                       o.label_counter.reset();
-                       o.fill_index = 0;
-                       o.state_goto = false;
-                       o.cond_goto = false;
-               }
-               yyparse(context);
-
-               // start new output block with accumulated options
-               o.new_block(opts);
-
-               if (mode == Scanner::Rules) {
-                       // save AST and options for future use
-                       rspecs = specs;
-                       ropts = o.block().opts;
-               } else {
-                       // validate and normalize AST
-                       check_specs(specs, globopts->cFlag);
-                       prepare_specs(specs);
-
-                       // compile AST to DFA
-                       o.block().line = input.get_cline();
-                       dfas_t dfas;
-                       for (specs_t::const_iterator i = specs.begin(); i != specs.end(); ++i) {
-                               dfas.push_back(compile(*i, output));
-                       }
-
-                       // compile DFA to code
-                       bool prolog = false;
-                       uint32_t ind = o.block().opts->topIndent;
-                       for (dfas_t::const_iterator i = dfas.begin(); i != dfas.end(); ++i) {
-                               (*i)->emit(output, ind, (i + 1) == dfas.end(), prolog);
-                       }
-               }
-
-               o.wline_info (input.get_cline (), input.get_fname ().c_str ());
-       }
-
-       if (globopts->target == TARGET_SKELETON) {
-               emit_epilog (o, output.skeletons);
-       }
-
-       AST::flist.clear();
-       Code::flist.clear();
-       Range::vFreeList.clear();
-       RangeSuffix::freeList.clear();
+    context_t context = {input, specs, symtab, opts};
+    yyparse(context);
 }
 
-} // end namespace re2c
+} // namespace re2c
diff --git a/re2c/src/ast/validate.cc b/re2c/src/ast/validate.cc
new file mode 100644 (file)
index 0000000..a770e4d
--- /dev/null
@@ -0,0 +1,96 @@
+#include "src/conf/msg.h"
+#include "src/ast/ast.h"
+
+namespace re2c {
+
+void validate_mode(Scanner::ParseMode mode, bool rflag, bool rules, Scanner &input)
+{
+       if (mode == Scanner::Rules) {
+               if (!rflag) {
+                       input.fatal("found 'rules:re2c' block without -r flag");
+               } else if (rules) {
+                       input.fatal("cannot have a second 'rules:re2c' block");
+               }
+       } else if (mode == Scanner::Reuse) {
+               if (!rflag) {
+                       input.fatal("found 'use:re2c' block without -r flag");
+               } else if (!rules) {
+                       input.fatal("got 'use:re2c' without 'rules:re2c'");
+               }
+       } else if (rflag) {
+               input.fatal("found standard 're2c' block while using -r flag");
+       }
+}
+
+void validate_ast(const specs_t &specs, bool cflag)
+{
+       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);
+               }
+       }
+
+       if (!cflag) {
+               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);
+                       }
+               }
+       } else {
+               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 (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->setup[0]->fline, i->name.c_str());
+                               exit(1);
+                       }
+               }
+
+               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);
+                       }
+               }
+       }
+}
+
+} // namespace re2c
index 4f56d8b7b43241153b41fa3c4e365adb80843360..3cfbeec7976214b8949b26311d8974fa460f27d8 100644 (file)
@@ -3,14 +3,18 @@
 #include <set>
 
 #include "src/code/output.h"
+#include "src/conf/msg.h"
 #include "src/compile.h"
 #include "src/adfa/adfa.h"
 #include "src/adfa/dump.h"
+#include "src/ast/parser.h"
 #include "src/dfa/dfa.h"
 #include "src/dfa/dump.h"
 #include "src/nfa/nfa.h"
+#include "src/re/encoding/range_suffix.h"
 #include "src/skeleton/skeleton.h"
 #include "src/ast/ast.h"
+#include "src/util/smart_ptr.h"
 
 namespace re2c {
 
@@ -27,7 +31,7 @@ static std::string make_name(const std::string &cond, uint32_t line)
        return name;
 }
 
-smart_ptr<DFA> compile(const spec_t &spec, Output &output)
+static smart_ptr<DFA> ast_to_dfa(const spec_t &spec, Output &output)
 {
        const opt_t *opts = output.source.block().opts;
        Warn &warn = output.source.warn;
@@ -100,4 +104,75 @@ smart_ptr<DFA> compile(const spec_t &spec, Output &output)
        return make_smart_ptr(adfa);
 }
 
+void compile(Scanner &input, Output &output, Opt &opts)
+{
+       specs_t rspecs;
+       symtab_t symtab;
+       const conopt_t *globopts = &opts.glob;
+       const opt_t *ropts = NULL;
+       OutputFile &o = output.source;
+       typedef std::vector<smart_ptr<DFA> > dfas_t;
+
+       o.new_block(opts);
+       o.wversion_time().wline_info(input.get_cline(), input.get_fname().c_str());
+       if (globopts->target == TARGET_SKELETON) {
+               emit_prolog(o);
+       }
+
+       for (Scanner::ParseMode mode; (mode = input.echo(o)) != Scanner::Stop;) {
+
+               validate_mode(mode, globopts->rFlag, ropts, input);
+
+               // parse next re2c block
+               specs_t specs;
+               if (mode == Scanner::Reuse) {
+                       specs = rspecs;
+                       opts.restore(ropts);
+                       opts.reset_mapCodeName();
+                       o.label_counter.reset();
+                       o.fill_index = 0;
+                       o.state_goto = false;
+                       o.cond_goto = false;
+               }
+               parse(input, specs, symtab, opts);
+
+               // start new output block with accumulated options
+               o.new_block(opts);
+
+               if (mode == Scanner::Rules) {
+                       // save AST and options for future use
+                       rspecs = specs;
+                       ropts = o.block().opts;
+               } else {
+                       validate_ast(specs, globopts->cFlag);
+                       normalize_ast(specs);
+
+                       // compile AST to DFA
+                       o.block().line = input.get_cline();
+                       dfas_t dfas;
+                       for (specs_t::const_iterator i = specs.begin(); i != specs.end(); ++i) {
+                               dfas.push_back(ast_to_dfa(*i, output));
+                       }
+
+                       // compile DFA to code
+                       bool prolog = false;
+                       uint32_t ind = o.block().opts->topIndent;
+                       for (dfas_t::const_iterator i = dfas.begin(); i != dfas.end(); ++i) {
+                               (*i)->emit(output, ind, (i + 1) == dfas.end(), prolog);
+                       }
+               }
+
+               o.wline_info (input.get_cline (), input.get_fname ().c_str ());
+       }
+
+       if (globopts->target == TARGET_SKELETON) {
+               emit_epilog (o, output.skeletons);
+       }
+
+       AST::flist.clear();
+       Code::flist.clear();
+       Range::vFreeList.clear();
+       RangeSuffix::freeList.clear();
+}
+
 } // namespace re2c
index fd41edbf819bd935da91aab00cd765765c4439e2..0ace65040ca9d177d346be5910a8d8c23428e98d 100644 (file)
@@ -1,14 +1,14 @@
 #ifndef _RE2C_COMPILE_
 #define _RE2C_COMPILE_
 
-#include "src/ast/parser.h"
+#include "src/ast/scanner.h"
+#include "src/code/output.h"
+#include "src/conf/opt.h"
 
 namespace re2c
 {
 
-struct Output;
-
-smart_ptr<DFA> compile(const spec_t &spec, Output &output);
+void compile(Scanner &input, Output &output, Opt &opts);
 
 } // namespace re2c
 
index 7637bc27aa92998e5bf98f83512850065dfd8925..06b3a31eb8217bbaedaf0b045754e3e55003fdac 100644 (file)
@@ -1,12 +1,11 @@
 #include "src/util/c99_stdint.h"
 #include <string>
 
-#include "src/code/output.h"
+#include "src/compile.h"
 #include "src/conf/msg.h"
 #include "src/conf/opt.h"
 #include "src/conf/warn.h"
 #include "src/ast/input.h"
-#include "src/ast/parser.h"
 #include "src/ast/scanner.h"
 
 using namespace re2c;
@@ -31,7 +30,7 @@ int main(int, char *argv[])
        Scanner scanner(input, warn);
        Output output(warn);
 
-       parse(scanner, output, opts);
+       compile(scanner, output, opts);
        if (!output.emit()) return 1;
 
        return warn.error() ? 1 : 0;