Use @docdir@ for the docdir makefile variable.
[external/ragel.git] / examples / clang.rl
1 /*
2  * A mini C-like language scanner.
3  */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8
9 %%{
10         machine clang;
11
12         newline = '\n' @{curline += 1;};
13         any_count_line = any | newline;
14
15         # Consume a C comment.
16         c_comment := any_count_line* :>> '*/' @{fgoto main;};
17
18         main := |*
19
20         # Alpha numberic characters or underscore.
21         alnum_u = alnum | '_';
22
23         # Alpha charactres or underscore.
24         alpha_u = alpha | '_';
25
26         # Symbols. Upon entering clear the buffer. On all transitions
27         # buffer a character. Upon leaving dump the symbol.
28         ( punct - [_'"] ) {
29                 printf( "symbol(%i): %c\n", curline, ts[0] );
30         };
31
32         # Identifier. Upon entering clear the buffer. On all transitions
33         # buffer a character. Upon leaving, dump the identifier.
34         alpha_u alnum_u* {
35                 printf( "ident(%i): ", curline );
36                 fwrite( ts, 1, te-ts, stdout );
37                 printf("\n");
38         };
39
40         # Single Quote.
41         sliteralChar = [^'\\] | newline | ( '\\' . any_count_line );
42         '\'' . sliteralChar* . '\'' {
43                 printf( "single_lit(%i): ", curline );
44                 fwrite( ts, 1, te-ts, stdout );
45                 printf("\n");
46         };
47
48         # Double Quote.
49         dliteralChar = [^"\\] | newline | ( '\\' any_count_line );
50         '"' . dliteralChar* . '"' {
51                 printf( "double_lit(%i): ", curline );
52                 fwrite( ts, 1, te-ts, stdout );
53                 printf("\n");
54         };
55
56         # Whitespace is standard ws, newlines and control codes.
57         any_count_line - 0x21..0x7e;
58
59         # Describe both c style comments and c++ style comments. The
60         # priority bump on tne terminator of the comments brings us
61         # out of the extend* which matches everything.
62         '//' [^\n]* newline;
63
64         '/*' { fgoto c_comment; };
65
66         # Match an integer. We don't bother clearing the buf or filling it.
67         # The float machine overlaps with int and it will do it.
68         digit+ {
69                 printf( "int(%i): ", curline );
70                 fwrite( ts, 1, te-ts, stdout );
71                 printf("\n");
72         };
73
74         # Match a float. Upon entering the machine clear the buf, buffer
75         # characters on every trans and dump the float upon leaving.
76         digit+ '.' digit+ {
77                 printf( "float(%i): ", curline );
78                 fwrite( ts, 1, te-ts, stdout );
79                 printf("\n");
80         };
81
82         # Match a hex. Upon entering the hex part, clear the buf, buffer characters
83         # on every trans and dump the hex on leaving transitions.
84         '0x' xdigit+ {
85                 printf( "hex(%i): ", curline );
86                 fwrite( ts, 1, te-ts, stdout );
87                 printf("\n");
88         };
89
90         *|;
91 }%%
92
93 %% write data nofinal;
94
95 #define BUFSIZE 128
96
97 void scanner()
98 {
99         static char buf[BUFSIZE];
100         int cs, act, have = 0, curline = 1;
101         char *ts, *te = 0;
102         int done = 0;
103
104         %% write init;
105
106         while ( !done ) {
107                 char *p = buf + have, *pe, *eof = 0;
108                 int len, space = BUFSIZE - have;
109                 
110                 if ( space == 0 ) {
111                         /* We've used up the entire buffer storing an already-parsed token
112                          * prefix that must be preserved. */
113                         fprintf(stderr, "OUT OF BUFFER SPACE\n" );
114                         exit(1);
115                 }
116
117                 len = fread( p, 1, space, stdin );
118                 pe = p + len;
119
120                 /* Check if this is the end of file. */
121                 if ( len < space ) {
122                         eof = pe;
123                         done = 1;
124                 }
125                         
126                 %% write exec;
127
128                 if ( cs == clang_error ) {
129                         fprintf(stderr, "PARSE ERROR\n" );
130                         break;
131                 }
132
133                 if ( ts == 0 )
134                         have = 0;
135                 else {
136                         /* There is a prefix to preserve, shift it over. */
137                         have = pe - ts;
138                         memmove( buf, ts, have );
139                         te = buf + (te-ts);
140                         ts = buf;
141                 }
142         }
143 }
144
145 int main()
146 {
147         scanner();
148         return 0;
149 }
150