]> granicus.if.org Git - re2c/commitdiff
Simplified 're2c::Action' class and its usage.
authorUlya Trofimovich <skvadrik@gmail.com>
Tue, 19 May 2015 11:53:24 +0000 (12:53 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Tue, 19 May 2015 11:53:24 +0000 (12:53 +0100)
Replaced inheritance hierarchy with tagged union.

13 files changed:
re2c/Makefile.am
re2c/bootstrap/parser.cc
re2c/src/codegen/dfa_emit.cc [deleted file]
re2c/src/codegen/dfa_emit.h [deleted file]
re2c/src/codegen/emit.h [new file with mode: 0644]
re2c/src/codegen/emit_action.cc [new file with mode: 0644]
re2c/src/codegen/emit_dfa.cc [new file with mode: 0644]
re2c/src/codegen/prepare_dfa.cc [moved from re2c/src/codegen/dfa_prepare.cc with 91% similarity]
re2c/src/dfa/action.h
re2c/src/dfa/dfa.cc
re2c/src/dfa/state.cc
re2c/src/dfa/state.h
re2c/src/parse/parser.ypp

index a5bfd0a3beb4d6772b49adb9592509aa4d56cf00..8975d98812303d75bbecb1b4ce506b01ac5deaea 100644 (file)
@@ -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 \
index 3662c911cdfaaa23ddd0b120beb3ec8f1719ded5..08b94e03615cd6b34d0347c6e6336f3f9c70f5eb 100644 (file)
@@ -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 (file)
index 964e8da..0000000
+++ /dev/null
@@ -1,709 +0,0 @@
-#include <assert.h>
-
-#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 (file)
index e286cc9..0000000
+++ /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<std::string> 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<typename _Ty>
-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 (file)
index 0000000..164faad
--- /dev/null
@@ -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<std::string> 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<typename _Ty> 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 (file)
index 0000000..b203e57
--- /dev/null
@@ -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 (file)
index 0000000..da7f2a4
--- /dev/null
@@ -0,0 +1,341 @@
+#include <assert.h>
+
+#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
similarity index 91%
rename from re2c/src/codegen/dfa_prepare.cc
rename to re2c/src/codegen/prepare_dfa.cc
index 7ed9b4d20b11c8be6ceaacd26400fbb6e3ee2df2..0e4ff54a95fe644cfecfc88b693cbd772508f696 100644 (file)
@@ -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);
index b972f10e496bd53db400727350a8a46b3a486f58..9271918bb0bd9abfd87b9265de8f03871a24ad6b 100644 (file)
@@ -2,20 +2,35 @@
 #define __ACTION__
 
 #include <map>
+#include <string>
 
-#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<uint32_t, const State *> 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<uint32_t, State *> 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
index 35e7ac941ad61de6aa5ea0c0aa480634cb971a8b..91778ff826dfd7dee793f7de9d8ce90a5bf543ff 100644 (file)
@@ -121,9 +121,6 @@ DFA::DFA(Ins *ins, uint32_t ni, uint32_t lb, uint32_t ub, const Char *rep)
                s->go.span = allocate<Span> (s->go.nSpans);
 
                memcpy((char*) s->go.span, (char*) span, s->go.nSpans*sizeof(Span));
-
-               (void) new Match(s);
-
        }
 
        delete [] work;
index 0d2e0f09af977d06798b4e9708db3241a53d49c4..3f463f63f758a1b07346795060e7c736ca39ab48 100644 (file)
@@ -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);
 }
index bb1a70e71c7dcaf48636ab86bf9c4eb58676cf95..b9d06a3845bf7946866e462da403116f3e9d700b 100644 (file)
@@ -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 ();
index 4c0eaf803b57868704c2d0ecbb887a16b4bd68e5..08f4f9af6d646a229b6002d9e09156ce142b4e96 100644 (file)
@@ -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"