}
if (bProlog)
{
-
genCondTable(o, ind, *specMap);
genGetState(o, ind, start_label);
genCondGoto(o, ind, *specMap);
}
}
+static RegExpIndices genCondList(const RegExpMap& specMap)
+{
+ RegExpIndices vCondList;
+
+ for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it)
+ {
+ vCondList.push_back(it->first);
+ }
+
+ return vCondList;
+}
+
void genCondTable(std::ostream &o, uint ind, const RegExpMap& specMap)
{
- if (cFlag && !bWroteCondCheck && gFlag)
+ if (cFlag && !bWroteCondCheck && gFlag && specMap.size())
{
o << indent(ind++) << "static void *" << mapCodeName["yyctable"] << "[" << specMap.size() << "] = {\n";
- for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it)
+ RegExpIndices vCondList = genCondList(specMap);
+
+ for(RegExpIndices::const_iterator it = vCondList.begin(); it != vCondList.end(); ++it)
{
- o << indent(ind) << "&&" << condPrefix << it->first << ",\n";
+ o << indent(ind) << "&&" << condPrefix << *it << ",\n";
}
o << indent(--ind) << "};\n";
}
}
+static void genCondGotoSub(std::ostream &o, uint ind, RegExpIndices& vCondList, uint cMin, uint cMax)
+{
+ if (cMin == cMax)
+ {
+ o << indent(ind) << "goto " << condPrefix << vCondList[cMin] << ";\n";
+ }
+ else
+ {
+ uint cMid = cMin + ((cMax - cMin + 1) / 2);
+
+ o << indent(ind) << "if (" << mapCodeName["YYCONDITION"] << " < " << cMid << ") {\n";
+ genCondGotoSub(o, ind + 1, vCondList, cMin, cMid - 1);
+ o << indent(ind) << "} else {\n";
+ genCondGotoSub(o, ind + 1, vCondList, cMid, cMax);
+ o << indent(ind) << "}\n";
+ }
+}
+
void genCondGoto(std::ostream &o, uint ind, const RegExpMap& specMap)
{
- if (cFlag && !bWroteCondCheck)
+ if (cFlag && !bWroteCondCheck && specMap.size())
{
if (gFlag)
{
}
else
{
- o << indent(ind) << "switch(" << mapCodeName["YYCONDITION"] << ") {\n";
- for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it)
+ RegExpIndices vCondList = genCondList(specMap);
+
+ if (sFlag)
{
- o << indent(ind) << "case " << it->first << ": goto " << condPrefix << it->first << ";\n";
+ genCondGotoSub(o, ind, vCondList, 0, vCondList.size() - 1);
+ }
+ else
+ {
+ o << indent(ind) << "switch(" << mapCodeName["YYCONDITION"] << ") {\n";
+
+ for(RegExpIndices::const_iterator it = vCondList.begin(); it != vCondList.end(); ++it)
+ {
+ o << indent(ind) << "case " << *it << ": goto " << condPrefix << *it << ";\n";
+ }
+ o << indent(ind) << "}\n";
}
- o << indent(ind) << "}\n";
}
bWroteCondCheck = true;
}
#include <set>
#include <map>
#include <list>
+#include <vector>
#include "token.h"
#include "ins.h"
#include "globals.h"
typedef std::set<std::string> CondList;
typedef std::pair<int, RegExp*> NRegExp;
typedef std::map<std::string, NRegExp> RegExpMap;
+typedef std::vector<std::string> RegExpIndices;
typedef std::list<RuleOp*> RuleOpList;
extern void genCode(std::ostream&, uint&, RegExp*, const RegExpMap*, const std::string&, bool);
--- /dev/null
+/* Generated by re2c */
+#line 1 "condition_05.cs.re"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BSIZE 8192
+
+typedef struct Scanner
+{
+ FILE *fp;
+ unsigned char *cur, *tok, *lim, *eof;
+ unsigned char buffer[BSIZE];
+} Scanner;
+
+int fill(Scanner *s, int len)
+{
+ if (!len)
+ {
+ s->cur = s->tok = s->lim = s->buffer;
+ s->eof = 0;
+ }
+ if (!s->eof)
+ {
+ int got, cnt = s->tok - s->buffer;
+
+ if (cnt > 0)
+ {
+ memcpy(s->buffer, s->tok, s->lim - s->tok);
+ s->tok -= cnt;
+ s->cur -= cnt;
+ s->lim -= cnt;
+ }
+ cnt = BSIZE - cnt;
+ if ((got = fread(s->lim, 1, cnt, s->fp)) != cnt)
+ {
+ s->eof = &s->lim[got];
+ }
+ s->lim += got;
+ }
+ else if (s->cur + len > s->eof)
+ {
+ return 0; /* not enough input data */
+ }
+ return -1;
+}
+
+char scan(Scanner *s)
+{
+ int state = 1;
+
+ fill(s, 0);
+
+ for(;;)
+ {
+ s->tok = s->cur;
+
+#line 59 "<stdout>"
+ {
+ unsigned char yych;
+ if (state < 1) {
+ goto yyc_comment;
+ } else {
+ goto yyc_normal;
+ }
+/* *********************************** */
+yyc_comment:
+
+ if((s->lim - s->cur) < 2) { if(fill(s, 2) >= 0) break; };
+ yych = *s->cur;
+ if(yych != '*') goto yy4;
+ ++s->cur;
+ if((yych = *s->cur) == '/') goto yy5;
+yy3:
+#line 80 "condition_05.cs.re"
+ {
+ goto yyc_comment;
+ }
+#line 80 "<stdout>"
+yy4:
+ yych = *++s->cur;
+ goto yy3;
+yy5:
+ ++s->cur;
+#line 76 "condition_05.cs.re"
+ {
+ continue;
+ }
+#line 90 "<stdout>"
+/* *********************************** */
+yyc_normal:
+ if((s->lim - s->cur) < 2) { if(fill(s, 2) >= 0) break; };
+ yych = *s->cur;
+ if(yych != '/') goto yy11;
+ ++s->cur;
+ if((yych = *s->cur) == '*') goto yy12;
+yy10:
+#line 71 "condition_05.cs.re"
+ {
+ fputc(*s->tok, stdout);
+ continue;
+ }
+#line 104 "<stdout>"
+yy11:
+ yych = *++s->cur;
+ goto yy10;
+yy12:
+ ++s->cur;
+#line 67 "condition_05.cs.re"
+ {
+ goto yyc_comment;
+ }
+#line 114 "<stdout>"
+ }
+#line 84 "condition_05.cs.re"
+
+ }
+}
+
+int main(int argc, char **argv)
+{
+ Scanner in;
+ char c;
+
+ if (argc != 2)
+ {
+ fprintf(stderr, "%s <file>\n", argv[0]);
+ return 1;;
+ }
+
+ memset((char*) &in, 0, sizeof(in));
+
+ if (!strcmp(argv[1], "-"))
+ {
+ in.fp = stdin;
+ }
+ else if ((in.fp = fopen(argv[1], "r")) == NULL)
+ {
+ fprintf(stderr, "Cannot open file '%s'\n", argv[1]);
+ return 1;
+ }
+
+ scan(&in);
+
+ if (in.fp != stdin)
+ {
+ fclose(in.fp);
+ }
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BSIZE 8192
+
+typedef struct Scanner
+{
+ FILE *fp;
+ unsigned char *cur, *tok, *lim, *eof;
+ unsigned char buffer[BSIZE];
+} Scanner;
+
+int fill(Scanner *s, int len)
+{
+ if (!len)
+ {
+ s->cur = s->tok = s->lim = s->buffer;
+ s->eof = 0;
+ }
+ if (!s->eof)
+ {
+ int got, cnt = s->tok - s->buffer;
+
+ if (cnt > 0)
+ {
+ memcpy(s->buffer, s->tok, s->lim - s->tok);
+ s->tok -= cnt;
+ s->cur -= cnt;
+ s->lim -= cnt;
+ }
+ cnt = BSIZE - cnt;
+ if ((got = fread(s->lim, 1, cnt, s->fp)) != cnt)
+ {
+ s->eof = &s->lim[got];
+ }
+ s->lim += got;
+ }
+ else if (s->cur + len > s->eof)
+ {
+ return 0; /* not enough input data */
+ }
+ return -1;
+}
+
+char scan(Scanner *s)
+{
+ int state = 1;
+
+ fill(s, 0);
+
+ for(;;)
+ {
+ s->tok = s->cur;
+/*!re2c
+
+re2c:define:YYCTYPE = "unsigned char";
+re2c:define:YYCURSOR = s->cur;
+re2c:define:YYLIMIT = s->lim;
+re2c:define:YYMARKER = s->ptr;
+re2c:define:YYFILL = "{ if(fill(s, 2) >= 0) break; }";
+re2c:define:YYCONDITION = state;
+re2c:yyfill:parameter = 0;
+re2c:indent:top = 2;
+
+<normal> "/*"
+ {
+ goto yyc_comment;
+ }
+<normal> [^]
+ {
+ fputc(*s->tok, stdout);
+ continue;
+ }
+<comment> "*" "/"
+ {
+ continue;
+ }
+<comment> [^]
+ {
+ goto yyc_comment;
+ }
+
+*/
+ }
+}
+
+int main(int argc, char **argv)
+{
+ Scanner in;
+ char c;
+
+ if (argc != 2)
+ {
+ fprintf(stderr, "%s <file>\n", argv[0]);
+ return 1;;
+ }
+
+ memset((char*) &in, 0, sizeof(in));
+
+ if (!strcmp(argv[1], "-"))
+ {
+ in.fp = stdin;
+ }
+ else if ((in.fp = fopen(argv[1], "r")) == NULL)
+ {
+ fprintf(stderr, "Cannot open file '%s'\n", argv[1]);
+ return 1;
+ }
+
+ scan(&in);
+
+ if (in.fp != stdin)
+ {
+ fclose(in.fp);
+ }
+ return 0;
+}