static void check_tags(const Tagpool &tagpool, size_t oldidx, size_t newidx, bool *badtags);
static bool compare_by_rule(const clos_t &c1, const clos_t &c2);
static void prune_final_items(closure_t &clos, std::valarray<Rule> &rules);
+static void merge_tags_with_mask(bool *oldtags, const bool *newtags, bool *oldmask, const bool *newmask, bool *badtags, size_t ntags);
-void closure(const closure_t &clos1, closure_t &clos2,
- Tagpool &tagpool, std::valarray<Rule> &rules,
- bool *tags, bool *badtags)
+size_t closure(const closure_t &clos1, closure_t &clos2,
+ Tagpool &tagpool, std::valarray<Rule> &rules, bool *badtags)
{
+ const size_t ntags = tagpool.ntags;
+ bool *buf1 = tagpool.buffer1,
+ *buf2 = tagpool.buffer2;
+
clos2.clear();
+ std::fill(buf1, buf1 + ntags, false);
for (cclositer_t c = clos1.begin(); c != clos1.end(); ++c) {
- closure_one(clos2, tagpool, c->state, tags, badtags);
+ closure_one(clos2, tagpool, c->state, buf1, badtags);
}
prune_final_items(clos2, rules);
// sort closure: we need this to compare closures by hash
std::sort(clos2.begin(), clos2.end(), compare_by_rule);
+
+ // merge tags from different rules
+ std::fill(buf1, buf1 + ntags, false);
+ std::fill(buf2, buf2 + ntags, false);
+ for (cclositer_t c = clos1.begin(); c != clos1.end(); ++c) {
+ merge_tags_with_mask(buf1, tagpool[c->tagidx], buf2,
+ tagpool[rules[c->state->rule].tags], badtags, ntags);
+ }
+ return tagpool.insert(buf1);
}
/* note [epsilon-closures in tagged NFA]
}
}
+void merge_tags_with_mask(bool *oldtags, const bool *newtags,
+ bool *oldmask, const bool *newmask,
+ bool *badtags, size_t ntags)
+{
+ for (size_t i = 0; i < ntags; ++i) {
+ const bool bad = oldmask[i] & newmask[i] & (oldtags[i] ^ newtags[i]);
+ // don't merge conflicting tags, only note the conflict
+ if (!bad) {
+ oldtags[i] |= newtags[i];
+ }
+ badtags[i] |= bad;
+ oldmask[i] |= newmask[i];
+ }
+}
+
} // namespace re2c
typedef closure_t::iterator clositer_t;
typedef closure_t::const_iterator cclositer_t;
-void closure(const closure_t &clos1, closure_t &clos2,
- Tagpool &tagpool, std::valarray<Rule> &rules,
- bool *tags, bool *badtags);
+size_t closure(const closure_t &clos1, closure_t &clos2,
+ Tagpool &tagpool, std::valarray<Rule> &rules, bool *badtags);
clos_t::clos_t()
: state(NULL)
static nfa_state_t *transition(nfa_state_t *state, uint32_t symbol);
static void reach(const closure_t &clos1, closure_t &clos2, uint32_t symbol);
+static void warn_bad_tags(const bool *badtags, const std::valarray<Tag> &tags,
+ const std::valarray<Rule> &rules, const std::string &cond);
const size_t dfa_t::NIL = std::numeric_limits<size_t>::max();
}
}
-static void merge_tags_with_mask(bool *oldtags, const bool *newtags,
- bool *oldmask, const bool *newmask,
- bool *badtags, size_t ntags)
-{
- for (size_t i = 0; i < ntags; ++i) {
- const bool bad = oldmask[i] & newmask[i] & (oldtags[i] ^ newtags[i]);
- // don't merge conflicting tags, only note the conflict
- if (!bad) {
- oldtags[i] |= newtags[i];
- }
- badtags[i] |= bad;
- oldmask[i] |= newmask[i];
- }
-}
-
dfa_t::dfa_t(const nfa_t &nfa,
const charset_t &charset,
const std::string &cond)
{
clospool_t clospool;
closure_t clos1, clos2;
- const size_t ntags = tags.size();
- bool *ktags = new bool[ntags]();
- bool *badtags = new bool[ntags]();
- bool *arctags = new bool[ntags];
- bool *mask = new bool[ntags];
+ bool *badtags = new bool[tags.size()]();
clos1.push_back(clos_t(nfa.root, ZERO_TAGS));
- closure(clos1, clos2, tagpool, rules, ktags, badtags);
+ closure(clos1, clos2, tagpool, rules, badtags);
find_state(clos2, clospool);
for (size_t i = 0; i < clospool.size(); ++i) {
for (size_t c = 0; c < nchars; ++c) {
reach(clos0, clos1, charset[c]);
- closure(clos1, clos2, tagpool, rules, ktags, badtags);
+ s->tags[c] = closure(clos1, clos2, tagpool, rules, badtags);
s->arcs[c] = find_state(clos2, clospool);
-
- memset(arctags, 0, ntags * sizeof(bool));
- memset(mask, 0, ntags * sizeof(bool));
- for (cclositer_t p = clos1.begin(); p != clos1.end(); ++p) {
- merge_tags_with_mask(arctags, tagpool[p->tagidx], mask,
- tagpool[rules[p->state->rule].tags], badtags, ntags);
- }
- s->tags[c] = tagpool.insert(arctags);
}
// see note [at most one final item per closure]
}
}
+ warn_bad_tags(badtags, tags, rules, cond);
+ delete[] badtags;
+}
+
+void warn_bad_tags(const bool *badtags,
+ const std::valarray<Tag> &tags,
+ const std::valarray<Rule> &rules,
+ const std::string &cond)
+{
+ const size_t ntags = tags.size();
for (size_t i = 0; i < ntags; ++i) {
if (badtags[i]) {
- warn.nondeterministic_tags(rules[tags[i].rule].info->loc.line,
- cond, tags[i].name);
+ const Tag &tag = tags[i];
+ const uint32_t line = rules[tag.rule].info->loc.line;
+ warn.nondeterministic_tags(line, cond, tag.name);
}
}
-
- delete[] ktags;
- delete[] badtags;
- delete[] arctags;
- delete[] mask;
}
dfa_t::~dfa_t()
{
Tagpool::Tagpool(size_t n)
- : ntags(n)
- , lookup()
- , buff(new bool[ntags]())
+ : lookup()
+ , buffer(new bool[n * 3])
+ , ntags(n)
+ , buffer1(&buffer[n * 1])
+ , buffer2(&buffer[n * 2])
{
// all-zero tag configuration must have static number zero
- assert(ZERO_TAGS == insert(buff));
+ std::fill(buffer, buffer + ntags, false);
+ assert(ZERO_TAGS == insert(buffer));
}
Tagpool::~Tagpool()
{
- delete[] buff;
+ delete[] buffer;
const size_t n = lookup.size();
for (size_t i = 0; i < n; ++i) {
free(const_cast<bool*>(lookup[i]));
const bool *tags = operator[](t);
const bool *ortags = operator[](o);
for (size_t i = 0; i < ntags; ++i) {
- buff[i] = tags[i] | ortags[i];
+ buffer[i] = tags[i] | ortags[i];
}
- return insert(buff);
+ return insert(buffer);
}
size_t Tagpool::andl(size_t t, size_t a)
const bool *tags = operator[](t);
const bool *andtags = operator[](a);
for (size_t i = 0; i < ntags; ++i) {
- buff[i] = tags[i] & andtags[i];
+ buffer[i] = tags[i] & andtags[i];
}
- return insert(buff);
+ return insert(buffer);
}
size_t Tagpool::andlinv(size_t t, size_t a)
const bool *tags = operator[](t);
const bool *andinvtags = operator[](a);
for (size_t i = 0; i < ntags; ++i) {
- buff[i] = tags[i] & ~andinvtags[i];
+ buffer[i] = tags[i] & ~andinvtags[i];
}
- return insert(buff);
+ return insert(buffer);
}
size_t Tagpool::subst(size_t t, const size_t *represent)
{
const bool *tags = operator[](t);
- memset(buff, 0, ntags * sizeof(bool));
+ memset(buffer, 0, ntags * sizeof(bool));
for (size_t i = 0; i < ntags; ++i) {
if (tags[i]) {
- buff[represent[i]] = true;
+ buffer[represent[i]] = true;
}
}
- return insert(buff);
+ return insert(buffer);
}
} // namespace re2c
struct Tagpool
{
- const size_t ntags;
-
private:
typedef lookup_t<const bool*> taglookup_t;
taglookup_t lookup;
- bool *buff;
+ bool *buffer;
public:
+ const size_t ntags;
+ bool *buffer1;
+ bool *buffer2;
+
explicit Tagpool(size_t n);
~Tagpool();
size_t insert(const bool *tags);