namespace re2c
{
-BitMap *BitMap::first = NULL;
-
-BitMap::BitMap(const Go *g, const State *x)
- : go(g)
- , on(x)
- , next(first)
- , i(0)
- , m(0)
+static bool matches(const Go *go1, const State *s1, const Go *go2, const State *s2);
+static void doGen(const Go *g, const State *s, uint32_t *bm, uint32_t f, uint32_t m);
+
+bitmaps_t::bitmaps_t(uint32_t n)
+ : maps()
+ , ncunit(n)
+ , buffer(new uint32_t[ncunit])
+ , used(false)
+{}
+
+bitmaps_t::~bitmaps_t()
{
- first = this;
+ delete[] buffer;
}
-BitMap::~BitMap()
+void bitmaps_t::insert(const Go *go, const State *s)
{
- delete next;
+ for (rciter_t i = maps.rbegin(); i != maps.rend(); ++i) {
+ if (matches(i->go, i->on, go, s)) return;
+ }
+
+ bitmap_t b = {go, s, 0, 0};
+ maps.push_back(b);
}
-const BitMap *BitMap::find(const Go *g, const State *x)
+const bitmap_t *bitmaps_t::find(const Go *go, const State *s) const
{
- for (const BitMap *b = first; b; b = b->next)
- {
- if (matches(b->go->span, b->go->nSpans, b->on, g->span, g->nSpans, x))
- {
- return b;
- }
+ for (rciter_t i = maps.rbegin(); i != maps.rend(); ++i) {
+ if (i->on == s && matches(i->go, i->on, go, s)) return &(*i);
}
-
- return new BitMap(g, x);
+ return NULL;
}
-const BitMap *BitMap::find(const State *x)
+bool bitmaps_t::empty() const { return maps.empty(); }
+
+void bitmaps_t::gen(OutputFile &o, uint32_t ind)
{
- for (const BitMap *b = first; b; b = b->next)
- {
- if (b->on == x)
- {
- return b;
+ if (empty() || !used) return;
+
+ Opt &opts = o.opts;
+ const uint32_t nmap = static_cast<uint32_t>(maps.size());
+ riter_t b = maps.rbegin(), e = maps.rend();
+
+ o.wind(ind).ws("static const unsigned char ")
+ .wstring(opts->yybm).ws("[] = {");
+
+ for (uint32_t i = 0, t = 1; b != e; i += ncunit, t += 8) {
+ memset(buffer, 0, ncunit * sizeof(uint32_t));
+
+ for (uint32_t m = 0x80; b != e && m; m >>= 1, ++b) {
+ b->i = i;
+ b->m = m;
+ doGen(b->go, b->on, buffer, 0, m);
+ }
+
+ if (nmap > 8) {
+ o.ws("\n").wind(ind + 1).ws("/* table ").wu32(t).ws(" .. ")
+ .wu32(std::min(nmap, t + 7)).ws(": ").wu32(i).ws(" */");
+ }
+
+ for (uint32_t c = 0; c < ncunit; ++c) {
+ if (c % 8 == 0) {
+ o.ws("\n").wind(ind + 1);
+ }
+ if (opts->yybmHexTable) {
+ o.wu32_hex(buffer[c]);
+ } else {
+ o.wu32_width(buffer[c], 3);
+ }
+ o.ws(", ");
}
}
- return NULL;
+ o.ws("\n").wind(ind).ws("};\n");
}
-static void doGen(const Go *g, const State *s, uint32_t *bm, uint32_t f, uint32_t m)
+void doGen(const Go *g, const State *s, uint32_t *bm, uint32_t f, uint32_t m)
{
Span *b = g->span, *e = &b[g->nSpans];
uint32_t lb = 0;
}
}
-void BitMap::gen(OutputFile & o, uint32_t ind, uint32_t lb, uint32_t ub)
-{
- Opt &opts = o.opts;
- if (first && bUsedYYBitmap)
- {
- o.wind(ind).ws("static const unsigned char ").wstring(opts->yybm).ws("[] = {");
-
- uint32_t c = 1, n = ub - lb;
- const BitMap *cb = first;
-
- while((cb = cb->next) != NULL) {
- ++c;
- }
- BitMap *b = first;
-
- uint32_t *bm = new uint32_t[n];
-
- for (uint32_t i = 0, t = 1; b; i += n, t += 8)
- {
- memset(bm, 0, n * sizeof(uint32_t));
-
- for (uint32_t m = 0x80; b && m; m >>= 1)
- {
- b->i = i;
- b->m = m;
- doGen(b->go, b->on, bm, lb, m);
- b = const_cast<BitMap*>(b->next);
- }
-
- if (c > 8)
- {
- o.ws("\n").wind(ind+1).ws("/* table ").wu32(t).ws(" .. ").wu32(std::min(c, t+7)).ws(": ").wu32(i).ws(" */");
- }
-
- for (uint32_t j = 0; j < n; ++j)
- {
- if (j % 8 == 0)
- {
- o.ws("\n").wind(ind+1);
- }
-
- if (opts->yybmHexTable)
- {
- o.wu32_hex(bm[j]);
- }
- else
- {
- o.wu32_width(bm[j], 3);
- }
- o.ws(", ");
- }
- }
-
- o.ws("\n").wind(ind).ws("};\n");
-
- delete[] bm;
- }
-}
-
// All spans in b1 that lead to s1 are pairwise equal to that in b2 leading to s2
-bool matches(const Span * b1, uint32_t n1, const State * s1, const Span * b2, uint32_t n2, const State * s2)
+bool matches(const Go *go1, const State *s1, const Go *go2, const State *s2)
{
- const Span * e1 = &b1[n1];
- uint32_t lb1 = 0;
- const Span * e2 = &b2[n2];
- uint32_t lb2 = 0;
+ const Span
+ *b1 = go1->span, *e1 = &b1[go1->nSpans],
+ *b2 = go2->span, *e2 = &b2[go2->nSpans];
+ uint32_t lb1 = 0, lb2 = 0;
for (;;)
{
#define _RE2C_CODEGEN_BITMAP_
#include "src/util/c99_stdint.h"
+#include <vector>
#include "src/util/forbid_copy.h"
-namespace re2c
-{
+namespace re2c {
struct Go;
struct Span;
class State;
class OutputFile;
-class BitMap
+struct bitmap_t
{
-public:
- static BitMap *first;
+ const Go *go;
+ const State *on;
+ uint32_t i;
+ uint32_t m;
+};
+
+class bitmaps_t
+{
+ typedef std::vector<bitmap_t> maps_t;
+ typedef maps_t::reverse_iterator riter_t;
+ typedef maps_t::const_reverse_iterator rciter_t;
- const Go *go;
- const State *on;
- const BitMap *next;
- uint32_t i;
- uint32_t m;
+ maps_t maps;
+ uint32_t ncunit;
+ uint32_t *buffer;
public:
- static const BitMap *find(const Go*, const State*);
- static const BitMap *find(const State*);
- static void gen(OutputFile &, uint32_t ind, uint32_t, uint32_t);
- BitMap(const Go*, const State*);
- ~BitMap();
-
- FORBID_COPY (BitMap);
+ bool used;
+
+ explicit bitmaps_t(uint32_t n);
+ ~bitmaps_t();
+ void insert(const Go *go, const State *s);
+ const bitmap_t *find(const Go *go, const State *s) const;
+ bool empty() const;
+ void gen(OutputFile &o, uint32_t ind);
+ FORBID_COPY(bitmaps_t);
};
-bool matches(const Span * b1, uint32_t n1, const State * s1, const Span * b2, uint32_t n2, const State * s2);
-
-#ifdef _MSC_VER
-# pragma warning(disable: 4355) /* 'this' : used in base member initializer list */
-#endif
-
-} // end namespace re2c
+} // namespace re2c
#endif // _RE2C_CODEGEN_BITMAP_
if (output.skeletons.insert (name).second)
{
emit_start(o, max_fill, name, key_size, def_rule, need_backup,
- need_accept, oldstyle_ctxmarker, tagnames, tagvars);
+ need_accept, oldstyle_ctxmarker, tagnames, tagvars, bitmaps);
uint32_t i = 2;
emit_body (o, i, used_labels, initial_label);
emit_end(o, name, need_backup, oldstyle_ctxmarker);
o.ws("\n").wdelay_line_info ();
if ((!opts->fFlag && ob.used_yyaccept)
|| (!opts->fFlag && opts->bEmitYYCh)
- || (opts->bFlag && !opts->cFlag && BitMap::first)
+ || (opts->bFlag && !opts->cFlag && !bitmaps.empty())
|| (opts->cFlag && !bWroteCondCheck && opts->gFlag)
|| (opts->fFlag && !bWroteGetState && opts->gFlag)
)
o.ws("\n");
}
}
- if (opts->bFlag && !opts->cFlag && BitMap::first)
+ if (opts->bFlag && !opts->cFlag)
{
- BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256);
+ bitmaps.gen(o, ind);
}
if (bProlog)
{
}
o.wstring(opts->condPrefix).wstring(cond).ws(":\n");
}
- if (opts->cFlag && opts->bFlag && BitMap::first)
+ if (opts->cFlag && opts->bFlag && !bitmaps.empty())
{
o.wind(ind++).ws("{\n");
- BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256);
+ bitmaps.gen(o, ind);
}
// Generate code
emit_body (o, ind, used_labels, initial_label);
- if (opts->cFlag && opts->bFlag && BitMap::first)
+ if (opts->cFlag && opts->bFlag && !bitmaps.empty())
{
o.wind(--ind).ws("}\n");
}
o.wind(--ind).ws("}\n");
}
}
-
- // Cleanup
- if (BitMap::first)
- {
- delete BitMap::first;
- BitMap::first = NULL;
- }
}
void genCondTable(OutputFile & o, uint32_t ind, const std::vector<std::string> & condnames)
{
struct DFA;
-class BitMap;
+class bitmap_t;
+class bitmaps_t;
class State;
struct If;
struct GoBitmap
{
- const BitMap * bitmap;
+ const bitmap_t * bitmap;
const State * bitmap_state;
SwitchIf * hgo;
SwitchIf * lgo;
GoBitmap (const Span * span, uint32_t nSpans, const Span * hspan,
- uint32_t hSpans, const BitMap * bm, const State * bm_state,
+ uint32_t hSpans, const bitmap_t * bm, const State * bm_state,
const State * next, bool sflag);
~GoBitmap ();
void emit (OutputFile & o, uint32_t ind, const DFA &dfa);
Go ();
~Go ();
- void init (const State * from, Opt &opts);
+ void init(const State* from, Opt &opts, bitmaps_t &bitmaps);
void emit (OutputFile & o, uint32_t ind, const DFA &dfa);
void used_labels (std::set<label_t> & used);
}
GoBitmap::GoBitmap (const Span * span, uint32_t nSpans, const Span * hspan,
- uint32_t hSpans, const BitMap * bm, const State * bm_state,
+ uint32_t hSpans, const bitmap_t * bm, const State * bm_state,
const State * next, bool sflag)
: bitmap (bm)
, bitmap_state (bm_state)
, info ()
{}
-void Go::init (const State * from, Opt &opts)
+void Go::init (const State * from, Opt &opts, bitmaps_t &bitmaps)
{
if (nSpans == 0)
{
// initialize bitmaps
uint32_t nBitmaps = 0;
- const BitMap * bitmap = NULL;
- const State * bitmap_state = NULL;
- for (uint32_t i = 0; i < nSpans; ++i)
- {
- if (span[i].to->isBase)
- {
- const BitMap *b = BitMap::find (span[i].to);
- if (b && matches(b->go->span, b->go->nSpans, b->on, span, nSpans, span[i].to))
- {
- if (bitmap == NULL)
- {
- bitmap = b;
- bitmap_state = span[i].to;
- }
- nBitmaps++;
+ const bitmap_t *bm = NULL;
+ const State *bms = NULL;
+
+ for (uint32_t i = 0; i < nSpans; ++i) {
+ const State *s = span[i].to;
+ if (!s->isBase) continue;
+
+ const bitmap_t *b = bitmaps.find(this, s);
+ if (b) {
+ if (bm == NULL) {
+ bm = b;
+ bms = s;
}
+ ++nBitmaps;
}
}
else if (opts->bFlag && (nBitmaps > 0))
{
type = BITMAP;
- info.bitmap = new GoBitmap (span, nSpans, hspan, hSpans, bitmap, bitmap_state, from->next, opts->sFlag);
- bUsedYYBitmap = true;
+ info.bitmap = new GoBitmap (span, nSpans, hspan, hSpans, bm, bms, from->next, opts->sFlag);
+ bitmaps.used = true;
}
else
{
namespace re2c
{
-extern bool bUsedYYBitmap;
extern bool bWroteGetState;
extern bool bWroteCondCheck;
, maxtagver (dfa.maxtagver)
, def_rule (def)
, key_size (key)
+ , bitmaps (std::min(ubChar, 256u))
{
const size_t nstates = dfa.states.size();
const size_t nchars = dfa.nchars;
#include <string>
#include <valarray>
+#include "src/codegen/bitmap.h"
#include "src/codegen/go.h"
#include "src/codegen/label.h"
#include "src/ir/adfa/action.h"
tagver_t maxtagver;
const size_t def_rule;
const size_t key_size;
+ bitmaps_t bitmaps;
DFA ( const dfa_t &dfa
, const std::vector<size_t> &fill
void DFA::prepare (Opt &opts)
{
- bUsedYYBitmap = false;
-
// create rule states
std::vector<State*> rule2state(rules.size());
for (State *s = head; s; s = s->next) {
s->isBase = true;
split(s);
- if (opts->bFlag)
- {
- BitMap::find(&s->next->go, s);
+ if (opts->bFlag) {
+ bitmaps.insert(&s->next->go, s);
}
s = s->next;
// find ``base'' state, if possible
findBaseState();
- for (State * s = head; s; s = s->next)
- {
- s->go.init (s, opts);
+ for (State *s = head; s; s = s->next) {
+ s->go.init(s, opts, bitmaps);
}
}
void emit_start(OutputFile &o, size_t maxfill, const std::string &name,
size_t sizeof_key, size_t def, bool backup, bool accept, bool oldstyle_ctxmarker,
- const std::set<std::string> &tagnames, const std::set<std::string> &tagvars)
+ const std::set<std::string> &tagnames, const std::set<std::string> &tagvars,
+ bitmaps_t &bitmaps)
{
Opt &opts = o.opts;
const size_t sizeof_cunit = opts->encoding.szCodeUnit();
}
o.ws("\n");
- if (opts->bFlag && BitMap::first) {
- BitMap::gen(o, 2, 0, std::min(0x100u, opts->encoding.nCodeUnits()));
+ if (opts->bFlag) {
+ bitmaps.gen(o, 2);
}
o.ws("\n");
}
#include <vector>
#include <utility>
+#include "src/codegen/bitmap.h"
#include "src/ir/regexp/regexp.h"
#include "src/ir/rule.h"
#include "src/ir/tcmd.h"
void emit_prolog(OutputFile & o);
void emit_start(OutputFile &o, size_t maxfill, const std::string &name,
size_t sizeof_key, size_t def, bool backup, bool accept, bool oldstyle_ctxmarker,
- const std::set<std::string> &tagnames, const std::set<std::string> &tagvars);
+ const std::set<std::string> &tagnames, const std::set<std::string> &tagvars,
+ bitmaps_t &bitmaps);
void emit_end(OutputFile &o, const std::string &name, bool backup, bool oldstyle_ctxmarker);
void emit_epilog(OutputFile &o, const std::set<std::string> &names);
void emit_action(OutputFile &o, uint32_t ind, const DFA &dfa, size_t rid);
namespace re2c
{
-bool bUsedYYBitmap = false;
bool bWroteGetState = false;
bool bWroteCondCheck = false;