From a1638639d79a779b0f3c5196b1ad6d7bf965a997 Mon Sep 17 00:00:00 2001 From: Ulya Trofimovich Date: Tue, 19 May 2015 12:53:24 +0100 Subject: [PATCH] Simplified 're2c::Action' class and its usage. Replaced inheritance hierarchy with tagged union. --- re2c/Makefile.am | 7 +- re2c/bootstrap/parser.cc | 2 +- re2c/src/codegen/dfa_emit.cc | 709 ------------------ re2c/src/codegen/dfa_emit.h | 40 - re2c/src/codegen/emit.h | 32 + re2c/src/codegen/emit_action.cc | 392 ++++++++++ re2c/src/codegen/emit_dfa.cc | 341 +++++++++ .../{dfa_prepare.cc => prepare_dfa.cc} | 19 +- re2c/src/dfa/action.h | 167 ++--- re2c/src/dfa/dfa.cc | 3 - re2c/src/dfa/state.cc | 4 +- re2c/src/dfa/state.h | 5 +- re2c/src/parse/parser.ypp | 2 +- 13 files changed, 852 insertions(+), 871 deletions(-) delete mode 100644 re2c/src/codegen/dfa_emit.cc delete mode 100644 re2c/src/codegen/dfa_emit.h create mode 100644 re2c/src/codegen/emit.h create mode 100644 re2c/src/codegen/emit_action.cc create mode 100644 re2c/src/codegen/emit_dfa.cc rename re2c/src/codegen/{dfa_prepare.cc => prepare_dfa.cc} (91%) diff --git a/re2c/Makefile.am b/re2c/Makefile.am index a5bfd0a3..8975d988 100644 --- a/re2c/Makefile.am +++ b/re2c/Makefile.am @@ -29,7 +29,7 @@ BOOTSTRAP_DOC_HTML = $(srcdir)/bootstrap/manual.html SRC_HDR = \ $(srcdir)/src/codegen/bitmap.h \ $(srcdir)/src/codegen/code_names.h \ - $(srcdir)/src/codegen/dfa_emit.h \ + $(srcdir)/src/codegen/emit.h \ $(srcdir)/src/codegen/go.h \ $(srcdir)/src/codegen/indent.h \ $(srcdir)/src/codegen/input_api.h \ @@ -68,8 +68,9 @@ SRC = \ $(SRC_SCANNER) \ $(srcdir)/src/codegen/bitmap.cc \ $(srcdir)/src/codegen/code_names.cc \ - $(srcdir)/src/codegen/dfa_emit.cc \ - $(srcdir)/src/codegen/dfa_prepare.cc \ + $(srcdir)/src/codegen/emit_action.cc \ + $(srcdir)/src/codegen/emit_dfa.cc \ + $(srcdir)/src/codegen/prepare_dfa.cc \ $(srcdir)/src/codegen/go_construct.cc \ $(srcdir)/src/codegen/go_destruct.cc \ $(srcdir)/src/codegen/go_emit.cc \ diff --git a/re2c/bootstrap/parser.cc b/re2c/bootstrap/parser.cc index 3662c911..08b94e03 100644 --- a/re2c/bootstrap/parser.cc +++ b/re2c/bootstrap/parser.cc @@ -81,7 +81,7 @@ #include "config.h" #include "src/dfa/dfa.h" -#include "src/codegen/dfa_emit.h" // genTypes +#include "src/codegen/emit.h" // genTypes #include "src/globals.h" #include "src/parse/parser.h" #include "src/util/c99_stdint.h" diff --git a/re2c/src/codegen/dfa_emit.cc b/re2c/src/codegen/dfa_emit.cc deleted file mode 100644 index 964e8da7..00000000 --- a/re2c/src/codegen/dfa_emit.cc +++ /dev/null @@ -1,709 +0,0 @@ -#include - -#include "src/codegen/bitmap.h" -#include "src/codegen/dfa_emit.h" -#include "src/codegen/go.h" -#include "src/codegen/indent.h" -#include "src/codegen/input_api.h" -#include "src/codegen/skeleton/skeleton.h" -#include "src/dfa/dfa.h" - -namespace re2c -{ - -void genYYFill(OutputFile & o, uint32_t, uint32_t need) -{ - if (bUseYYFillParam) - { - o << mapCodeName["YYFILL"]; - if (!bUseYYFillNaked) - { - o << "(" << need << ");"; - } - o << "\n"; - } - else - { - o << replaceParam(mapCodeName["YYFILL"], yyFillLength, need); - if (!bUseYYFillNaked) - { - o << ";"; - } - o << "\n"; - } -} - -std::string genGetCondition() -{ - if (bUseYYGetConditionNaked) - { - return mapCodeName["YYGETCONDITION"]; - } - else - { - return mapCodeName["YYGETCONDITION"] + "()"; - } -} - -void genSetCondition(OutputFile & o, uint32_t ind, const std::string& newcond) -{ - if (bUseYYSetConditionParam) - { - o << indent(ind) << mapCodeName["YYSETCONDITION"] << "(" << condEnumPrefix << newcond << ");\n"; - } - else - { - o << indent(ind) << replaceParam(mapCodeName["YYSETCONDITION"], yySetConditionParam, condEnumPrefix + newcond) << "\n"; - } -} - -void genGoTo(OutputFile & o, uint32_t ind, const State *from, const State *to, bool & readCh) -{ - if (DFlag) - { - o << from->label << " -> " << to->label << "\n"; - return; - } - - if (readCh && from->label + 1 != to->label) - { - o << input_api.stmt_peek (ind); - readCh = false; - } - - o << indent(ind) << "goto " << labelPrefix << to->label << ";\n"; - vUsedLabels.insert(to->label); -} - -void need(OutputFile & o, uint32_t ind, uint32_t n, bool & readCh, bool bSetMarker) -{ - if (DFlag) - { - return; - } - - uint32_t fillIndex = next_fill_index; - - if (fFlag) - { - next_fill_index++; - if (bUseYYSetStateParam) - { - o << indent(ind) << mapCodeName["YYSETSTATE"] << "(" << fillIndex << ");\n"; - } - else - { - o << indent(ind) << replaceParam(mapCodeName["YYSETSTATE"], yySetStateParam, fillIndex) << "\n"; - } - } - - if (bUseYYFill && n > 0) - { - o << indent(ind); - if (n == 1) - { - if (bUseYYFillCheck) - { - o << "if (" << input_api.expr_lessthan_one () << ") "; - } - genYYFill(o, ind, n); - } - else - { - if (bUseYYFillCheck) - { - o << "if (" << input_api.expr_lessthan (n) << ") "; - } - genYYFill(o, ind, n); - } - } - - if (fFlag) - { - o << mapCodeName["yyFillLabel"] << fillIndex << ":\n"; - } - - if (n > 0) - { - if (bSetMarker) - { - o << input_api.stmt_backup_peek (ind); - } - else - { - o << input_api.stmt_peek (ind); - } - readCh = false; - } -} - -void Match::emit(Output & output, uint32_t ind, bool &readCh, const std::string&) const -{ - OutputFile & o = output.source; - - if (DFlag) - { - return; - } - - if (state->link) - { - o << input_api.stmt_skip (ind); - } - else if (!readAhead()) - { - /* do not read next char if match */ - o << input_api.stmt_skip (ind); - readCh = true; - } - else - { - o << input_api.stmt_skip_peek (ind); - readCh = false; - } - - if (state->link) - { - need(o, ind, state->depth, readCh, false); - } -} - -void Initial::emit(Output & output, uint32_t ind, bool &readCh, const std::string&) const -{ - OutputFile & o = output.source; - - if (!cFlag && !startLabelName.empty()) - { - o << startLabelName << ":\n"; - } - - if (vUsedLabels.count(label+1)) - { - if (state->link) - { - o << input_api.stmt_skip (ind); - } - else - { - o << input_api.stmt_skip_peek (ind); - } - } - - if (vUsedLabels.count(label)) - { - o << labelPrefix << label << ":\n"; - } - else if (!label) - { - o << "\n"; - } - - if (dFlag) - { - o << indent(ind) << mapCodeName["YYDEBUG"] << "(" << label << ", *" << mapCodeName["YYCURSOR"] << ");" << "\n"; - } - - if (state->link) - { - need(o, ind, state->depth, readCh, setMarker && bUsedYYMarker); - } - else - { - if (setMarker && bUsedYYMarker) - { - o << input_api.stmt_backup (ind); - } - readCh = false; - } -} - -void Save::emit(Output & output, uint32_t ind, bool &readCh, const std::string&) const -{ - OutputFile & o = output.source; - - if (DFlag) - { - return; - } - - o.insert_yyaccept_selector (ind, selector); - - if (state->link) - { - if (bUsedYYMarker) - { - o << input_api.stmt_skip_backup (ind); - } - need(o, ind, state->depth, readCh, false); - } - else - { - if (bUsedYYMarker) - { - o << input_api.stmt_skip_backup_peek (ind); - } - else - { - o << input_api.stmt_skip_peek (ind); - } - readCh = false; - } -} - -void Move::emit(Output &, uint32_t, bool &, const std::string&) const -{ - ; -} - -void Accept::genRuleMap() -{ - for (uint32_t i = 0; i < nRules; ++i) - { - if (saves[i] != ~0u) - { - mapRules[saves[i]] = rules[i]; - } - } -} - -void Accept::emitBinary(OutputFile & o, uint32_t ind, uint32_t l, uint32_t r, bool &readCh) const -{ - if (l < r) - { - uint32_t m = (l + r) >> 1; - - o << indent(ind) << "if (" << mapCodeName["yyaccept"] << (r == l+1 ? " == " : " <= ") << m << ") {\n"; - emitBinary(o, ++ind, l, m, readCh); - o << indent(--ind) << "} else {\n"; - emitBinary(o, ++ind, m + 1, r, readCh); - o << indent(--ind) << "}\n"; - } - else - { - genGoTo(o, ind, state, mapRules.find(l)->second, readCh); - } -} - -void Accept::emit(Output & output, uint32_t ind, bool &readCh, const std::string &) const -{ - OutputFile & o = output.source; - - if (mapRules.size() > 0) - { - bUsedYYMarker = true; - if (!DFlag) - { - o << input_api.stmt_restore (ind); - } - - if (readCh) // shouldn't be necessary, but might become at some point - { - o << input_api.stmt_peek (ind); - readCh = false; - } - - if (mapRules.size() > 1) - { - o.set_used_yyaccept (); - - if (gFlag && mapRules.size() >= cGotoThreshold) - { - o << indent(ind++) << "{\n"; - o << indent(ind++) << "static void *" << mapCodeName["yytarget"] << "[" << mapRules.size() << "] = {\n"; - for (RuleMap::const_iterator it = mapRules.begin(); it != mapRules.end(); ++it) - { - o << indent(ind) << "&&" << labelPrefix << it->second->label << ",\n"; - vUsedLabels.insert(it->second->label); - } - o << indent(--ind) << "};\n"; - o << indent(ind) << "goto *" << mapCodeName["yytarget"] << "[" << mapCodeName["yyaccept"] << "];\n"; - o << indent(--ind) << "}\n"; - } - else if (sFlag || (mapRules.size() == 2 && !DFlag)) - { - emitBinary(o, ind, 0, mapRules.size() - 1, readCh); - } - else if (DFlag) - { - for (RuleMap::const_iterator it = mapRules.begin(); it != mapRules.end(); ++it) - { - o << state->label << " -> " << it->second->label; - o << " [label=\"yyaccept=" << it->first << "\"]\n"; - } - } - else - { - o << indent(ind) << "switch (" << mapCodeName["yyaccept"] << ") {\n"; - - RuleMap::const_iterator it = mapRules.begin(), end = mapRules.end(); - - while (it != end) - { - RuleMap::const_iterator tmp = it; - - if (++it == end) - { - o << indent(ind) << "default:\t"; - } - else - { - o << indent(ind) << "case " << tmp->first << ": \t"; - } - - genGoTo(o, 0, state, tmp->second, readCh); - } - - o << indent(ind) << "}\n"; - } - } - else - { - // no need to write if statement here since there is only case 0. - genGoTo(o, ind, state, mapRules.find(0)->second, readCh); - } - } -} - -void Rule::emit(Output & output, uint32_t ind, bool &, const std::string& condName) const -{ - OutputFile & o = output.source; - - if (DFlag) - { - o << state->label << " [label=\"" << rule->code->source << ":" << rule->code->line << "\"]\n"; - return; - } - - uint32_t back = rule->ctx->fixedLength(); - - if (back != 0u && !DFlag) - { - o << input_api.stmt_restorectx (ind); - } - - if (rule->code->newcond.length() && condName != rule->code->newcond) - { - genSetCondition(o, ind, rule->code->newcond); - } - - if (!yySetupRule.empty() && !rule->code->autogen) - { - o << indent(ind) << yySetupRule << "\n"; - } - - o.write_line_info (rule->code->line, rule->code->source.c_str ()); - o << indent(ind); - if (flag_skeleton) - { - o << "{ if (cursor == &data[result[i].endpos] && result[i].rule == " << rule->accept << ") "; - o << "{ cursor = &data[result[i].startpos]; continue; }"; - o << " else "; - o << "{ printf (\"error: %lu/%u, %u/%u, '%s'\\n\", cursor - data, result[i].endpos, result[i].rule, " - << rule->accept - << ", &data[result[i].startpos]); return 1; } }"; - } - else if (rule->code->autogen) - { - o << replaceParam(condGoto, condGotoParam, condPrefix + rule->code->newcond); - } - else - { - o << rule->code->text; - } - o << "\n"; - o.insert_line_info (); -} - -void State::emit(Output & output, uint32_t ind, bool &readCh, const std::string& condName) const -{ - OutputFile & o = output.source; - - if (vUsedLabels.count(label)) - { - o << labelPrefix << label << ":\n"; - } - if (dFlag && (action->type != Action::INITIAL)) - { - o << indent(ind) << mapCodeName["YYDEBUG"] << "(" << label << ", " << input_api.expr_peek () << ");\n"; - } - if (isPreCtxt && !DFlag) - { - o << input_api.stmt_backupctx (ind); - } - action->emit(output, ind, readCh, condName); -} - -void DFA::emit(Output & output, uint32_t& ind, const RegExpMap* specMap, const std::string& condName, bool isLastCond, bool& bPrologBrace) -{ - OutputFile & o = output.source; - - bool bProlog = (!cFlag || !bWroteCondCheck); - - // In -c mode, the prolog needs its own label separate from start_label. - // prolog_label is before the condition branch (GenCondGoto). It is - // equivalent to startLabelName. - // start_label corresponds to current condition. - // NOTE: prolog_label must be yy0 because of the !getstate:re2c handling - // in scanner.re - uint32_t prolog_label = next_label; - if (bProlog && cFlag) - { - next_label++; - } - - uint32_t start_label = next_label; - - (void) new Initial(head, next_label++, bSaveOnHead); - - if (bUseStartLabel) - { - if (startLabelName.empty()) - { - vUsedLabels.insert(prolog_label); - } - } - - State *s; - - for (s = head; s; s = s->next) - { - s->label = next_label++; - } - - for (s = head; s; s = s->next) - { - s->go.used_labels (); - } - - // Save 'next_fill_index' and compute information about code generation - // while writing to null device. - uint32_t save_fill_index = next_fill_index; - Output null_dev (NULL, NULL); - - for (s = head; s; s = s->next) - { - bool readCh = false; - s->emit(null_dev, ind, readCh, condName); - s->go.emit(null_dev.source, ind, readCh); - } - if (last_fill_index < next_fill_index) - { - last_fill_index = next_fill_index; - } - next_fill_index = save_fill_index; - - // Generate prolog - if (bProlog) - { - o << "\n"; - o.insert_line_info (); - - if (DFlag) - { - bPrologBrace = true; - o << "digraph re2c {\n"; - } - else if ((!fFlag && o.get_used_yyaccept ()) - || (!fFlag && bEmitYYCh) - || (bFlag && !cFlag && BitMap::first) - || (cFlag && !bWroteCondCheck && gFlag && !specMap->empty()) - || (fFlag && !bWroteGetState && gFlag) - ) - { - bPrologBrace = true; - o << indent(ind++) << "{\n"; - } - else if (ind == 0) - { - ind = 1; - } - - if (!fFlag && !DFlag) - { - if (bEmitYYCh) - { - o << indent(ind) << mapCodeName["YYCTYPE"] << " " << mapCodeName["yych"] << ";\n"; - } - o.insert_yyaccept_init (ind); - } - else - { - o << "\n"; - } - } - if (bFlag && !cFlag && BitMap::first) - { - BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256); - } - if (bProlog) - { - genCondTable(o, ind, *specMap); - o.insert_state_goto (ind, prolog_label); - if (cFlag && !DFlag) - { - if (vUsedLabels.count(prolog_label)) - { - o << labelPrefix << prolog_label << ":\n"; - } - if (!startLabelName.empty()) - { - o << startLabelName << ":\n"; - } - } - genCondGoto(o, ind, *specMap); - } - - if (cFlag && !condName.empty()) - { - if (condDivider.length()) - { - o << replaceParam(condDivider, condDividerParam, condName) << "\n"; - } - - if (DFlag) - { - o << condName << " -> " << (start_label+1) << "\n"; - } - else - { - o << condPrefix << condName << ":\n"; - } - } - if (cFlag && bFlag && BitMap::first) - { - o << indent(ind++) << "{\n"; - BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256); - } - - // The start_label is not always the first to be emitted, so we may have to jump. c.f. Initial::emit() - if (vUsedLabels.count(start_label+1)) - { - vUsedLabels.insert(start_label); - o << indent(ind) << "goto " << labelPrefix << start_label << ";\n"; - } - - // Generate code - for (s = head; s; s = s->next) - { - bool readCh = false; - s->emit(output, ind, readCh, condName); - s->go.emit(o, ind, readCh); - } - - if (cFlag && bFlag && BitMap::first) - { - o << indent(--ind) << "}\n"; - } - // Generate epilog - if ((!cFlag || isLastCond) && bPrologBrace) - { - o << indent(--ind) << "}\n"; - } - if (flag_skeleton) - { - skeleton::emit_epilog (o, ind); - } - - // Cleanup - if (BitMap::first) - { - delete BitMap::first; - BitMap::first = NULL; - } - - bUseStartLabel = false; -} - -void genCondTable(OutputFile & o, uint32_t ind, const RegExpMap& specMap) -{ - if (cFlag && !bWroteCondCheck && gFlag && specMap.size()) - { - RegExpIndices vCondList(specMap.size()); - - for(RegExpMap::const_iterator itSpec = specMap.begin(); itSpec != specMap.end(); ++itSpec) - { - vCondList[itSpec->second.first] = itSpec->first; - } - - o << indent(ind++) << "static void *" << mapCodeName["yyctable"] << "[" << specMap.size() << "] = {\n"; - - for(RegExpIndices::const_iterator it = vCondList.begin(); it != vCondList.end(); ++it) - { - o << indent(ind) << "&&" << condPrefix << *it << ",\n"; - } - o << indent(--ind) << "};\n"; - } -} - -void genCondGotoSub(OutputFile & o, uint32_t ind, RegExpIndices& vCondList, uint32_t cMin, uint32_t cMax) -{ - if (cMin == cMax) - { - o << indent(ind) << "goto " << condPrefix << vCondList[cMin] << ";\n"; - } - else - { - uint32_t cMid = cMin + ((cMax - cMin + 1) / 2); - - o << indent(ind) << "if (" << genGetCondition() << " < " << cMid << ") {\n"; - genCondGotoSub(o, ind + 1, vCondList, cMin, cMid - 1); - o << indent(ind) << "} else {\n"; - genCondGotoSub(o, ind + 1, vCondList, cMid, cMax); - o << indent(ind) << "}\n"; - } -} - -void genCondGoto(OutputFile & o, uint32_t ind, const RegExpMap& specMap) -{ - if (cFlag && !bWroteCondCheck && specMap.size()) - { - if (gFlag) - { - o << indent(ind) << "goto *" << mapCodeName["yyctable"] << "[" << genGetCondition() << "];\n"; - } - else - { - if (sFlag) - { - RegExpIndices vCondList(specMap.size()); - - for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it) - { - vCondList[it->second.first] = it->first; - } - genCondGotoSub(o, ind, vCondList, 0, vCondList.size() - 1); - } - else if (DFlag) - { - for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it) - { - o << "0 -> " << it->first << " [label=\"state=" << it->first << "\"]\n"; - } - } - else - { - o << indent(ind) << "switch (" << genGetCondition() << ") {\n"; - - for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it) - { - o << indent(ind) << "case " << condEnumPrefix << it->first << ": goto " << condPrefix << it->first << ";\n"; - } - o << indent(ind) << "}\n"; - } - } - bWroteCondCheck = true; - } -} - -void genTypes(Output & output, const RegExpMap& specMap) -{ - output.types.resize (specMap.size()); - for(RegExpMap::const_iterator itSpecMap = specMap.begin(); itSpecMap != specMap.end(); ++itSpecMap) - { - // If an entry is < 0 then we did the 0/empty correction twice. - assert(itSpecMap->second.first >= 0); - output.types[itSpecMap->second.first] = itSpecMap->first; - } -} - -} // end namespace re2c diff --git a/re2c/src/codegen/dfa_emit.h b/re2c/src/codegen/dfa_emit.h deleted file mode 100644 index e286cc9c..00000000 --- a/re2c/src/codegen/dfa_emit.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __DFA_EMIT__ -#define __DFA_EMIT__ - -#include "src/codegen/output.h" -#include "src/dfa/dfa.h" - -namespace re2c { - -class DFA; - -typedef std::vector RegExpIndices; - -void genCondTable (OutputFile &, uint32_t, const RegExpMap &); -void genCondGoto (OutputFile &, uint32_t, const RegExpMap &); -void genTypes (Output &, const RegExpMap &); - -// helpers -void genYYFill (OutputFile & o, uint32_t, uint32_t need); -std::string genGetCondition (); -void genSetCondition (OutputFile & o, uint32_t ind, const std::string & newcond); -void genGoTo (OutputFile & o, uint32_t ind, const State * from, const State * to, bool & readCh); -void need (OutputFile & o, uint32_t ind, uint32_t n, bool & readCh, bool bSetMarker); -void genCondGotoSub (OutputFile & o, uint32_t ind, RegExpIndices & vCondList, uint32_t cMin, uint32_t cMax); - -template -std::string replaceParam (std::string str, const std::string & param, const _Ty & value) -{ - std::ostringstream strValue; - strValue << value; - std::string::size_type pos; - while((pos = str.find(param)) != std::string::npos) - { - str.replace(pos, param.length(), strValue.str()); - } - return str; -} - -} // namespace re2c - -#endif // __DFA_EMIT__ diff --git a/re2c/src/codegen/emit.h b/re2c/src/codegen/emit.h new file mode 100644 index 00000000..164faad0 --- /dev/null +++ b/re2c/src/codegen/emit.h @@ -0,0 +1,32 @@ +#ifndef __EMIT__ +#define __EMIT__ + +#include "src/codegen/output.h" +#include "src/dfa/dfa.h" + +namespace re2c { + +class DFA; +typedef std::vector RegExpIndices; + +void emit_action (const Action & action, OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const std::string & condName); + +// helpers +void genGoTo (OutputFile & o, uint32_t ind, const State * from, const State * to, bool & readCh); +void genTypes (Output &, const RegExpMap &); + +template std::string replaceParam (std::string str, const std::string & param, const _Ty & value) +{ + std::ostringstream strValue; + strValue << value; + std::string::size_type pos; + while((pos = str.find(param)) != std::string::npos) + { + str.replace(pos, param.length(), strValue.str()); + } + return str; +} + +} // namespace re2c + +#endif // __EMIT__ diff --git a/re2c/src/codegen/emit_action.cc b/re2c/src/codegen/emit_action.cc new file mode 100644 index 00000000..b203e570 --- /dev/null +++ b/re2c/src/codegen/emit_action.cc @@ -0,0 +1,392 @@ +#include "src/codegen/emit.h" +#include "src/codegen/indent.h" +#include "src/codegen/input_api.h" +#include "src/codegen/skeleton/skeleton.h" +#include "src/dfa/action.h" + +namespace re2c +{ + +static void need (OutputFile & o, uint32_t ind, bool & readCh, uint32_t n, bool bSetMarker); +static void emit_match (OutputFile & o, uint32_t ind, bool & readCh, const State * const s); +static void emit_initial (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const Initial & init); +static void emit_save (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, uint32_t save); +static void emit_accept_binary (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accept, uint32_t l, uint32_t r); +static void emit_accept (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accept); +static void emit_rule (OutputFile & o, uint32_t ind, const State * const s, const RuleOp * const rule, const std::string & condName); +static void genYYFill (OutputFile & o, uint32_t need); +static void genSetCondition (OutputFile & o, uint32_t ind, const std::string & newcond); + +void emit_action (const Action & action, OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const std::string & condName) +{ + switch (action.type) + { + case Action::MATCH: + emit_match (o, ind, readCh, s); + break; + case Action::INITIAL: + emit_initial (o, ind, readCh, s, * action.info.initial); + break; + case Action::SAVE: + emit_save (o, ind, readCh, s, action.info.save); + break; + case Action::MOVE: + break; + case Action::ACCEPT: + emit_accept (o, ind, readCh, s, * action.info.accept); + break; + case Action::RULE: + emit_rule (o, ind, s, action.info.rule, condName); + break; + } +} + +void emit_match (OutputFile & o, uint32_t ind, bool & readCh, const State * const s) +{ + if (DFlag) + { + return; + } + + const bool read_ahead = s + && s->next + && s->next->action.type != Action::RULE; + if (s->link) + { + o << input_api.stmt_skip (ind); + } + else if (!read_ahead) + { + /* do not read next char if match */ + o << input_api.stmt_skip (ind); + readCh = true; + } + else + { + o << input_api.stmt_skip_peek (ind); + readCh = false; + } + + if (s->link) + { + need(o, ind, readCh, s->depth, false); + } +} + +void emit_initial (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const Initial & initial) +{ + if (!cFlag && !startLabelName.empty()) + { + o << startLabelName << ":\n"; + } + + if (vUsedLabels.count(initial.label+1)) + { + if (s->link) + { + o << input_api.stmt_skip (ind); + } + else + { + o << input_api.stmt_skip_peek (ind); + } + } + + if (vUsedLabels.count(initial.label)) + { + o << labelPrefix << initial.label << ":\n"; + } + else if (!initial.label) + { + o << "\n"; + } + + if (dFlag) + { + o << indent(ind) << mapCodeName["YYDEBUG"] << "(" << initial.label << ", *" << mapCodeName["YYCURSOR"] << ");" << "\n"; + } + + if (s->link) + { + need(o, ind, readCh, s->depth, initial.setMarker && bUsedYYMarker); + } + else + { + if (initial.setMarker && bUsedYYMarker) + { + o << input_api.stmt_backup (ind); + } + readCh = false; + } +} + +void emit_save (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, uint32_t save) +{ + if (DFlag) + { + return; + } + + o.insert_yyaccept_selector (ind, save); + + if (s->link) + { + if (bUsedYYMarker) + { + o << input_api.stmt_skip_backup (ind); + } + need(o, ind, readCh, s->depth, false); + } + else + { + if (bUsedYYMarker) + { + o << input_api.stmt_skip_backup_peek (ind); + } + else + { + o << input_api.stmt_skip_peek (ind); + } + readCh = false; + } +} + +void emit_accept_binary (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accept, uint32_t l, uint32_t r) +{ + if (l < r) + { + const uint32_t m = (l + r) >> 1; + o << indent(ind) << "if (" << mapCodeName["yyaccept"] << (r == l+1 ? " == " : " <= ") << m << ") {\n"; + emit_accept_binary (o, ++ind, readCh, s, accept, l, m); + o << indent(--ind) << "} else {\n"; + emit_accept_binary (o, ++ind, readCh, s, accept, m + 1, r); + o << indent(--ind) << "}\n"; + } + else + { + genGoTo(o, ind, s, accept.find(l)->second, readCh); + } +} + +void emit_accept (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accept) +{ + if (accept.size() > 0) + { + bUsedYYMarker = true; + if (!DFlag) + { + o << input_api.stmt_restore (ind); + } + + if (readCh) // shouldn't be necessary, but might become at some point + { + o << input_api.stmt_peek (ind); + readCh = false; + } + + if (accept.size() > 1) + { + o.set_used_yyaccept (); + + if (gFlag && accept.size() >= cGotoThreshold) + { + o << indent(ind++) << "{\n"; + o << indent(ind++) << "static void *" << mapCodeName["yytarget"] << "[" << accept.size() << "] = {\n"; + for (accept_t::const_iterator it = accept.begin(); it != accept.end(); ++it) + { + o << indent(ind) << "&&" << labelPrefix << it->second->label << ",\n"; + vUsedLabels.insert(it->second->label); + } + o << indent(--ind) << "};\n"; + o << indent(ind) << "goto *" << mapCodeName["yytarget"] << "[" << mapCodeName["yyaccept"] << "];\n"; + o << indent(--ind) << "}\n"; + } + else if (sFlag || (accept.size() == 2 && !DFlag)) + { + emit_accept_binary (o, ind, readCh, s, accept, 0, accept.size() - 1); + } + else if (DFlag) + { + for (accept_t::const_iterator it = accept.begin(); it != accept.end(); ++it) + { + o << s->label << " -> " << it->second->label; + o << " [label=\"yyaccept=" << it->first << "\"]\n"; + } + } + else + { + o << indent(ind) << "switch (" << mapCodeName["yyaccept"] << ") {\n"; + + accept_t::const_iterator it = accept.begin(), end = accept.end(); + + while (it != end) + { + accept_t::const_iterator tmp = it; + + if (++it == end) + { + o << indent(ind) << "default:\t"; + } + else + { + o << indent(ind) << "case " << tmp->first << ": \t"; + } + + genGoTo(o, 0, s, tmp->second, readCh); + } + + o << indent(ind) << "}\n"; + } + } + else + { + // no need to write if statement here since there is only case 0. + genGoTo(o, ind, s, accept.find(0)->second, readCh); + } + } +} + +void emit_rule (OutputFile & o, uint32_t ind, const State * const s, const RuleOp * const rule, const std::string & condName) +{ + if (DFlag) + { + o << s->label << " [label=\"" << rule->code->source << ":" << rule->code->line << "\"]\n"; + return; + } + + uint32_t back = rule->ctx->fixedLength(); + if (back != 0u && !DFlag) + { + o << input_api.stmt_restorectx (ind); + } + + if (rule->code->newcond.length() && condName != rule->code->newcond) + { + genSetCondition(o, ind, rule->code->newcond); + } + + if (!yySetupRule.empty() && !rule->code->autogen) + { + o << indent(ind) << yySetupRule << "\n"; + } + + o.write_line_info (rule->code->line, rule->code->source.c_str ()); + o << indent(ind); + if (flag_skeleton) + { + o << "{ if (cursor == &data[result[i].endpos] && result[i].rule == " << rule->accept << ") "; + o << "{ cursor = &data[result[i].startpos]; continue; }"; + o << " else "; + o << "{ printf (\"error: %lu/%u, %u/%u, '%s'\\n\", cursor - data, result[i].endpos, result[i].rule, " + << rule->accept + << ", &data[result[i].startpos]); return 1; } }"; + } + else if (rule->code->autogen) + { + o << replaceParam(condGoto, condGotoParam, condPrefix + rule->code->newcond); + } + else + { + o << rule->code->text; + } + o << "\n"; + o.insert_line_info (); +} + +void need (OutputFile & o, uint32_t ind, bool & readCh, uint32_t n, bool bSetMarker) +{ + if (DFlag) + { + return; + } + + uint32_t fillIndex = next_fill_index; + + if (fFlag) + { + next_fill_index++; + if (bUseYYSetStateParam) + { + o << indent(ind) << mapCodeName["YYSETSTATE"] << "(" << fillIndex << ");\n"; + } + else + { + o << indent(ind) << replaceParam(mapCodeName["YYSETSTATE"], yySetStateParam, fillIndex) << "\n"; + } + } + + if (bUseYYFill && n > 0) + { + o << indent(ind); + if (n == 1) + { + if (bUseYYFillCheck) + { + o << "if (" << input_api.expr_lessthan_one () << ") "; + } + genYYFill(o, n); + } + else + { + if (bUseYYFillCheck) + { + o << "if (" << input_api.expr_lessthan (n) << ") "; + } + genYYFill(o, n); + } + } + + if (fFlag) + { + o << mapCodeName["yyFillLabel"] << fillIndex << ":\n"; + } + + if (n > 0) + { + if (bSetMarker) + { + o << input_api.stmt_backup_peek (ind); + } + else + { + o << input_api.stmt_peek (ind); + } + readCh = false; + } +} + +void genYYFill(OutputFile & o, uint32_t need) +{ + if (bUseYYFillParam) + { + o << mapCodeName["YYFILL"]; + if (!bUseYYFillNaked) + { + o << "(" << need << ");"; + } + o << "\n"; + } + else + { + o << replaceParam(mapCodeName["YYFILL"], yyFillLength, need); + if (!bUseYYFillNaked) + { + o << ";"; + } + o << "\n"; + } +} + +void genSetCondition(OutputFile & o, uint32_t ind, const std::string& newcond) +{ + if (bUseYYSetConditionParam) + { + o << indent(ind) << mapCodeName["YYSETCONDITION"] << "(" << condEnumPrefix << newcond << ");\n"; + } + else + { + o << indent(ind) << replaceParam(mapCodeName["YYSETCONDITION"], yySetConditionParam, condEnumPrefix + newcond) << "\n"; + } +} + +} // namespace re2c diff --git a/re2c/src/codegen/emit_dfa.cc b/re2c/src/codegen/emit_dfa.cc new file mode 100644 index 00000000..da7f2a4c --- /dev/null +++ b/re2c/src/codegen/emit_dfa.cc @@ -0,0 +1,341 @@ +#include + +#include "src/codegen/bitmap.h" +#include "src/codegen/emit.h" +#include "src/codegen/go.h" +#include "src/codegen/indent.h" +#include "src/codegen/input_api.h" +#include "src/codegen/skeleton/skeleton.h" +#include "src/dfa/dfa.h" + +namespace re2c +{ + +static std::string genGetCondition (); +static void genCondGotoSub (OutputFile & o, uint32_t ind, RegExpIndices & vCondList, uint32_t cMin, uint32_t cMax); +static void genCondTable (OutputFile & o, uint32_t ind, const RegExpMap & specMap); +static void genCondGoto (OutputFile & o, uint32_t ind, const RegExpMap & specMap); + +std::string genGetCondition() +{ + if (bUseYYGetConditionNaked) + { + return mapCodeName["YYGETCONDITION"]; + } + else + { + return mapCodeName["YYGETCONDITION"] + "()"; + } +} + +void genGoTo(OutputFile & o, uint32_t ind, const State *from, const State *to, bool & readCh) +{ + if (DFlag) + { + o << from->label << " -> " << to->label << "\n"; + return; + } + + if (readCh && from->label + 1 != to->label) + { + o << input_api.stmt_peek (ind); + readCh = false; + } + + o << indent(ind) << "goto " << labelPrefix << to->label << ";\n"; + vUsedLabels.insert(to->label); +} + +void State::emit(Output & output, uint32_t ind, bool &readCh, const std::string& condName) const +{ + OutputFile & o = output.source; + + if (vUsedLabels.count(label)) + { + o << labelPrefix << label << ":\n"; + } + if (dFlag && (action.type != Action::INITIAL)) + { + o << indent(ind) << mapCodeName["YYDEBUG"] << "(" << label << ", " << input_api.expr_peek () << ");\n"; + } + if (isPreCtxt && !DFlag) + { + o << input_api.stmt_backupctx (ind); + } + emit_action (action, o, ind, readCh, this, condName); +} + +void DFA::emit(Output & output, uint32_t& ind, const RegExpMap* specMap, const std::string& condName, bool isLastCond, bool& bPrologBrace) +{ + OutputFile & o = output.source; + + bool bProlog = (!cFlag || !bWroteCondCheck); + + // In -c mode, the prolog needs its own label separate from start_label. + // prolog_label is before the condition branch (GenCondGoto). It is + // equivalent to startLabelName. + // start_label corresponds to current condition. + // NOTE: prolog_label must be yy0 because of the !getstate:re2c handling + // in scanner.re + uint32_t prolog_label = next_label; + if (bProlog && cFlag) + { + next_label++; + } + + uint32_t start_label = next_label; + + head->action.set_initial (next_label++, bSaveOnHead); + + if (bUseStartLabel) + { + if (startLabelName.empty()) + { + vUsedLabels.insert(prolog_label); + } + } + + State *s; + + for (s = head; s; s = s->next) + { + s->label = next_label++; + } + + for (s = head; s; s = s->next) + { + s->go.used_labels (); + } + + // Save 'next_fill_index' and compute information about code generation + // while writing to null device. + uint32_t save_fill_index = next_fill_index; + Output null_dev (NULL, NULL); + + for (s = head; s; s = s->next) + { + bool readCh = false; + s->emit(null_dev, ind, readCh, condName); + s->go.emit(null_dev.source, ind, readCh); + } + if (last_fill_index < next_fill_index) + { + last_fill_index = next_fill_index; + } + next_fill_index = save_fill_index; + + // Generate prolog + if (bProlog) + { + o << "\n"; + o.insert_line_info (); + + if (DFlag) + { + bPrologBrace = true; + o << "digraph re2c {\n"; + } + else if ((!fFlag && o.get_used_yyaccept ()) + || (!fFlag && bEmitYYCh) + || (bFlag && !cFlag && BitMap::first) + || (cFlag && !bWroteCondCheck && gFlag && !specMap->empty()) + || (fFlag && !bWroteGetState && gFlag) + ) + { + bPrologBrace = true; + o << indent(ind++) << "{\n"; + } + else if (ind == 0) + { + ind = 1; + } + + if (!fFlag && !DFlag) + { + if (bEmitYYCh) + { + o << indent(ind) << mapCodeName["YYCTYPE"] << " " << mapCodeName["yych"] << ";\n"; + } + o.insert_yyaccept_init (ind); + } + else + { + o << "\n"; + } + } + if (bFlag && !cFlag && BitMap::first) + { + BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256); + } + if (bProlog) + { + genCondTable(o, ind, *specMap); + o.insert_state_goto (ind, prolog_label); + if (cFlag && !DFlag) + { + if (vUsedLabels.count(prolog_label)) + { + o << labelPrefix << prolog_label << ":\n"; + } + if (!startLabelName.empty()) + { + o << startLabelName << ":\n"; + } + } + genCondGoto(o, ind, *specMap); + } + + if (cFlag && !condName.empty()) + { + if (condDivider.length()) + { + o << replaceParam(condDivider, condDividerParam, condName) << "\n"; + } + + if (DFlag) + { + o << condName << " -> " << (start_label+1) << "\n"; + } + else + { + o << condPrefix << condName << ":\n"; + } + } + if (cFlag && bFlag && BitMap::first) + { + o << indent(ind++) << "{\n"; + BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256); + } + + // The start_label is not always the first to be emitted, so we may have to jump. c.f. Initial::emit() + if (vUsedLabels.count(start_label+1)) + { + vUsedLabels.insert(start_label); + o << indent(ind) << "goto " << labelPrefix << start_label << ";\n"; + } + + // Generate code + for (s = head; s; s = s->next) + { + bool readCh = false; + s->emit(output, ind, readCh, condName); + s->go.emit(o, ind, readCh); + } + + if (cFlag && bFlag && BitMap::first) + { + o << indent(--ind) << "}\n"; + } + // Generate epilog + if ((!cFlag || isLastCond) && bPrologBrace) + { + o << indent(--ind) << "}\n"; + } + if (flag_skeleton) + { + skeleton::emit_epilog (o, ind); + } + + // Cleanup + if (BitMap::first) + { + delete BitMap::first; + BitMap::first = NULL; + } + + bUseStartLabel = false; +} + +void genCondTable(OutputFile & o, uint32_t ind, const RegExpMap& specMap) +{ + if (cFlag && !bWroteCondCheck && gFlag && specMap.size()) + { + RegExpIndices vCondList(specMap.size()); + + for(RegExpMap::const_iterator itSpec = specMap.begin(); itSpec != specMap.end(); ++itSpec) + { + vCondList[itSpec->second.first] = itSpec->first; + } + + o << indent(ind++) << "static void *" << mapCodeName["yyctable"] << "[" << specMap.size() << "] = {\n"; + + for(RegExpIndices::const_iterator it = vCondList.begin(); it != vCondList.end(); ++it) + { + o << indent(ind) << "&&" << condPrefix << *it << ",\n"; + } + o << indent(--ind) << "};\n"; + } +} + +void genCondGotoSub(OutputFile & o, uint32_t ind, RegExpIndices& vCondList, uint32_t cMin, uint32_t cMax) +{ + if (cMin == cMax) + { + o << indent(ind) << "goto " << condPrefix << vCondList[cMin] << ";\n"; + } + else + { + uint32_t cMid = cMin + ((cMax - cMin + 1) / 2); + + o << indent(ind) << "if (" << genGetCondition() << " < " << cMid << ") {\n"; + genCondGotoSub(o, ind + 1, vCondList, cMin, cMid - 1); + o << indent(ind) << "} else {\n"; + genCondGotoSub(o, ind + 1, vCondList, cMid, cMax); + o << indent(ind) << "}\n"; + } +} + +void genCondGoto(OutputFile & o, uint32_t ind, const RegExpMap& specMap) +{ + if (cFlag && !bWroteCondCheck && specMap.size()) + { + if (gFlag) + { + o << indent(ind) << "goto *" << mapCodeName["yyctable"] << "[" << genGetCondition() << "];\n"; + } + else + { + if (sFlag) + { + RegExpIndices vCondList(specMap.size()); + + for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it) + { + vCondList[it->second.first] = it->first; + } + genCondGotoSub(o, ind, vCondList, 0, vCondList.size() - 1); + } + else if (DFlag) + { + for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it) + { + o << "0 -> " << it->first << " [label=\"state=" << it->first << "\"]\n"; + } + } + else + { + o << indent(ind) << "switch (" << genGetCondition() << ") {\n"; + + for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it) + { + o << indent(ind) << "case " << condEnumPrefix << it->first << ": goto " << condPrefix << it->first << ";\n"; + } + o << indent(ind) << "}\n"; + } + } + bWroteCondCheck = true; + } +} + +void genTypes(Output & output, const RegExpMap& specMap) +{ + output.types.resize (specMap.size()); + for(RegExpMap::const_iterator itSpecMap = specMap.begin(); itSpecMap != specMap.end(); ++itSpecMap) + { + // If an entry is < 0 then we did the 0/empty correction twice. + assert(itSpecMap->second.first >= 0); + output.types[itSpecMap->second.first] = itSpecMap->first; + } +} + +} // end namespace re2c diff --git a/re2c/src/codegen/dfa_prepare.cc b/re2c/src/codegen/prepare_dfa.cc similarity index 91% rename from re2c/src/codegen/dfa_prepare.cc rename to re2c/src/codegen/prepare_dfa.cc index 7ed9b4d2..0e4ff54a 100644 --- a/re2c/src/codegen/dfa_prepare.cc +++ b/re2c/src/codegen/prepare_dfa.cc @@ -32,8 +32,8 @@ void DFA::findSCCs() void DFA::split(State *s) { State *move = new State; - (void) new Move(move); addState(&s->next, move); + move->action.set_move (); move->link = s->link; move->rule = s->rule; move->go = s->go; @@ -193,16 +193,13 @@ void DFA::prepare(uint32_t & max_fill) { if (s->go.span[i].to && !s->go.span[i].to->rule) { - delete s->action; - s->action = NULL; - if (saves[s->rule->accept] == ~0u) { saves[s->rule->accept] = nSaves++; } bSaveOnHead |= s == head; - (void) new Save(s, saves[s->rule->accept]); // sets s->action + s->action.set_save (saves[s->rule->accept]); } } } @@ -214,7 +211,7 @@ void DFA::prepare(uint32_t & max_fill) memset(rules, 0, (nRules)*sizeof(*rules)); State *accept = NULL; - Accept *accfixup = NULL; + State *accfixup = NULL; for (s = head; s; s = s->next) { @@ -229,7 +226,7 @@ void DFA::prepare(uint32_t & max_fill) if (!rules[s->rule->accept]) { State *n = new State; - (void) new Rule(n, s->rule); + n->action.set_rule (s->rule); rules[s->rule->accept] = n; addState(&s->next, n); } @@ -243,8 +240,7 @@ void DFA::prepare(uint32_t & max_fill) { if (!ow) { - ow = accept = new State; - accfixup = new Accept(accept, nRules, saves, rules); + ow = accept = accfixup = new State; addState(&s->next, accept); } @@ -255,7 +251,7 @@ void DFA::prepare(uint32_t & max_fill) if (accfixup) { - accfixup->genRuleMap(); + accfixup->action.set_accept (nRules, saves, rules); } // split ``base'' states into two parts @@ -287,9 +283,6 @@ void DFA::prepare(uint32_t & max_fill) // find ``base'' state, if possible findBaseState(); - delete head->action; - head->action = NULL; - for (s = head; s; s = s->next) { s->go.init (s); diff --git a/re2c/src/dfa/action.h b/re2c/src/dfa/action.h index b972f10e..9271918b 100644 --- a/re2c/src/dfa/action.h +++ b/re2c/src/dfa/action.h @@ -2,20 +2,35 @@ #define __ACTION__ #include +#include -#include "src/dfa/state.h" -#include "src/util/forbid_copy.h" +#include "src/util/c99_stdint.h" namespace re2c { +struct OutputFile; +class RuleOp; +class State; + +struct Initial +{ + uint32_t label; + bool setMarker; + + inline Initial (uint32_t l, bool b) + : label (l) + , setMarker (b) + {} +}; + +typedef std::map accept_t; + class Action { public: - State * state; enum type_t { - NONE, MATCH, INITIAL, SAVE, @@ -24,118 +39,80 @@ public: RULE } type; - explicit inline Action (State * s) - : state (s) - , type (NONE) +private: + union { - delete s->action; - s->action = this; - } - virtual ~Action () {} - inline bool readAhead () const - { - return (type != MATCH) - || (state && state->next - && state->next->action - && (state->next->action->type != RULE)); - } - virtual void emit (Output &, uint32_t, bool &, const std::string &) const = 0; + Initial * initial; + uint32_t save; + accept_t * accept; + const RuleOp * rule; + } info; - FORBID_COPY (Action); -}; - -class Match: public Action -{ public: - explicit inline Match (State * s) - : Action (s) + inline Action () + : type (MATCH) + , info () + {} + ~Action () { - type = MATCH; + clear (); } - void emit (Output &, uint32_t, bool &, const std::string &) const; -}; - -class Initial: public Action -{ -public: - uint32_t label; - bool setMarker; - - inline Initial (State * s, uint32_t l, bool b) - : Action (s) - , label (l) - , setMarker (b) + void set_initial (uint32_t label, bool used_marker) { + clear (); type = INITIAL; + info.initial = new Initial (label, used_marker); } - void emit (Output &, uint32_t, bool &, const std::string &) const; -}; - -class Save: public Match -{ -public: - uint32_t selector; - - inline Save (State * s, uint32_t i) - : Match (s) - , selector (i) + void set_save (uint32_t save) { + clear (); type = SAVE; + info.save = save; } - void emit (Output &, uint32_t, bool &, const std::string &) const; -}; - -class Move: public Action -{ -public: - explicit inline Move (State * s) - : Action (s) + void set_move () { + clear (); type = MOVE; } - void emit (Output &, uint32_t, bool &, const std::string &) const; -}; - -class Accept: public Action -{ -public: - typedef std::map RuleMap; - - uint32_t nRules; - uint32_t * saves; - State ** rules; - RuleMap mapRules; - - inline Accept (State * x, uint32_t n, uint32_t * s, State ** r) - : Action (x) - , nRules (n) - , saves (s) - , rules (r) - , mapRules () + void set_accept (uint32_t rules_count, uint32_t * saves, State * const * rules) { + clear (); type = ACCEPT; + info.accept = new accept_t (); + for (uint32_t i = 0; i < rules_count; ++i) + { + if (saves[i] != ~0u) + { + (* info.accept)[saves[i]] = rules[i]; + } + } } - void emit (Output &, uint32_t, bool &, const std::string &) const; - void emitBinary (OutputFile & o, uint32_t ind, uint32_t l, uint32_t r, bool & readCh) const; - void genRuleMap (); - - FORBID_COPY (Accept); -}; - -class Rule: public Action -{ -public: - RuleOp * rule; - - inline Rule (State * s, RuleOp * r) - : Action(s) - , rule(r) + void set_rule (const RuleOp * const rule) { + clear (); type = RULE; + info.rule = rule; } - void emit (Output &, uint32_t, bool &, const std::string &) const; + friend void emit_action (const Action & action, OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const std::string & condName); - FORBID_COPY (Rule); +private: + void clear () + { + switch (type) + { + case INITIAL: + delete info.initial; + break; + case ACCEPT: + delete info.accept; + break; + case MATCH: + case SAVE: + case MOVE: + case RULE: + break; + } + } }; } // namespace re2c diff --git a/re2c/src/dfa/dfa.cc b/re2c/src/dfa/dfa.cc index 35e7ac94..91778ff8 100644 --- a/re2c/src/dfa/dfa.cc +++ b/re2c/src/dfa/dfa.cc @@ -121,9 +121,6 @@ DFA::DFA(Ins *ins, uint32_t ni, uint32_t lb, uint32_t ub, const Char *rep) s->go.span = allocate (s->go.nSpans); memcpy((char*) s->go.span, (char*) span, s->go.nSpans*sizeof(Span)); - - (void) new Match(s); - } delete [] work; diff --git a/re2c/src/dfa/state.cc b/re2c/src/dfa/state.cc index 0d2e0f09..3f463f63 100644 --- a/re2c/src/dfa/state.cc +++ b/re2c/src/dfa/state.cc @@ -1,4 +1,3 @@ -#include "src/dfa/action.h" #include "src/dfa/state.h" namespace re2c @@ -15,12 +14,11 @@ State::State () , isPreCtxt (false) , isBase (false) , go () - , action (NULL) + , action () {} State::~State () { - delete action; delete [] kernel; operator delete (go.span); } diff --git a/re2c/src/dfa/state.h b/re2c/src/dfa/state.h index bb1a70e7..b9d06a38 100644 --- a/re2c/src/dfa/state.h +++ b/re2c/src/dfa/state.h @@ -2,14 +2,13 @@ #define __STATE__ #include "src/codegen/go.h" +#include "src/dfa/action.h" #include "src/dfa/re.h" #include "src/util/forbid_copy.h" namespace re2c { -class Action; - class State { public: @@ -24,7 +23,7 @@ public: bool isPreCtxt; bool isBase; Go go; - Action * action; + Action action; State (); ~State (); diff --git a/re2c/src/parse/parser.ypp b/re2c/src/parse/parser.ypp index 4c0eaf80..08f4f9af 100644 --- a/re2c/src/parse/parser.ypp +++ b/re2c/src/parse/parser.ypp @@ -11,7 +11,7 @@ #include "config.h" #include "src/dfa/dfa.h" -#include "src/codegen/dfa_emit.h" // genTypes +#include "src/codegen/emit.h" // genTypes #include "src/globals.h" #include "src/parse/parser.h" #include "src/util/c99_stdint.h" -- 2.40.0