static void need(OutputFile &o, uint32_t ind, bool &readCh, size_t n, bool bSetMarker);
static void emit_match(OutputFile &o, uint32_t ind, bool &readCh, const State *s);
-static void emit_initial(OutputFile &o, uint32_t ind, bool &readCh, const State *s, const std::set<label_t> &used_labels);
+static void emit_initial(OutputFile &o, uint32_t ind, bool &readCh, const State *s, const std::set<label_t> &used_labels, bool save_yyaccept);
static void emit_save(OutputFile &o, uint32_t ind, bool &readCh, const State *s, bool save_yyaccept);
static void emit_accept_binary(OutputFile &o, uint32_t ind, bool &readCh, const DFA &dfa, const State *s, size_t l, size_t r);
static void emit_accept(OutputFile &o, uint32_t ind, bool &readCh, const DFA &dfa, const State *s);
void emit_action(OutputFile &o, uint32_t ind, bool &readCh,
const DFA &dfa, const State *s, const std::set<label_t> &used_labels)
{
+ const bool save_yyaccept = dfa.accepts.size() > 1;
switch (s->action.type) {
case Action::MATCH:
emit_match(o, ind, readCh, s);
break;
case Action::INITIAL:
- emit_initial(o, ind, readCh, s, used_labels);
+ emit_initial(o, ind, readCh, s, used_labels, save_yyaccept);
break;
case Action::SAVE:
- emit_save(o, ind, readCh, s, dfa.accepts.size() > 1);
+ emit_save(o, ind, readCh, s, save_yyaccept);
break;
case Action::MOVE:
break;
}
void emit_initial(OutputFile &o, uint32_t ind, bool &readCh,
- const State *s, const std::set<label_t> &used_labels)
+ const State *s, const std::set<label_t> &used_labels, bool save_yyaccept)
{
+ const Initial &initial = *s->action.info.initial;
+
if (used_labels.count(s->label)) {
+ const size_t save = initial.save;
+ if (save_yyaccept && save != Initial::NOSAVE) {
+ o.wind(ind).wstring(opts->yyaccept).ws(" = ")
+ .wu64(save).ws(";\n");
+ }
+
if (s->fill != 0) {
o.wstring(opts->input_api.stmt_skip(ind));
} else {
}
}
- const Initial &initial = *s->action.info.initial;
if (used_labels.count(initial.label)) {
o.wstring(opts->labelPrefix).wlabel(initial.label).ws(":\n");
}
#ifndef _RE2C_IR_ADFA_ACTION_
#define _RE2C_IR_ADFA_ACTION_
+#include <assert.h>
#include <vector>
#include "src/codegen/label.h"
struct Initial
{
+ static const size_t NOSAVE;
+
label_t label;
bool setMarker;
+ size_t save;
- inline Initial (label_t l, bool b)
+ inline Initial (label_t l, bool b, size_t s)
: label (l)
, setMarker (b)
+ , save (s)
{}
};
{}
~Action ()
{
- clear ();
+ if (type == INITIAL) {
+ delete info.initial;
+ }
}
void set_initial (label_t label, bool used_marker)
{
- clear ();
- type = INITIAL;
- info.initial = new Initial (label, used_marker);
+ if (type == MATCH) {
+ // ordinary state with no special action
+ type = INITIAL;
+ info.initial = new Initial(label, used_marker, Initial::NOSAVE);
+ } else if (type == SAVE) {
+ // fallback state: do not loose 'yyaccept'
+ type = INITIAL;
+ info.initial = new Initial(label, used_marker, info.save);
+ } else if (type == INITIAL) {
+ // already marked as initial, probably reuse mode
+ info.initial->label = label;
+ info.initial->setMarker = used_marker;
+ } else {
+ assert(false);
+ }
}
void set_save (size_t save)
{
- clear ();
+ assert(type == MATCH);
type = SAVE;
info.save = save;
}
void set_move ()
{
- clear ();
+ assert(type == MATCH);
type = MOVE;
}
void set_accept (const accept_t * accepts)
{
- clear ();
+ assert(type == MATCH);
type = ACCEPT;
info.accepts = accepts;
}
void set_rule (size_t rule)
{
- clear ();
+ assert(type == MATCH);
type = RULE;
info.rule = rule;
}
-
-private:
- void clear ()
- {
- switch (type)
- {
- case INITIAL:
- delete info.initial;
- break;
- case MATCH:
- case SAVE:
- case MOVE:
- case ACCEPT:
- case RULE:
- break;
- }
- }
};
} // namespace re2c
--- /dev/null
+/* Generated by re2c */
+// In this example initial state coincides with fallback state
+// which must update 'yyaccept'. There is a loop through initial
+// state that changes 'yyaccept' value, so if the initial state
+// forgets to update 'yyaccept', the wrong rule will match.
+
+
+{
+ YYCTYPE yych;
+ unsigned int yyaccept = 0;
+ goto yy0;
+yy1:
+ yyaccept = 0;
+ ++YYCURSOR;
+yy0:
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *(YYMARKER = YYCURSOR);
+ switch (yych) {
+ case 'a': goto yy3;
+ default: goto yy2;
+ }
+yy2:
+ { 1 }
+yy3:
+ ++YYCURSOR;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ switch (yych) {
+ case 'b': goto yy5;
+ default: goto yy4;
+ }
+yy4:
+ YYCURSOR = YYMARKER;
+ if (yyaccept == 0) {
+ goto yy2;
+ } else {
+ goto yy6;
+ }
+yy5:
+ yyaccept = 1;
+ YYMARKER = ++YYCURSOR;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ switch (yych) {
+ case 'a': goto yy7;
+ default: goto yy6;
+ }
+yy6:
+ { 2 }
+yy7:
+ ++YYCURSOR;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ switch (yych) {
+ case 'b': goto yy1;
+ default: goto yy4;
+ }
+}
+
+re2c: warning: line 8: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 9: rule matches empty string [-Wmatch-empty-string]