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