{
bUsedYYAccept = true;
- if (gFlag)
+ if (gFlag && mapRules.size() >= cGotoThreshold)
{
o << indent(ind++) << "{\n";
o << indent(ind++) << "static void *yytarget[" << mapRules.size() << "] = {\n";
}
}
-void Go::genGoto(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh)
+void Go::genCpGoto(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh) const
{
- if (gFlag || wFlag)
+ const char * sYych = readCh ? "(yych = *YYCURSOR)" : "yych";
+
+ readCh = false;
+ if (wFlag)
+ {
+ o << indent(ind) << "if(" << sYych <<" & 0xFF00) {\n";
+ genBase(o, ind+1, from, next, readCh, 1);
+ o << indent(ind++) << "} else {\n";
+ sYych = "yych";
+ }
+ else
{
- if (wSpans == ~0u)
+ o << indent(ind++) << "{\n";
+ }
+ o << indent(ind++) << "static void *yytarget[256] = {\n";
+ o << indent(ind);
+
+ uint ch = 0;
+ for (uint i = 0; i < lSpans; ++i)
+ {
+ vUsedLabels.insert(span[i].to->label);
+ for(; ch < span[i].ub; ++ch)
{
- wSpans = 0;
- lSpans = 1;
- for (uint p = 0; p < nSpans; p++)
+ o << "&&yy" << span[i].to->label;
+ if (ch == 255)
{
- if (span[p].ub > 0xFF)
- {
- wSpans++;
- }
- if (span[p].ub < 0x100)
- {
- lSpans++;
- }
+ o << "\n";
+ i = lSpans;
+ break;
+ }
+ else if (ch % 8 == 7)
+ {
+ o << ",\n" << indent(ind);
+ }
+ else
+ {
+ o << "," << space(span[i].to->label);
}
- }
- else
- {
- lSpans = nSpans;
}
}
+ o << indent(--ind) << "};\n";
+ o << indent(ind) << "goto *yytarget[" << sYych << "];\n";
+ o << indent(--ind) << "}\n";
+}
- if (gFlag && lSpans >= 16)
+void Go::genGoto(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh)
+{
+ if ((gFlag || wFlag) && wSpans == ~0u)
{
- const char * sYych = readCh ? "(yych = *YYCURSOR)" : "yych";
-
- readCh = false;
- if (wFlag)
- {
- o << indent(ind) << "if(" << sYych <<" & 0xFF00) {\n";
- genBase(o, ind+1, from, next, readCh, 1);
- o << indent(ind++) << "} else {\n";
- sYych = "yych";
- }
- else
- {
- o << indent(ind++) << "{\n";
- }
- o << indent(ind++) << "static void *yytarget[256] = {\n";
- o << indent(ind);
-
- uint ch = 0;
- for (uint i = 0; i < lSpans; ++i)
+ uint nBitmaps = 0;
+ std::set<uint> vTargets;
+ wSpans = 0;
+ lSpans = 1;
+ dSpans = 0;
+ for (uint i = 0; i < nSpans; ++i)
{
- vUsedLabels.insert(span[i].to->label);
- for(; ch < span[i].ub; ++ch)
+ if (span[i].ub > 0xFF)
{
- o << "&&yy" << span[i].to->label;
- if (ch == 255)
- {
- o << "\n";
- i = lSpans;
- break;
- }
- else if (ch % 8 == 7)
+ wSpans++;
+ }
+ if (span[i].ub < 0x100 || !wFlag)
+ {
+ lSpans++;
+
+ State *to = span[i].to;
+
+ if (to && to->isBase)
{
- o << ",\n" << indent(ind);
+ const BitMap *b = BitMap::find(to);
+ const char * sYych;
+
+ if (b && matches(b->go, b->on, this, to))
+ {
+ nBitmaps++;
+ }
+ else
+ {
+ dSpans++;
+ vTargets.insert(to->label);
+ }
}
else
{
- o << "," << space(span[i].to->label);
+ dSpans++;
+ vTargets.insert(to->label);
}
}
}
- o << indent(--ind) << "};\n";
- o << indent(ind) << "goto *yytarget[" << sYych << "];\n";
- o << indent(--ind) << "}\n";
+ lTargets = vTargets.size() >> nBitmaps;
+ }
+
+ if (gFlag && (lTargets >= cGotoThreshold || dSpans >= cGotoThreshold))
+ {
+ genCpGoto(o, ind, from, next, readCh);
return;
}
else if (bFlag)
{
bUseYYFill = num != 0;
}
+ else if (cfg.to_string() == "cgoto:threshold")
+ {
+ cGotoThreshold = num;
+ }
else
{
fatal("unrecognized configuration name or illegal integer value");
: nSpans(0)
, wSpans(~0u)
, lSpans(~0u)
+ , dSpans(~0u)
+ , lTargets(~0u)
, span(NULL)
{
}
public:
- uint nSpans;
- uint wSpans;
- uint lSpans;
+ uint nSpans; // number of spans
+ uint wSpans; // number of spans in wide mode
+ uint lSpans; // number of low (non wide) spans
+ uint dSpans; // number of decision spans (decide between g and b mode)
+ uint lTargets;
Span *span;
public:
void genLinear(std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
void genBinary(std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
void genSwitch(std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
+ void genCpGoto(std::ostream&, uint ind, const State *from, const State *next, bool &readCh) const;
void compact();
void unmap(Go*, const State*);
};
std::string startLabelName;
uint maxFill = 1;
uint next_label = 0;
+uint cGotoThreshold = 9;
uint topIndent = 0;
std::string indString("\t");
static void usage()
{
- cerr << "usage: re2c [-bdefhisvVw1] [-o file] file\n"
+ cerr << "usage: re2c [-bdefghisvVw1] [-o file] file\n"
"\n"
"-? -h --help Display this info.\n"
"\n"
"\n"
"-f --storable-state Generate a scanner that supports storable states.\n"
"\n"
- "-g --computed-gotos Implies -b. Generate computed goto code (only useable \n"
+ "-g --computed-gotos Implies -b. Generate computed goto code (only useable\n"
" with gcc).\n"
"\n"
"-i --no-debug-info Do not generate '#line' info (usefull for versioning).\n"
"-w --wide-chars Create a parser that supports wide chars (UCS-2). This\n"
" implies -s and cannot be used together with -e switch.\n"
"\n"
- "-1 --single-pass Force two pass generation, allows YYMAXFILL generation\n"
- " prior to last re2c block.\n"
+ "-1 --single-pass Force single pass generation, this cannot be combined\n"
+ " with -f and disables YYMAXFILL generation prior to last\n"
+ " re2c block.\n"
;
}