]> granicus.if.org Git - re2c/commitdiff
- Add -cs support
authorhelly <helly@642ea486-5414-0410-9d7f-a0204ed87703>
Mon, 23 Apr 2007 22:18:43 +0000 (22:18 +0000)
committerhelly <helly@642ea486-5414-0410-9d7f-a0204ed87703>
Mon, 23 Apr 2007 22:18:43 +0000 (22:18 +0000)
re2c/code.cc
re2c/re.h
re2c/test/condition_05.cs.c [new file with mode: 0755]
re2c/test/condition_05.cs.re [new file with mode: 0755]

index 828f4aa906b7cd01dbf0e730b6361165c9f16d37..8a16ad4204bfcf125880dc68b2f682a81dfec91f 100644 (file)
@@ -1586,7 +1586,6 @@ void DFA::emit(std::ostream &o, uint& ind, const RegExpMap* specMap, const std::
        }
        if (bProlog)
        {
-
                genCondTable(o, ind, *specMap);
                genGetState(o, ind, start_label);
                genCondGoto(o, ind, *specMap);
@@ -1663,23 +1662,55 @@ void genGetState(std::ostream &o, uint& ind, uint start_label)
        }
 }
 
+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)
                {
@@ -1687,12 +1718,22 @@ void genCondGoto(std::ostream &o, uint ind, const RegExpMap& specMap)
                }
                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;
        }
index 89c4d0fc78675057e36cd965558df605c514985b..9dd676900d4cd372fcea884bc7ab7e585862057c 100644 (file)
--- a/re2c/re.h
+++ b/re2c/re.h
@@ -6,6 +6,7 @@
 #include <set>
 #include <map>
 #include <list>
+#include <vector>
 #include "token.h"
 #include "ins.h"
 #include "globals.h"
@@ -489,6 +490,7 @@ private:
 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);
diff --git a/re2c/test/condition_05.cs.c b/re2c/test/condition_05.cs.c
new file mode 100755 (executable)
index 0000000..930b412
--- /dev/null
@@ -0,0 +1,150 @@
+/* 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;
+}
diff --git a/re2c/test/condition_05.cs.re b/re2c/test/condition_05.cs.re
new file mode 100755 (executable)
index 0000000..7c702fa
--- /dev/null
@@ -0,0 +1,118 @@
+#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;
+}