From: Ulya Trofimovich Date: Wed, 8 Mar 2017 08:32:16 +0000 (+0000) Subject: Moved the main driver out of parser grammar file. X-Git-Tag: 1.0~39^2~91 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=eba6b926fbdb93d5e796ff9f0712600eae658aa2;p=re2c Moved the main driver out of parser grammar file. --- diff --git a/re2c/Makefile.am b/re2c/Makefile.am index 3b491be8..8b524279 100644 --- a/re2c/Makefile.am +++ b/re2c/Makefile.am @@ -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 = \ diff --git a/re2c/bootstrap/src/ast/lex.cc b/re2c/bootstrap/src/ast/lex.cc index dd4cfd81..b811e669 100644 --- a/re2c/bootstrap/src/ast/lex.cc +++ b/re2c/bootstrap/src/ast/lex.cc @@ -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 diff --git a/re2c/bootstrap/src/ast/parser.cc b/re2c/bootstrap/src/ast/parser.cc index b99e52a5..e2e663ec 100644 --- a/re2c/bootstrap/src/ast/parser.cc +++ b/re2c/bootstrap/src/ast/parser.cc @@ -65,30 +65,7 @@ -#include "src/util/c99_stdint.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 diff --git a/re2c/src/ast/ast.h b/re2c/src/ast/ast.h index e5bd7689..7580a7f5 100644 --- a/re2c/src/ast/ast.h +++ b/re2c/src/ast/ast.h @@ -2,9 +2,11 @@ #define _RE2C_AST_AST_ #include "src/util/c99_stdint.h" +#include #include #include +#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 rules; + std::vector defs; + std::vector setup; + + explicit spec_t(const std::string &n): + name(n), rules(), defs(), setup() {} +}; + +typedef std::vector specs_t; +typedef std::map symtab_t; + const AST *ast_nil(uint32_t l, uint32_t c); const AST *ast_str(uint32_t l, uint32_t c, std::vector *chars, bool icase); const AST *ast_cls(uint32_t l, uint32_t c, std::vector *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 index 00000000..40e0232b --- /dev/null +++ b/re2c/src/ast/normalize.cc @@ -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 diff --git a/re2c/src/ast/parser.h b/re2c/src/ast/parser.h index 563441d0..d820fed1 100644 --- a/re2c/src/ast/parser.h +++ b/re2c/src/ast/parser.h @@ -1,36 +1,17 @@ #ifndef _RE2C_AST_PARSER_ #define _RE2C_AST_PARSER_ -#include +#include #include -#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 rules; - std::vector defs; - std::vector setup; - - explicit spec_t(const std::string &n): - name(n), rules(), defs(), setup() {} -}; - -typedef std::vector specs_t; typedef std::set CondList; -typedef std::map symtab_t; -typedef std::vector > 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_ diff --git a/re2c/src/ast/parser.ypp b/re2c/src/ast/parser.ypp index 75fbec77..e4b1f919 100644 --- a/re2c/src/ast/parser.ypp +++ b/re2c/src/ast/parser.ypp @@ -1,29 +1,6 @@ %{ -#include "src/util/c99_stdint.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 index 00000000..a770e4d5 --- /dev/null +++ b/re2c/src/ast/validate.cc @@ -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 diff --git a/re2c/src/compile.cc b/re2c/src/compile.cc index 4f56d8b7..3cfbeec7 100644 --- a/re2c/src/compile.cc +++ b/re2c/src/compile.cc @@ -3,14 +3,18 @@ #include #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 compile(const spec_t &spec, Output &output) +static smart_ptr 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 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 > 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 diff --git a/re2c/src/compile.h b/re2c/src/compile.h index fd41edbf..0ace6504 100644 --- a/re2c/src/compile.h +++ b/re2c/src/compile.h @@ -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 compile(const spec_t &spec, Output &output); +void compile(Scanner &input, Output &output, Opt &opts); } // namespace re2c diff --git a/re2c/src/main.cc b/re2c/src/main.cc index 7637bc27..06b3a31e 100644 --- a/re2c/src/main.cc +++ b/re2c/src/main.cc @@ -1,12 +1,11 @@ #include "src/util/c99_stdint.h" #include -#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;