, const std::string &n
, const std::string &c
, uint32_t l
- , bool base_ctx
+ , size_t used_tags
)
: accepts ()
, skeleton (skel)
// statistics
, max_fill (0)
, need_backup (false)
- , need_backupctx (opts->contexts)
+
+ // determine if 'YYCTXMARKER' or 'YYBACKUPCTX'/'YYRESTORECTX' pair is used
+ , need_backupctx (used_tags > 0 || opts->contexts)
, need_accept (false)
- , base_ctxmarker (base_ctx)
+
+ // Non-trailing contexts imply the existence of base context marker
+ // that points at the beginning of lexeme. First, it is a feature
+ // of re2c API. Second, it simplifies implementation (otherwise
+ // it would be hard to mix generic API and fixed-length contexts).
+ //
+ // The only case without base context marker is when:
+ // - only trailing contexts are allowed
+ // - they don't overlap (one marker is enough for all of them)
+ // - with generic API fixed-length contexts are forbidden
+ // Note that in this case, if generic API is used, fixed-length
+ // contexts are forbidden (which may cause additional overlaps).
+ , base_ctxmarker (used_tags > 1 || opts->contexts)
{
const size_t nstates = dfa.states.size();
const size_t nchars = dfa.nchars;
, const std::string &n
, const std::string &c
, uint32_t l
- , bool base_ctx
+ , size_t used_tags
);
~DFA ();
void reorder();
// determine if 'YYMARKER' or 'YYBACKUP'/'YYRESTORE' pair is used
need_backup = accepts.size () > 0;
- // determine if 'YYCTXMARKER' or 'YYBACKUPCTX'/'YYRESTORECTX' pair is used
- for (State * s = head; s; s = s->next) {
- if (!s->ctxs.empty()) {
- need_backupctx = true;
- break;
- }
- }
-
// determine if 'yyaccept' variable is used
need_accept = accepts.size () > 1;
}
std::vector<size_t> fallback;
fallback_states(dfa, fallback);
- // Non-trailing contexts imply the existence of base context marker
- // that points at the beginning of lexeme. First, it is a feature
- // of re2c API. Second, it simplifies implementation (otherwise
- // it would be hard to mix generic API and fixed-length contexts).
- //
- // The only case without base context marker is when:
- // - only trailing contexts are allowed
- // - they don't overlap (one marker is enough for all of them)
- // - with generic API fixed-length contexts are forbidden
- // Note that in this case, if generic API is used, fixed-length
- // contexts are forbidden (which may cause additional overlaps).
- const bool multiple_ctxmarkers = deduplicate_contexts(dfa, fallback);
- const bool base_ctxmarker
- = multiple_ctxmarkers
- || opts->contexts;
+ // try to minimize the number of tag variables
+ const size_t used_tags = deduplicate_contexts(dfa, fallback);
// ADFA stands for 'DFA with actions'
DFA *adfa = new DFA(dfa, fill, fallback, skeleton, cs,
- name, cond, line, base_ctxmarker);
+ name, cond, line, used_tags);
// see note [reordering DFA states]
adfa->reorder();
}
}
-bool deduplicate_contexts(
- const dfa_t &dfa,
+size_t deduplicate_contexts(dfa_t &dfa,
const std::vector<size_t> &fallback)
{
const size_t nctxs = dfa.contexts.size();
if (nctxs < 2) {
- return false;
+ return nctxs;
}
std::set<size_t> fbctxs;
head[0] = c;
}
}
- const bool multiple_contexts = head[0] != END;
-
-/*
- std::vector<size_t> c2c;
- std::vector<std::vector<size_t> > part;
+ size_t ncontexts = 0;
for (size_t i = 0; i < nctxs; ++i) {
- size_t j;
- for (j = 0; j < partn.size(); ++j) {
- std::vector<size_t> &p = part[j];
- size_t k;
- for (k = 0; k < p.size(); ++k) {
- if (xxx[i * nctxs + p[k]]) {
- break;
- }
- }
- if (k == p.size()) {
- break;
- }
+ if (part[i] == i) {
+ ++ncontexts;
}
- if (j == part.size()) {
- part.push_back(std::vector<size_t>());
- }
- part[j].push_back(i);
- c2c[i] = part[j][0];
}
-*/
+
for (size_t i = 0; i < nstates; ++i) {
dfa_state_t *s = dfa.states[i];
std::set<size_t> ctxs;
dfa.contexts[i].uniqname = dfa.contexts[part[i]].uniqname;
}
- return multiple_contexts;
+ return ncontexts;
}
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);
-bool deduplicate_contexts(const dfa_t &dfa, const std::vector<size_t> &fallback);
+size_t deduplicate_contexts(dfa_t &dfa, const std::vector<size_t> &fallback);
} // namespace re2c