]> granicus.if.org Git - re2c/commitdiff
- Add lesson 2
authorhelly <helly@642ea486-5414-0410-9d7f-a0204ed87703>
Mon, 17 Apr 2006 02:08:09 +0000 (02:08 +0000)
committerhelly <helly@642ea486-5414-0410-9d7f-a0204ed87703>
Mon, 17 Apr 2006 02:08:09 +0000 (02:08 +0000)
lessons/002_strip_comments/.cvsignore [new file with mode: 0755]
lessons/002_strip_comments/readme.txt [new file with mode: 0755]
lessons/002_strip_comments/strip_001.s.c [new file with mode: 0755]
lessons/002_strip_comments/strip_001.s.re [new file with mode: 0755]
lessons/002_strip_comments/strip_002.s.c [new file with mode: 0755]
lessons/002_strip_comments/strip_002.s.re [new file with mode: 0755]
lessons/002_strip_comments/t.c [new file with mode: 0755]

diff --git a/lessons/002_strip_comments/.cvsignore b/lessons/002_strip_comments/.cvsignore
new file mode 100755 (executable)
index 0000000..1938665
--- /dev/null
@@ -0,0 +1,4 @@
+a.out
+*.temp
+*.diff
+*.o
diff --git a/lessons/002_strip_comments/readme.txt b/lessons/002_strip_comments/readme.txt
new file mode 100755 (executable)
index 0000000..535a4ea
--- /dev/null
@@ -0,0 +1,13 @@
+re2c lesson_002, (c) M. Boerger 2006
+
+In this lesson you will learn how to use multiple scanner blocks and how to 
+read the input from a file instead of a zero terminated string. In the end you
+will have a scanner that filters comments out of c source files but keeps re2c
+comments.
+
+The first scanner can be generated with:
+
+  re2c -s -o t.c strip_001.s.re
+
+In the second step we will learn about YYMARKER that stores backtracking 
+information and YYCTXMARKER that is used for trailing contexts.
\ No newline at end of file
diff --git a/lessons/002_strip_comments/strip_001.s.c b/lessons/002_strip_comments/strip_001.s.c
new file mode 100755 (executable)
index 0000000..ad0d85b
--- /dev/null
@@ -0,0 +1,187 @@
+/* Generated by re2c */
+#line 1 "strip_001.s.re"
+/* re2c lesson_002, strip_001.s, (c) M. Boerger 2006 */
+#line 32 "strip_001.s.re"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define YYMAXFILL 2
+#define        BSIZE   128
+
+#if BSIZE < YYMAXFILL
+# error BSIZE must be greater YYMAXFILL
+#endif
+
+#define        YYCTYPE         char
+#define        YYCURSOR        s.cur
+#define        YYLIMIT         s.lim
+#define        YYFILL(n)       { if ((res = fill(&s, n)) >= 0) break; }
+
+typedef struct Scanner
+{
+       FILE            *fp;
+       char            *cur, *tok, *lim, *eof;
+       char            buffer[BSIZE];
+} Scanner;
+
+int fill(Scanner *s, int len)
+{
+       if (!len)
+       {
+               s->tok = s->cur = buf = 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;
+}
+
+int scan(FILE *fp)
+{
+       int  res = 0;
+    Scanner s;
+
+       if (!fp)
+       {
+               return 1; /* no file was opened */
+       }
+
+    s.fp = fp;
+       
+       fill(&s, 0);
+
+       for(;;)
+       {
+               s.tok = s.cur;
+
+#line 80 "<stdout>"
+               {
+                       YYCTYPE yych;
+
+                       if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+                       yych = *YYCURSOR;
+                       if(yych != '/') goto yy4;
+                       ++YYCURSOR;
+                       if((yych = *YYCURSOR) == '*') goto yy5;
+                       if(yych == '/') goto yy7;
+yy3:
+#line 113 "strip_001.s.re"
+                       { fputc(*s.tok, stdout); continue; }
+#line 93 "<stdout>"
+yy4:
+                       yych = *++YYCURSOR;
+                       goto yy3;
+yy5:
+                       ++YYCURSOR;
+#line 112 "strip_001.s.re"
+                       { goto comment; }
+#line 101 "<stdout>"
+yy7:
+                       ++YYCURSOR;
+#line 111 "strip_001.s.re"
+                       { goto cppcomment; }
+#line 106 "<stdout>"
+               }
+#line 114 "strip_001.s.re"
+
+comment:
+               s.tok = s.cur;
+
+#line 113 "<stdout>"
+               {
+                       YYCTYPE yych;
+                       if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+                       yych = *YYCURSOR;
+                       if(yych != '*') goto yy13;
+                       ++YYCURSOR;
+                       if((yych = *YYCURSOR) == '/') goto yy14;
+yy12:
+#line 119 "strip_001.s.re"
+                       { goto comment; }
+#line 124 "<stdout>"
+yy13:
+                       yych = *++YYCURSOR;
+                       goto yy12;
+yy14:
+                       ++YYCURSOR;
+#line 118 "strip_001.s.re"
+                       { continue; }
+#line 132 "<stdout>"
+               }
+#line 120 "strip_001.s.re"
+
+cppcomment:
+               s.tok = s.cur;
+
+#line 139 "<stdout>"
+               {
+                       YYCTYPE yych;
+                       if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+                       yych = *YYCURSOR;
+                       if(yych == 0x0A) goto yy20;
+                       if(yych != 0x0D) goto yy22;
+                       ++YYCURSOR;
+                       if((yych = *YYCURSOR) == 0x0A) goto yy23;
+yy19:
+#line 125 "strip_001.s.re"
+                       { goto cppcomment; }
+#line 151 "<stdout>"
+yy20:
+                       ++YYCURSOR;
+yy21:
+#line 124 "strip_001.s.re"
+                       { fwrite(s.tok, 1, s.cur - s.tok, stdout); continue; }
+#line 157 "<stdout>"
+yy22:
+                       yych = *++YYCURSOR;
+                       goto yy19;
+yy23:
+                       ++YYCURSOR;
+                       yych = *YYCURSOR;
+                       goto yy21;
+               }
+#line 126 "strip_001.s.re"
+
+       }
+
+       if (fp != stdin)
+       {
+               fclose(fp); /* close only if not stdin */
+       }
+       return res; /* return result */
+}
+
+int main(int argc, char **argv)
+{
+       if (argc > 1)
+       {
+               return scan(!strcmp(argv[1], "-") ? stdin : fopen(argv[1], "r"));
+       }
+       else
+       {
+               fprintf(stderr, "%s <expr>\n", argv[0]);
+               return 1;
+       }
+}
diff --git a/lessons/002_strip_comments/strip_001.s.re b/lessons/002_strip_comments/strip_001.s.re
new file mode 100755 (executable)
index 0000000..cf09d5e
--- /dev/null
@@ -0,0 +1,147 @@
+/* re2c lesson_002, strip_001.s, (c) M. Boerger 2006 */
+/*!ignore:re2c
+
+- basic interface for file reading
+  . This scanner will read chunks of input from a file. The easiest way would 
+    be to read the whole file into a memory buffer and use that a zero 
+    terminated string.
+  . Instead we want to read input chunks of a reasonable size as they are neede
+    by the scanner. Thus we basically need YYFILL(n) to call fread(n).
+  . Before we provide a buffer that we constantly reallocate we instead use
+    one buffer that we get from the stack or global memory just once. When we 
+    reach the end of the buffer we simply move the beginning of our input
+    that is somewhere in our buffer to the beginning of our buffer and then
+    append the next chunk of input to the correct end inside our buffer.
+  . As re2c scanners might read more than one character we need to ensure our
+    buffer is long enough. We can use re2c to inform about the maximum size 
+    by placing a "!max:re2c" comment somewhere. This gets translated to a 
+    "#define YYMAXFILL <n>" line where <n> is the maximum length value. This
+    define can be used as precompiler condition.
+
+- multiple scanner blocks
+  . We use a main scanner block that outputs every input character unless the
+    input is two /s or a / followed by a *. In the lattertwo cases we switch
+    to a special c++ comment and a comment block respectively.
+  . Both special blocks simply detect their end ignore any other character.
+  . The c++ block is a bit special. Since the terminating new line needs to
+    be output and that can either be a new line or a carridge return followed 
+    by a new line.
+  . In order to ensure that we do not read behind our buffer we reset the token
+    pointer to the cursor on every scanner run.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/*!max:re2c */
+#define        BSIZE   128
+
+#if BSIZE < YYMAXFILL
+# error BSIZE must be greater YYMAXFILL
+#endif
+
+#define        YYCTYPE         char
+#define        YYCURSOR        s.cur
+#define        YYLIMIT         s.lim
+#define        YYFILL(n)       { if ((res = fill(&s, n)) >= 0) break; }
+
+typedef struct Scanner
+{
+       FILE            *fp;
+       char            *cur, *tok, *lim, *eof;
+       char            buffer[BSIZE];
+} Scanner;
+
+int fill(Scanner *s, int len)
+{
+       if (!len)
+       {
+               s->tok = s->cur = buf = 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;
+}
+
+int scan(FILE *fp)
+{
+       int  res = 0;
+    Scanner s;
+
+       if (!fp)
+       {
+               return 1; /* no file was opened */
+       }
+
+    s.fp = fp;
+       
+       fill(&s, 0);
+
+       for(;;)
+       {
+               s.tok = s.cur;
+/*!re2c
+       re2c:indent:top = 2;
+       
+       NL                      = "\r"? "\n" ;
+       ANY                     = [^] ;
+
+       "/" "/"         { goto cppcomment; }
+       "/" "*"         { goto comment; }
+       ANY                     { fputc(*s.tok, stdout); continue; }
+*/
+comment:
+               s.tok = s.cur;
+/*!re2c
+       "*" "/"         { continue; }
+       ANY                     { goto comment; }
+*/
+cppcomment:
+               s.tok = s.cur;
+/*!re2c
+       NL                      { fwrite(s.tok, 1, s.cur - s.tok, stdout); continue; }
+       ANY                     { goto cppcomment; }
+*/
+       }
+
+       if (fp != stdin)
+       {
+               fclose(fp); /* close only if not stdin */
+       }
+       return res; /* return result */
+}
+
+int main(int argc, char **argv)
+{
+       if (argc > 1)
+       {
+               return scan(!strcmp(argv[1], "-") ? stdin : fopen(argv[1], "r"));
+       }
+       else
+       {
+               fprintf(stderr, "%s <expr>\n", argv[0]);
+               return 1;
+       }
+}
diff --git a/lessons/002_strip_comments/strip_002.s.c b/lessons/002_strip_comments/strip_002.s.c
new file mode 100755 (executable)
index 0000000..63d103c
--- /dev/null
@@ -0,0 +1,304 @@
+/* Generated by re2c */
+#line 1 "strip_002.s.re"
+/* re2c lesson_002, strip_002.s, (c) M. Boerger 2006 */
+#line 27 "strip_002.s.re"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define YYMAXFILL 4
+#define        BSIZE   128
+
+#if BSIZE < YYMAXFILL
+# error BSIZE must be greater YYMAXFILL
+#endif
+
+#define        YYCTYPE         char
+#define        YYCURSOR        s.cur
+#define        YYLIMIT         s.lim
+#define YYMARKER       s.mrk
+#define YYCTXMARKER s.ctx
+#define        YYFILL(n)       { if ((res = fill(&s, n)) >= 0) break; }
+
+typedef struct Scanner
+{
+       FILE            *fp;
+       char            *cur, *tok, *lim, *eof, *ctx, *mrk;
+       char            buffer[BSIZE];
+} Scanner;
+
+int fill(Scanner *s, int len)
+{
+       if (!len)
+       {
+               s->tok = s->cur = s->lim = s->mrk = 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;
+                       s->mrk -= cnt;
+                       s->ctx -= 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;
+}
+
+void echo(Scanner *s)
+{
+       fwrite(s->tok, 1, s->cur - s->tok, stdout);
+}
+
+int scan(FILE *fp)
+{
+       int  res = 0;
+       int  nlcomment = 0;
+    Scanner s;
+
+       if (!fp)
+       {
+               return 1; /* no file was opened */
+       }
+
+    s.fp = fp;
+       
+       fill(&s, 0);
+
+       for(;;)
+       {
+               s.tok = s.cur;
+
+#line 90 "<stdout>"
+               {
+                       YYCTYPE yych;
+
+                       if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+                       yych = *YYCURSOR;
+                       if(yych <= 0x0C) {
+                               if(yych == 0x0A) goto yy5;
+                               goto yy6;
+                       } else {
+                               if(yych <= 0x0D) goto yy4;
+                               if(yych != '/') goto yy6;
+                       }
+                       ++YYCURSOR;
+                       if((yych = *YYCURSOR) == '*') goto yy12;
+                       if(yych == '/') goto yy14;
+yy3:
+#line 120 "strip_002.s.re"
+                       { fputc(*s.tok, stdout); continue; }
+#line 109 "<stdout>"
+yy4:
+                       yych = *(YYMARKER = ++YYCURSOR);
+                       if(yych == 0x0A) goto yy11;
+                       goto yy3;
+yy5:
+                       YYCTXMARKER = YYCURSOR + 1;
+                       yych = *(YYMARKER = ++YYCURSOR);
+                       if(yych == '/') goto yy7;
+                       goto yy3;
+yy6:
+                       yych = *++YYCURSOR;
+                       goto yy3;
+yy7:
+                       yych = *++YYCURSOR;
+                       if(yych == '*') goto yy9;
+yy8:
+                       YYCURSOR = YYMARKER;
+                       goto yy3;
+yy9:
+                       ++YYCURSOR;
+                       YYCURSOR = YYCTXMARKER;
+#line 118 "strip_002.s.re"
+                       { echo(&s); nlcomment = 1; continue; }
+#line 133 "<stdout>"
+yy11:
+                       YYCTXMARKER = YYCURSOR + 1;
+                       yych = *++YYCURSOR;
+                       if(yych == '/') goto yy7;
+                       goto yy8;
+yy12:
+                       ++YYCURSOR;
+#line 119 "strip_002.s.re"
+                       { goto comment; }
+#line 143 "<stdout>"
+yy14:
+                       ++YYCURSOR;
+#line 117 "strip_002.s.re"
+                       { goto cppcomment; }
+#line 148 "<stdout>"
+               }
+#line 121 "strip_002.s.re"
+
+comment:
+               s.tok = s.cur;
+
+#line 155 "<stdout>"
+               {
+                       YYCTYPE yych;
+                       if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+                       yych = *YYCURSOR;
+                       if(yych != '*') goto yy20;
+                       ++YYCURSOR;
+                       if((yych = *YYCURSOR) == '/') goto yy21;
+yy19:
+#line 126 "strip_002.s.re"
+                       { goto comment; }
+#line 166 "<stdout>"
+yy20:
+                       yych = *++YYCURSOR;
+                       goto yy19;
+yy21:
+                       ++YYCURSOR;
+#line 125 "strip_002.s.re"
+                       { goto commentws; }
+#line 174 "<stdout>"
+               }
+#line 127 "strip_002.s.re"
+
+commentws:
+               s.tok = s.cur;
+
+#line 181 "<stdout>"
+               {
+                       YYCTYPE yych;
+                       if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+                       yych = *YYCURSOR;
+                       if(yych <= 0x0D) {
+                               if(yych <= 0x09) {
+                                       if(yych <= 0x08) goto yy32;
+                                       goto yy31;
+                               } else {
+                                       if(yych <= 0x0A) goto yy27;
+                                       if(yych <= 0x0C) goto yy32;
+                               }
+                       } else {
+                               if(yych <= ' ') {
+                                       if(yych <= 0x1F) goto yy32;
+                                       goto yy31;
+                               } else {
+                                       if(yych == '/') goto yy29;
+                                       goto yy32;
+                               }
+                       }
+                       ++YYCURSOR;
+                       if((yych = *YYCURSOR) == 0x0A) goto yy37;
+yy26:
+#line 140 "strip_002.s.re"
+                       { goto commentws; }
+#line 208 "<stdout>"
+yy27:
+                       yych = *(YYMARKER = ++YYCURSOR);
+                       if(yych == '/') goto yy35;
+yy28:
+#line 132 "strip_002.s.re"
+                       {
+                               if (!nlcomment)
+                               {
+                                       echo(&s);
+                               }
+                               nlcomment = 0;
+                               continue;
+                       }
+#line 222 "<stdout>"
+yy29:
+                       ++YYCURSOR;
+                       if((yych = *YYCURSOR) == '*') goto yy33;
+yy30:
+#line 141 "strip_002.s.re"
+                       { echo(&s); nlcomment = 0; continue; }
+#line 229 "<stdout>"
+yy31:
+                       yych = *++YYCURSOR;
+                       goto yy26;
+yy32:
+                       yych = *++YYCURSOR;
+                       goto yy30;
+yy33:
+                       ++YYCURSOR;
+#line 131 "strip_002.s.re"
+                       { goto comment; }
+#line 240 "<stdout>"
+yy35:
+                       yych = *++YYCURSOR;
+                       if(yych == '*') goto yy33;
+                       YYCURSOR = YYMARKER;
+                       goto yy28;
+yy37:
+                       yych = *(YYMARKER = ++YYCURSOR);
+                       if(yych == '/') goto yy35;
+                       goto yy28;
+               }
+#line 142 "strip_002.s.re"
+
+cppcomment:
+               s.tok = s.cur;
+
+#line 256 "<stdout>"
+               {
+                       YYCTYPE yych;
+                       if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+                       yych = *YYCURSOR;
+                       if(yych == 0x0A) goto yy42;
+                       if(yych != 0x0D) goto yy44;
+                       ++YYCURSOR;
+                       if((yych = *YYCURSOR) == 0x0A) goto yy45;
+yy41:
+#line 147 "strip_002.s.re"
+                       { goto cppcomment; }
+#line 268 "<stdout>"
+yy42:
+                       ++YYCURSOR;
+yy43:
+#line 146 "strip_002.s.re"
+                       { echo(&s); continue; }
+#line 274 "<stdout>"
+yy44:
+                       yych = *++YYCURSOR;
+                       goto yy41;
+yy45:
+                       ++YYCURSOR;
+                       yych = *YYCURSOR;
+                       goto yy43;
+               }
+#line 148 "strip_002.s.re"
+
+       }
+
+       if (fp != stdin)
+       {
+               fclose(fp); /* close only if not stdin */
+       }
+       return res; /* return result */
+}
+
+int main(int argc, char **argv)
+{
+       if (argc > 1)
+       {
+               return scan(!strcmp(argv[1], "-") ? stdin : fopen(argv[1], "r"));
+       }
+       else
+       {
+               fprintf(stderr, "%s <expr>\n", argv[0]);
+               return 1;
+       }
+}
diff --git a/lessons/002_strip_comments/strip_002.s.re b/lessons/002_strip_comments/strip_002.s.re
new file mode 100755 (executable)
index 0000000..282f00d
--- /dev/null
@@ -0,0 +1,169 @@
+/* re2c lesson_002, strip_002.s, (c) M. Boerger 2006 */
+/*!ignore:re2c
+
+- complexity
+  . When two comments are only separated by whitespace we want to drop both.
+  . When a comemnt is preceeded by a new line and followed by whitespace and a 
+    new line then we can drop the trailing whitespace and new line.
+    But we cannot simply use the following two rules:
+         "*" "/" WS* "/" "*" { continue; }
+         "*" "/" WS* NL      { continue; }
+       The main problem is that WS* can get bigger then our buffer, so we need a 
+       new scanner.
+  . Meanwhile our scanner gets a bit more complex and we have to add two more 
+    things. First the scanner code now uses a YYMARKER to store backtracking 
+    information. And second we have a new rule that utilizes trailing contexts.
+    Therefore we also need to add YYCTXMARKER.
+- formatting
+  . Until now we only used single line expression code and we always had the 
+    opening { on the same line as the rule itself. If we have multiline rule
+    code and care for formatting we can nolonger rely on re2c. Now we have 
+    to indent the rule code ourself. Also we need to take care of the opening
+    {. If we keep it on the same line as the rule then re2c will indent it 
+    correctly and the emitted #line informations will be correct. If we place
+    it on the next line then the #line directivy will also point to that line
+    and not to the rule.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/*!max:re2c */
+#define        BSIZE   128
+
+#if BSIZE < YYMAXFILL
+# error BSIZE must be greater YYMAXFILL
+#endif
+
+#define        YYCTYPE         char
+#define        YYCURSOR        s.cur
+#define        YYLIMIT         s.lim
+#define YYMARKER       s.mrk
+#define YYCTXMARKER s.ctx
+#define        YYFILL(n)       { if ((res = fill(&s, n)) >= 0) break; }
+
+typedef struct Scanner
+{
+       FILE            *fp;
+       char            *cur, *tok, *lim, *eof, *ctx, *mrk;
+       char            buffer[BSIZE];
+} Scanner;
+
+int fill(Scanner *s, int len)
+{
+       if (!len)
+       {
+               s->tok = s->cur = s->lim = s->mrk = 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;
+                       s->mrk -= cnt;
+                       s->ctx -= 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;
+}
+
+void echo(Scanner *s)
+{
+       fwrite(s->tok, 1, s->cur - s->tok, stdout);
+}
+
+int scan(FILE *fp)
+{
+       int  res = 0;
+       int  nlcomment = 0;
+    Scanner s;
+
+       if (!fp)
+       {
+               return 1; /* no file was opened */
+       }
+
+    s.fp = fp;
+       
+       fill(&s, 0);
+
+       for(;;)
+       {
+               s.tok = s.cur;
+/*!re2c
+       re2c:indent:top = 2;
+       
+       NL                      = "\r"? "\n" ;
+       WS                      = [\r\n\t ] ;
+       ANY                     = [^] ;
+
+       "/" "/"         { goto cppcomment; }
+       NL / "/""*"     { echo(&s); nlcomment = 1; continue; }
+       "/" "*"         { goto comment; }
+       ANY                     { fputc(*s.tok, stdout); continue; }
+*/
+comment:
+               s.tok = s.cur;
+/*!re2c
+       "*" "/"         { goto commentws; }
+       ANY                     { goto comment; }
+*/
+commentws:
+               s.tok = s.cur;
+/*!re2c
+       NL? "/" "*"     { goto comment; }
+       NL                      {
+                               if (!nlcomment)
+                               {
+                                       echo(&s);
+                               }
+                               nlcomment = 0;
+                               continue;
+                       }
+       WS                      { goto commentws; }
+       ANY                     { echo(&s); nlcomment = 0; continue; }
+*/
+cppcomment:
+               s.tok = s.cur;
+/*!re2c
+       NL                      { echo(&s); continue; }
+       ANY                     { goto cppcomment; }
+*/
+       }
+
+       if (fp != stdin)
+       {
+               fclose(fp); /* close only if not stdin */
+       }
+       return res; /* return result */
+}
+
+int main(int argc, char **argv)
+{
+       if (argc > 1)
+       {
+               return scan(!strcmp(argv[1], "-") ? stdin : fopen(argv[1], "r"));
+       }
+       else
+       {
+               fprintf(stderr, "%s <expr>\n", argv[0]);
+               return 1;
+       }
+}
diff --git a/lessons/002_strip_comments/t.c b/lessons/002_strip_comments/t.c
new file mode 100755 (executable)
index 0000000..592e964
--- /dev/null
@@ -0,0 +1,349 @@
+/* Generated by re2c 0.10.2.dev on Sun Apr 16 21:50:17 2006 */
+#line 1 "strip_002.s.re"
+/* re2c lesson_002, strip_001.s, (c) M. Boerger 2006 */
+#line 14 "strip_002.s.re"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define YYMAXFILL 4
+#define        BSIZE   128
+
+#if BSIZE < YYMAXFILL
+# error BSIZE must be greater YYMAXFILL
+#endif
+
+#define        YYCTYPE         char
+#define        YYCURSOR        s.cur
+#define        YYLIMIT         s.lim
+#define YYMARKER       s.mrk
+#define YYCTXMARKER s.ctx
+#define        YYFILL(n)       { if ((res = fill(&s, n)) >= 0) break; }
+
+typedef struct Scanner
+{
+       FILE            *fp;
+       char            *cur, *tok, *lim, *eof, *ctx, *mrk;
+       char            buffer[BSIZE];
+} Scanner;
+
+int fill(Scanner *s, int len)
+{
+       if (!len)
+       {
+               s->tok = s->cur = s->lim = s->mrk = 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;
+                       s->mrk -= cnt;
+                       s->ctx -= 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;
+}
+
+void echo(Scanner *s)
+{
+       fwrite(s->tok, 1, s->cur - s->tok, stdout);
+}
+
+int scan(FILE *fp)
+{
+       int  res = 0;
+       int  nlcomment = 0;
+    Scanner s;
+
+       if (!fp)
+       {
+               return 1; // no file was opened
+       }
+
+    s.fp = fp;
+       
+       fill(&s, 0);
+
+       for(;;)
+       {
+               s.tok = s.cur;
+
+#line 90 "t.c"
+               {
+                       YYCTYPE yych;
+
+                       if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+                       yych = *YYCURSOR;
+                       switch(yych){
+                       case 0x0A:      goto yy5;
+                       case 0x0D:      goto yy4;
+                       case '/':       goto yy2;
+                       default:        goto yy6;
+                       }
+yy2:
+                       ++YYCURSOR;
+                       switch((yych = *YYCURSOR)) {
+                       case '*':       goto yy12;
+                       case '/':       goto yy14;
+                       default:        goto yy3;
+                       }
+yy3:
+#line 107 "strip_002.s.re"
+                       { fputc(*s.tok, stdout); continue; }
+#line 112 "t.c"
+yy4:
+                       yych = *(YYMARKER = ++YYCURSOR);
+                       switch(yych){
+                       case 0x0A:      goto yy11;
+                       default:        goto yy3;
+                       }
+yy5:
+                       YYCTXMARKER = YYCURSOR + 1;
+                       yych = *(YYMARKER = ++YYCURSOR);
+                       switch(yych){
+                       case '/':       goto yy7;
+                       default:        goto yy3;
+                       }
+yy6:
+                       yych = *++YYCURSOR;
+                       goto yy3;
+yy7:
+                       yych = *++YYCURSOR;
+                       switch(yych){
+                       case '*':       goto yy9;
+                       default:        goto yy8;
+                       }
+yy8:
+                       YYCURSOR = YYMARKER;
+                       goto yy3;
+yy9:
+                       ++YYCURSOR;
+                       YYCURSOR = YYCTXMARKER;
+#line 105 "strip_002.s.re"
+                       { echo(&s); nlcomment = 1; continue; }
+#line 143 "t.c"
+yy11:
+                       YYCTXMARKER = YYCURSOR + 1;
+                       yych = *++YYCURSOR;
+                       switch(yych){
+                       case '/':       goto yy7;
+                       default:        goto yy8;
+                       }
+yy12:
+                       ++YYCURSOR;
+#line 106 "strip_002.s.re"
+                       { goto comment; }
+#line 155 "t.c"
+yy14:
+                       ++YYCURSOR;
+#line 104 "strip_002.s.re"
+                       { goto cppcomment; }
+#line 160 "t.c"
+               }
+#line 108 "strip_002.s.re"
+
+comment:
+               s.tok = s.cur;
+
+#line 167 "t.c"
+               {
+                       YYCTYPE yych;
+                       if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+                       yych = *YYCURSOR;
+                       switch(yych){
+                       case '*':       goto yy18;
+                       default:        goto yy20;
+                       }
+yy18:
+                       ++YYCURSOR;
+                       switch((yych = *YYCURSOR)) {
+                       case '/':       goto yy21;
+                       default:        goto yy19;
+                       }
+yy19:
+#line 113 "strip_002.s.re"
+                       { goto comment; }
+#line 185 "t.c"
+yy20:
+                       yych = *++YYCURSOR;
+                       goto yy19;
+yy21:
+                       ++YYCURSOR;
+#line 112 "strip_002.s.re"
+                       { goto commentws; }
+#line 193 "t.c"
+               }
+#line 114 "strip_002.s.re"
+
+commentws:
+               s.tok = s.cur;
+
+#line 200 "t.c"
+               {
+                       YYCTYPE yych;
+                       if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+                       yych = *YYCURSOR;
+                       switch(yych){
+                       case 0x09:
+                       case ' ':       goto yy31;
+                       case 0x0A:      goto yy27;
+                       case 0x0D:      goto yy25;
+                       case '/':       goto yy29;
+                       default:        goto yy32;
+                       }
+yy25:
+                       ++YYCURSOR;
+                       switch((yych = *YYCURSOR)) {
+                       case 0x0A:      goto yy37;
+                       default:        goto yy26;
+                       }
+yy26:
+#line 127 "strip_002.s.re"
+                       { goto commentws; }
+#line 222 "t.c"
+yy27:
+                       yych = *(YYMARKER = ++YYCURSOR);
+                       switch(yych){
+                       case '/':       goto yy35;
+                       default:        goto yy28;
+                       }
+yy28:
+#line 119 "strip_002.s.re"
+                       {
+                               if (!nlcomment)
+                               {
+                                       echo(&s);
+                               }
+                               nlcomment = 0;
+                               continue;
+                       }
+#line 239 "t.c"
+yy29:
+                       ++YYCURSOR;
+                       switch((yych = *YYCURSOR)) {
+                       case '*':       goto yy33;
+                       default:        goto yy30;
+                       }
+yy30:
+#line 128 "strip_002.s.re"
+                       { echo(&s); nlcomment = 0; continue; }
+#line 249 "t.c"
+yy31:
+                       yych = *++YYCURSOR;
+                       goto yy26;
+yy32:
+                       yych = *++YYCURSOR;
+                       goto yy30;
+yy33:
+                       ++YYCURSOR;
+#line 118 "strip_002.s.re"
+                       { nlcomment = 1; goto comment; }
+#line 260 "t.c"
+yy35:
+                       yych = *++YYCURSOR;
+                       switch(yych){
+                       case '*':       goto yy33;
+                       default:        goto yy36;
+                       }
+yy36:
+                       YYCURSOR = YYMARKER;
+                       goto yy28;
+yy37:
+                       yych = *(YYMARKER = ++YYCURSOR);
+                       switch(yych){
+                       case '/':       goto yy35;
+                       default:        goto yy28;
+                       }
+               }
+#line 129 "strip_002.s.re"
+
+cppcomment:
+               s.tok = s.cur;
+
+#line 282 "t.c"
+               {
+                       YYCTYPE yych;
+                       if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+                       yych = *YYCURSOR;
+                       switch(yych){
+                       case 0x0A:      goto yy42;
+                       case 0x0D:      goto yy40;
+                       default:        goto yy44;
+                       }
+yy40:
+                       ++YYCURSOR;
+                       switch((yych = *YYCURSOR)) {
+                       case 0x0A:      goto yy45;
+                       default:        goto yy41;
+                       }
+yy41:
+#line 134 "strip_002.s.re"
+                       { goto cppcomment; }
+#line 301 "t.c"
+yy42:
+                       ++YYCURSOR;
+yy43:
+#line 133 "strip_002.s.re"
+                       { echo(&s); continue; }
+#line 307 "t.c"
+yy44:
+                       yych = *++YYCURSOR;
+                       goto yy41;
+yy45:
+                       ++YYCURSOR;
+                       yych = *YYCURSOR;
+                       goto yy43;
+               }
+#line 135 "strip_002.s.re"
+
+       }
+
+       fflush(fp); // ensure we write
+       if (fp != stdin)
+       {
+               fclose(fp); // close only if not stdin
+       }
+       return res; // return result
+}
+
+/**/
+/**/
+/***/
+/***/
+/****/
+/****/
+/*****/
+/*****/
+/******/
+/******/
+
+int main(int argc, char **argv)
+{
+       if (argc > 1)
+       {
+               return scan(!strcmp(argv[1], "-") ? stdin : fopen(argv[1], "r"));
+       }
+       else
+       {
+               fprintf(stderr, "%s <expr>\n", argv[0]);
+               return 1;
+       }
+}