Initialize Tizen 2.3
[external/ragel.git] / examples / cppscan.rl
1 /*
2  * A C++ scanner. Uses the longest match construction.
3  * << <= <<= >> >= >>= are left out since angle brackets are used in templates.
4  */
5
6 #include <string.h>
7 #include <stdlib.h>
8 #include <iostream>
9
10 #define TK_Dlit 256
11 #define TK_Slit 257
12 #define TK_Float 258
13 #define TK_Id 259
14 #define TK_NameSep 260
15 #define TK_Arrow 261
16 #define TK_PlusPlus 262
17 #define TK_MinusMinus 263
18 #define TK_ArrowStar 264
19 #define TK_DotStar 265
20 #define TK_ShiftLeft 266
21 #define TK_ShiftRight 267
22 #define TK_IntegerDecimal 268
23 #define TK_IntegerOctal 269
24 #define TK_IntegerHex 270
25 #define TK_EqualsEquals 271
26 #define TK_NotEquals 272
27 #define TK_AndAnd 273
28 #define TK_OrOr 274
29 #define TK_MultAssign 275
30 #define TK_DivAssign 276
31 #define TK_PercentAssign 277
32 #define TK_PlusAssign 278
33 #define TK_MinusAssign 279
34 #define TK_AmpAssign 280
35 #define TK_CaretAssign 281
36 #define TK_BarAssign 282
37 #define TK_DotDotDot 283
38 #define TK_Whitespace 284
39 #define TK_Comment 285
40
41 #define BUFSIZE 16384
42
43 /* EOF char used to flush out that last token. This should be a whitespace
44  * token. */
45
46 #define LAST_CHAR 0
47
48 using std::cerr;
49 using std::cout;
50 using std::cin;
51 using std::endl;
52
53 static char buf[BUFSIZE];
54 static int line = 1, col = 1;
55 static char *ts, *te;
56 static int act, have = 0;
57 static int cs;
58
59 %%{
60         machine Scanner; 
61         write data nofinal;
62
63         # Floating literals.
64         fract_const = digit* '.' digit+ | digit+ '.';
65         exponent = [eE] [+\-]? digit+;
66         float_suffix = [flFL];
67
68         c_comment := 
69                 any* :>> '*/'
70                 @{ fgoto main; };
71
72         main := |*
73
74         # Single and double literals.
75         ( 'L'? "'" ( [^'\\\n] | /\\./ )* "'" ) 
76                 {token( TK_Slit );};
77         ( 'L'? '"' ( [^"\\\n] | /\\./ )* '"' ) 
78                 {token( TK_Dlit );};
79
80         # Identifiers
81         ( [a-zA-Z_] [a-zA-Z0-9_]* ) 
82                 {token( TK_Id );};
83
84         # Floating literals.
85         ( fract_const exponent? float_suffix? | digit+ exponent float_suffix? ) 
86                 {token( TK_Float );};
87         
88         # Integer decimal. Leading part buffered by float.
89         ( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} ) 
90                 {token( TK_IntegerDecimal );};
91
92         # Integer octal. Leading part buffered by float.
93         ( '0' [0-9]+ [ulUL]{0,2} ) 
94                 {token( TK_IntegerOctal );};
95
96         # Integer hex. Leading 0 buffered by float.
97         ( '0' ( 'x' [0-9a-fA-F]+ [ulUL]{0,2} ) ) 
98                 {token( TK_IntegerHex );};
99
100         # Only buffer the second item, first buffered by symbol. */
101         '::' {token( TK_NameSep );};
102         '==' {token( TK_EqualsEquals );};
103         '!=' {token( TK_NotEquals );};
104         '&&' {token( TK_AndAnd );};
105         '||' {token( TK_OrOr );};
106         '*=' {token( TK_MultAssign );};
107         '/=' {token( TK_DivAssign );};
108         '%=' {token( TK_PercentAssign );};
109         '+=' {token( TK_PlusAssign );};
110         '-=' {token( TK_MinusAssign );};
111         '&=' {token( TK_AmpAssign );};
112         '^=' {token( TK_CaretAssign );};
113         '|=' {token( TK_BarAssign );};
114         '++' {token( TK_PlusPlus );};
115         '--' {token( TK_MinusMinus );};
116         '->' {token( TK_Arrow );};
117         '->*' {token( TK_ArrowStar );};
118         '.*' {token( TK_DotStar );};
119
120         # Three char compounds, first item already buffered. */
121         '...' {token( TK_DotDotDot );};
122
123         # Single char symbols.
124         ( punct - [_"'] ) {token( ts[0] );};
125
126         # Comments and whitespace.
127         '/*' { fgoto c_comment; };
128         '//' [^\n]* '\n';
129         ( any - 33..126 )+;
130
131         *|;
132 }%%
133
134 void token( int tok )
135 {
136         char *data = ts;
137         int len = te - ts;
138
139         cout << '<' << tok << "> ";
140         cout.write( data, len );
141         cout << '\n';
142         
143         /* Count newlines and columns. This code is here mainly for having some
144          * code in the token routine when commenting out the above output during
145          * performance testing. */
146         for ( int i = 0; i < len; i ++ ) {
147                 if ( data[i] == '\n' ) {
148                         line += 1;
149                         col = 1;
150                 }
151                 else {
152                         col += 1;
153                 }
154         }
155 }
156
157 int main()
158 {
159         std::ios::sync_with_stdio(false);
160
161         %% write init;
162
163         /* Do the first read. */
164         bool done = false;
165         while ( !done ) {
166                 char *p = buf + have;
167                 int space = BUFSIZE - have;
168
169                 if ( space == 0 ) {
170                         /* We filled up the buffer trying to scan a token. */
171                         cerr << "OUT OF BUFFER SPACE" << endl;
172                         exit(1);
173                 }
174
175                 cin.read( p, space );
176                 int len = cin.gcount();
177                 char *pe = p + len;
178                 char *eof = 0;
179
180                 /* If we see eof then append the EOF char. */
181                 if ( cin.eof() ) {
182                         eof = pe;
183                         done = true;
184                 }
185
186                 %% write exec;
187
188                 /* Check if we failed. */
189                 if ( cs == Scanner_error ) {
190                         /* Machine failed before finding a token. */
191                         cerr << "PARSE ERROR" << endl;
192                         exit(1);
193                 }
194
195                 /* Now set up the prefix. */
196                 if ( ts == 0 )
197                         have = 0;
198                 else {
199                         /* There is data that needs to be shifted over. */
200                         have = pe - ts;
201                         memmove( buf, ts, have );
202                         te -= (ts-buf);
203                         ts = buf;
204                 }
205         }
206
207         return 0;
208 }