Fixed a problem reading hex numbers that have the high bit set when the
[external/ragel.git] / test / clang2.rl
1 /*
2  * @LANG: obj-c
3  * A mini C-like language scanner.
4  */
5
6 #include <stdio.h>
7 #include <objc/Object.h>
8 #include <string.h>
9
10 #define IDENT_BUFLEN 256
11
12 @interface Clang : Object
13 {
14 @public 
15         /* State machine operation data. */
16         int cs;
17
18         /* Parsing data. */
19         char identBuf[IDENT_BUFLEN+1];
20         int identLen;
21         int curLine;
22 };
23
24 - (void) initFsm;
25 - (void) executeWithData:(const char *)data len:(int)len;
26 - (int) finish;
27
28 @end
29
30 %%{ 
31         machine Clang;
32
33         # Function to buffer a character.
34         action bufChar {
35                 if ( identLen < IDENT_BUFLEN ) {
36                         identBuf[identLen] = fc;
37                         identLen += 1;
38                 }
39         }
40
41         # Function to clear the buffer.
42         action clearBuf {
43                 identLen = 0;
44         }
45
46         # Functions to dump tokens as they are matched.
47         action ident {
48                 identBuf[identLen] = 0;
49                 printf("ident(%i): %s\n", curLine, identBuf);
50         }
51         action literal {
52                 identBuf[identLen] = 0;
53                 printf("literal(%i): %s\n", curLine, identBuf);
54         }
55         action float {
56                 identBuf[identLen] = 0;
57                 printf("float(%i): %s\n", curLine, identBuf);
58         }
59         action int {
60                 identBuf[identLen] = 0;
61                 printf("int(%i): %s\n", curLine, identBuf);
62         }
63         action hex {
64                 identBuf[identLen] = 0;
65                 printf("hex(%i): 0x%s\n", curLine, identBuf);
66         }
67         action symbol {
68                 identBuf[identLen] = 0;
69                 printf("symbol(%i): %s\n", curLine, identBuf);
70         }
71
72         # Alpha numberic characters or underscore.
73         alnumu = alnum | '_';
74
75         # Alpha charactres or underscore.
76         alphau = alpha | '_';
77
78         # Symbols. Upon entering clear the buffer. On all transitions
79         # buffer a character. Upon leaving dump the symbol.
80         symbol = ( punct - [_'"] ) >clearBuf $bufChar %symbol;
81
82         # Identifier. Upon entering clear the buffer. On all transitions
83         # buffer a character. Upon leaving, dump the identifier.
84         ident = (alphau . alnumu*) >clearBuf $bufChar %ident;
85
86         # Match single characters inside literal strings. Or match 
87         # an escape sequence. Buffers the charater matched.
88         sliteralChar =
89                         ( extend - ['\\] ) @bufChar |
90                         ( '\\' . extend @bufChar );
91         dliteralChar =
92                         ( extend - ["\\] ) @bufChar |
93                         ( '\\' . extend @bufChar );
94
95         # Single quote and double quota literals. At the start clear
96         # the buffer. Upon leaving dump the literal.
97         sliteral = ('\'' @clearBuf . sliteralChar* . '\'' ) %literal;
98         dliteral = ('"' @clearBuf . dliteralChar* . '"' ) %literal;
99         literal = sliteral | dliteral;
100
101         # Whitespace is standard ws, newlines and control codes.
102         whitespace = any - 0x21..0x7e;
103
104         # Describe both c style comments and c++ style comments. The
105         # priority bump on tne terminator of the comments brings us
106         # out of the extend* which matches everything.
107         ccComment = '//' . extend* $0 . '\n' @1;
108         cComment = '/*' . extend* $0 . '*/' @1;
109
110         # Match an integer. We don't bother clearing the buf or filling it.
111         # The float machine overlaps with int and it will do it.
112         int = digit+ %int;
113
114         # Match a float. Upon entering the machine clear the buf, buffer
115         # characters on every trans and dump the float upon leaving.
116         float =  ( digit+ . '.' . digit+ ) >clearBuf $bufChar %float;
117
118         # Match a hex. Upon entering the hex part, clear the buf, buffer characters
119         # on every trans and dump the hex on leaving transitions.
120         hex = '0x' . xdigit+ >clearBuf $bufChar %hex;
121
122         # Or together all the lanuage elements.
123         fin = ( ccComment |
124                 cComment |
125                 symbol |
126                 ident |
127                 literal |
128                 whitespace |
129                 int |
130                 float |
131                 hex );
132
133         # Star the language elements. It is critical in this type of application
134         # that we decrease the priority of out transitions before doing so. This
135         # is so that when we see 'aa' we stay in the fin machine to match an ident
136         # of length two and not wrap around to the front to match two idents of 
137         # length one.
138         clang_main = ( fin $1 %0 )*;
139
140         # This machine matches everything, taking note of newlines.
141         newline = ( any | '\n' @{ curLine += 1; } )*;
142
143         # The final fsm is the lexer intersected with the newline machine which
144         # will count lines for us. Since the newline machine accepts everything,
145         # the strings accepted is goverened by the clang_main machine, onto which
146         # the newline machine overlays line counting.
147         main := clang_main & newline;
148 }%%
149
150 @implementation Clang
151
152 %% write data;
153
154 - (void) initFsm;
155 {
156         identLen = 0;
157         curLine = 1;
158         %% write init;
159 }
160
161 - (void) executeWithData:(const char *)data len:(int)len;
162 {
163         const char *p = data; 
164         const char *pe = data + len;
165         const char *eof = pe;
166
167         %% write exec;
168 }
169
170 - (int) finish;
171 {
172         if ( cs == Clang_error ) 
173                 return -1;
174         if ( cs >= Clang_first_final ) 
175                 return 1;
176         return 0;
177 }
178
179 @end
180
181 #define BUFSIZE 2048
182
183 Clang *fsm;
184 char buf[BUFSIZE];
185
186 void test( char *buf )
187 {
188         int len = strlen(buf);
189         fsm = [[Clang alloc] init];
190         [fsm initFsm];
191         [fsm executeWithData:buf len:len];
192         if ( [fsm finish] > 0 )
193                 printf("ACCEPT\n");
194         else
195                 printf("FAIL\n");
196 }
197
198 int main()
199 {
200         test( 
201                 "999 0xaAFF99 99.99 /*\n"
202                 "*/ 'lksdj' //\n"
203                 "\"\n"
204                 "\n"
205                 "literal\n"
206                 "\n"
207                 "\n"
208                 "\"0x00aba foobardd.ddsf 0x0.9\n" );
209
210         test( 
211                 "wordwithnum00asdf\n"
212                 "000wordfollowsnum,makes new symbol\n"
213                 "\n"
214                 "finishing early /* unfinished ...\n" );
215
216         test( 
217                 "/*\n"
218                 " *  Copyright\n"
219                 " */\n"
220                 "\n"
221                 "/*  Aapl.\n"
222                 " */\n"
223                 "\f\n"
224                 "#define _AAPL_RESIZE_H\n"
225                 "\n"
226                 "#include <assert.h>\n"
227                 "\n"
228                 "#ifdef AAPL_NAMESPACE\n"
229                 "namespace Aapl {\n"
230                 "#endif\n"
231                 "#define LIN_DEFAULT_STEP 256\n"
232                 "#define EXPN_UP( existing, needed ) \\\n"
233                 "               need > eng ? (ned<<1) : eing\n"
234                 "       \n"
235                 "\n"
236                 "/*@}*/\n"
237                 "#undef EXPN_UP\n"
238                 "#ifdef AAPL_NAMESPACE\n"
239                 "#endif /* _AAPL_RESIZE_H */\n" );
240         return 0;
241 }
242
243 #ifdef _____OUTPUT_____
244 int(1): 999
245 hex(1): 0xaAFF99
246 float(1): 99.99
247 literal(2): lksdj
248 literal(8): 
249
250 literal
251
252
253
254 hex(8): 0x00aba
255 ident(8): foobardd
256 symbol(8): .
257 ident(8): ddsf
258 hex(8): 0x0
259 symbol(8): .
260 int(8): 9
261 ACCEPT
262 ident(1): wordwithnum00asdf
263 int(2): 000
264 ident(2): wordfollowsnum
265 symbol(2): ,
266 ident(2): makes
267 ident(2): new
268 ident(2): symbol
269 ident(4): finishing
270 ident(4): early
271 FAIL
272 symbol(8): #
273 ident(8): define
274 ident(8): _AAPL_RESIZE_H
275 symbol(10): #
276 ident(10): include
277 symbol(10): <
278 ident(10): assert
279 symbol(10): .
280 ident(10): h
281 symbol(10): >
282 symbol(12): #
283 ident(12): ifdef
284 ident(12): AAPL_NAMESPACE
285 ident(13): namespace
286 ident(13): Aapl
287 symbol(13): {
288 symbol(14): #
289 ident(14): endif
290 symbol(15): #
291 ident(15): define
292 ident(15): LIN_DEFAULT_STEP
293 int(15): 256
294 symbol(16): #
295 ident(16): define
296 ident(16): EXPN_UP
297 symbol(16): (
298 ident(16): existing
299 symbol(16): ,
300 ident(16): needed
301 symbol(16): )
302 symbol(16): \
303 ident(17): need
304 symbol(17): >
305 ident(17): eng
306 symbol(17): ?
307 symbol(17): (
308 ident(17): ned
309 symbol(17): <
310 symbol(17): <
311 int(17): 1
312 symbol(17): )
313 symbol(17): :
314 ident(17): eing
315 symbol(21): #
316 ident(21): undef
317 ident(21): EXPN_UP
318 symbol(22): #
319 ident(22): ifdef
320 ident(22): AAPL_NAMESPACE
321 symbol(23): #
322 ident(23): endif
323 ACCEPT
324 #endif