DFA::DFA
( const dfa_t &dfa
, const std::vector<size_t> &fill
- , const std::vector<size_t> &fallback
, Skeleton *skel
, const charset_t &charset
, const std::string &n
s->rule = t->rule;
s->rule_tags = t->rule_tags;
s->fill = fill[i];
+ s->fallback = fallback_state(dfa, i); // see note [fallback states]
+
s->go.span = allocate<Span>(nchars);
uint32_t j = 0;
for (uint32_t c = 0; c < nchars; ++j)
}
*p = NULL;
- for (size_t i = 0; i < fallback.size(); ++i) {
- i2s[fallback[i]]->fallback = true;
- }
-
delete[] i2s;
}
DFA ( const dfa_t &dfa
, const std::vector<size_t> &fill
- , const std::vector<size_t> &fallback
, Skeleton *skel
, const charset_t &charset
, const std::string &n
// but prior to any other DFA transformations
Skeleton *skeleton = new Skeleton(dfa, cs, defrule, name, cond, line);
+ // try to minimize the number of tag variables
+ const size_t used_tags = deduplicate_tags(dfa);
+
minimization(dfa);
// find YYFILL states and calculate argument to YYFILL
std::vector<size_t> fill;
fillpoints(dfa, fill);
- // see note [fallback states]
- std::vector<size_t> fallback;
- fallback_states(dfa, fallback);
-
- // try to minimize the number of tag variables
- const size_t used_tags = deduplicate_tags(dfa, fallback);
-
// ADFA stands for 'DFA with actions'
- DFA *adfa = new DFA(dfa, fill, fallback, skeleton, cs,
+ DFA *adfa = new DFA(dfa, fill, skeleton, cs,
name, cond, line, used_tags);
// see note [reordering DFA states]
void minimization(dfa_t &dfa);
void fillpoints(const dfa_t &dfa, std::vector<size_t> &fill);
-void fallback_states(const dfa_t &dfa, std::vector<size_t> &fallback);
-size_t deduplicate_tags(dfa_t &dfa, const std::vector<size_t> &fallback);
+bool fallback_state(const dfa_t &dfa, size_t i);
+size_t deduplicate_tags(dfa_t &dfa);
} // namespace re2c
/* note [fallback states]
*
- * Find accepting states that may be shadowed by other accepting
- * states: when the short rule matches, lexer must try to match
- * longer rules; if this attempt is unsuccessful it must fallback
- * to the short match.
+ * Check if the given state is accepting, but may be shadowed
+ * by other accepting states: when the short rule matches,
+ * lexer must try to match longer rules; if this attempt is
+ * unsuccessful it must fallback to the short match.
*/
-void fallback_states(const dfa_t &dfa, std::vector<size_t> &fallback)
+bool fallback_state(const dfa_t &dfa, size_t i)
{
- const size_t count = dfa.states.size();
- for (size_t i = 0; i < count; ++i) {
- dfa_state_t *s = dfa.states[i];
- if (s->rule != Rule::NONE) {
- for (size_t c = 0; c < dfa.nchars; ++c) {
- const size_t j = s->arcs[c];
- if (j != dfa_t::NIL
- && dfa.states[j]->rule == Rule::NONE) {
- fallback.push_back(i);
- break;
- }
- }
+ dfa_state_t *s = dfa.states[i];
+
+ if (s->rule == Rule::NONE) {
+ return false;
+ }
+
+ for (size_t c = 0; c < dfa.nchars; ++c) {
+ const size_t j = s->arcs[c];
+ if (j != dfa_t::NIL
+ && dfa.states[j]->rule == Rule::NONE) {
+ return true;
}
}
+
+ return false;
}
} // namespace re2c
}
}
-size_t deduplicate_tags(dfa_t &dfa,
- const std::vector<size_t> &fallback)
+// see note [fallback states]
+// fallback tags are all tags that belong to fallback rules
+static size_t fallback_tags(const dfa_t &dfa)
+{
+ const size_t nstates = dfa.states.size();
+ size_t tags = 0;
+ for (size_t i = 0; i < nstates; ++i) {
+ if (fallback_state(dfa, i)) {
+ const size_t r = dfa.states[i]->rule;
+ tags = dfa.tagpool.orl(tags, dfa.rules[r].tags);
+ }
+ }
+ return tags;
+}
+
+size_t deduplicate_tags(dfa_t &dfa)
{
const size_t ntags = dfa.tags.size();
if (ntags == 0) {
return 0;
}
- size_t fbtags = 0;
- for (size_t i = 0; i < fallback.size(); ++i) {
- const size_t r = dfa.states[fallback[i]]->rule;
- fbtags = dfa.tagpool.orl(fbtags, dfa.rules[r].tags);
- }
+ const size_t fallback = fallback_tags(dfa);
const size_t nstates = dfa.states.size();
size_t *live = new size_t[nstates]();
- calc_live(dfa, fbtags, live);
+ calc_live(dfa, fallback, live);
mask_dead(dfa, live);
bool *incompattbl = new bool[ntags * ntags]();
- incompatibility_table(dfa, live, fbtags, incompattbl);
+ incompatibility_table(dfa, live, fallback, incompattbl);
size_t *represent = new size_t[ntags]();
equivalence_classes(incompattbl, ntags, represent);
{
YYCTYPE yych;
- if (YYLESSTHAN (3)) YYFILL(3);
+ if (YYLESSTHAN (2)) YYFILL(2);
yych = YYPEEK ();
switch (yych) {
case 'a': goto yy4;
{}
yy4:
YYSKIP ();
- switch ((yych = YYPEEK ())) {
- case 'a': goto yy10;
- default: goto yy8;
- }
+ yych = YYPEEK ();
+ goto yy8;
YYRESTORECTX ();
{}
yy6:
if (YYLESSTHAN (1)) YYFILL(1);
yych = YYPEEK ();
goto yy8;
-yy10:
- YYSKIP ();
- yych = YYPEEK ();
- goto yy8;
}
re2c: warning: line 2: unreachable rule [-Wunreachable-rules]
{
YYCTYPE yych;
- if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
switch (yych) {
case 'a': goto yy4;
{}
yy4:
++YYCURSOR;
- switch ((yych = *YYCURSOR)) {
- case 'a': goto yy10;
- default: goto yy8;
- }
+ yych = *YYCURSOR;
+ goto yy8;
YYCURSOR = YYCTXMARKER;
{}
yy6:
if (YYLIMIT <= YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
goto yy8;
-yy10:
- ++YYCURSOR;
- yych = *YYCURSOR;
- goto yy8;
}
re2c: warning: line 2: unreachable rule [-Wunreachable-rules]