Replaced inheritance hierarchy with tagged union.
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 \
$(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 \
#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"
+++ /dev/null
-#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
+++ /dev/null
-#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__
--- /dev/null
+#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__
--- /dev/null
+#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
--- /dev/null
+#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
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;
{
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]);
}
}
}
memset(rules, 0, (nRules)*sizeof(*rules));
State *accept = NULL;
- Accept *accfixup = NULL;
+ State *accfixup = NULL;
for (s = head; s; s = s->next)
{
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);
}
{
if (!ow)
{
- ow = accept = new State;
- accfixup = new Accept(accept, nRules, saves, rules);
+ ow = accept = accfixup = new State;
addState(&s->next, accept);
}
if (accfixup)
{
- accfixup->genRuleMap();
+ accfixup->action.set_accept (nRules, saves, rules);
}
// split ``base'' states into two parts
// find ``base'' state, if possible
findBaseState();
- delete head->action;
- head->action = NULL;
-
for (s = head; s; s = s->next)
{
s->go.init (s);
#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,
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
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;
-#include "src/dfa/action.h"
#include "src/dfa/state.h"
namespace re2c
, isPreCtxt (false)
, isBase (false)
, go ()
- , action (NULL)
+ , action ()
{}
State::~State ()
{
- delete action;
delete [] kernel;
operator delete (go.span);
}
#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:
bool isPreCtxt;
bool isBase;
Go go;
- Action * action;
+ Action action;
State ();
~State ();
#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"