Rewrote the material taken from the changelog.
[ragel.git] / examples / pullscan.rl
blobf009dd29a42bb5173b6340913b4d50a386d40634
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
5 #define BUFSIZE 4096
7 typedef struct _Scanner {
8         /* Scanner state. */
9     int cs;
10     int act;
11     int have;
12     int curline;
13     char *ts;
14     char *te;
15     char *p;
16     char *pe;
17     char *eof;
18         FILE *file;
19         int done;
21         /* Token data */
22         char *data;
23         int len;
24     int value;
26         char buf[BUFSIZE];
27 } Scanner;
30 %%{
31         machine Scanner;
32         write data;
33 }%%
35 void scan_init( Scanner *s, FILE *file )
37         memset (s, '\0', sizeof(Scanner));
38         s->curline = 1;
39         s->file = file;
40         s->eof = 0;
41         %% write init;
44 #define TK_NO_TOKEN (-1)
45 #define TK_ERR 128
46 #define TK_EOF 129
47 #define TK_Identifier 130
48 #define TK_Number 131
49 #define TK_String 132
51 #define ret_tok( _tok ) token = _tok; s->data = s->ts
53 int scan( Scanner *s )
55         int token = TK_NO_TOKEN;
56         int space, readlen;
58         while ( 1 ) {
59                 if ( s->p == s->pe ) {
60                         printf("scanner: need more data\n");
62                         if ( s->ts == 0 )
63                                 s->have = 0;
64                         else {
65                                 /* There is data that needs to be shifted over. */
66                                 printf("scanner: buffer broken mid token\n");
67                                 s->have = s->pe - s->ts;
68                                 memmove( s->buf, s->ts, s->have );
69                                 s->te -= (s->ts-s->buf);
70                                 s->ts = s->buf;
71                         }
73                         s->p = s->buf + s->have;
74                         space = BUFSIZE - s->have;
76                         if ( space == 0 ) {
77                                 /* We filled up the buffer trying to scan a token. */
78                                 printf("scanner: out of buffer space\n");
79                                 return TK_ERR;
80                         }
82                         if ( s->done ) {
83                                 printf("scanner: end of file\n");
84                                 s->p[0] = 0;
85                                 readlen = 1;
86                         }
87                         else {
88                                 readlen = fread( s->p, 1, space, s->file );
89                                 if ( readlen < space )
90                                         s->done = 1;
91                         }
93                         s->pe = s->p + readlen;
94                 }
96                 %%{
97                         machine Scanner;
98                         access s->;
99                         variable p s->p;
100                         variable pe s->pe;
101                         variable eof s->eof;
103                         main := |*
105                         # Identifiers
106                         ( [a-zA-Z_] [a-zA-Z0-9_]* ) =>
107                                 { ret_tok( TK_Identifier ); fbreak; };
109                         # Whitespace
110                         [ \t\n];
112                         '"' ( [^\\"] | '\\' any ) * '"' =>
113                                 { ret_tok( TK_String ); fbreak; };
115                         # Number
116                         digit+ => 
117                                 { ret_tok( TK_Number ); fbreak; };
118                         
119                         # EOF
120                         0 =>
121                                 { ret_tok( TK_EOF ); fbreak; };
123                         # Anything else
124                         any => 
125                                 { ret_tok( *s->p ); fbreak; };
127                         *|;
129                         write exec;
130                 }%%
132                 if ( s->cs == Scanner_error )
133                         return TK_ERR;
135                 if ( token != TK_NO_TOKEN ) {
136                         /* Save p and pe. fbreak does not advance p. */
137                         s->len = s->p - s->data;
138                         return token;
139                 }
140         }
144 int main (int argc, char** argv)
146         Scanner ss;
147         int tok;
149         scan_init(&ss, stdin);
151         while ( 1 ) {
152                 tok = scan (&ss);
153                 if ( tok == TK_EOF ) {
154                         printf ("parser: EOF\n");
155                         break;
156                 }
157                 else if ( tok == TK_ERR ) {
158                         printf ("parser: ERR\n");
159                         break;
160                 }
161                 else {
162                         printf ("parser: %d \"", tok);
163                         fwrite ( ss.data, 1, ss.len, stdout );
164                         printf ("\"\n" );
165                 }
166         }
168         return 0;