Include the offset of p in the test.
[external/ragel.git] / test / cppscan3.rl
1 /*
2  * @LANG: c++
3  */
4
5 #include <iostream>
6 #include <string.h>
7 using namespace std;
8
9 #define TK_Dlit 192
10 #define TK_Slit 193
11 #define TK_Float 194
12 #define TK_Id 195
13 #define TK_NameSep 197
14 #define TK_Arrow 211
15 #define TK_PlusPlus 212
16 #define TK_MinusMinus 213
17 #define TK_ArrowStar 214
18 #define TK_DotStar 215
19 #define TK_ShiftLeft 216
20 #define TK_ShiftRight 217
21 #define TK_IntegerDecimal 218
22 #define TK_IntegerOctal 219
23 #define TK_IntegerHex 220
24 #define TK_EqualsEquals 223
25 #define TK_NotEquals 224
26 #define TK_AndAnd 225
27 #define TK_OrOr 226
28 #define TK_MultAssign 227
29 #define TK_DivAssign 228
30 #define TK_PercentAssign 229
31 #define TK_PlusAssign 230
32 #define TK_MinusAssign 231
33 #define TK_AmpAssign 232
34 #define TK_CaretAssign 233
35 #define TK_BarAssign 234
36 #define TK_DotDotDot 240
37 #define TK_Whitespace 241
38 #define TK_Comment 242
39
40 #define BUFSIZE 4096
41
42 char buf[BUFSIZE];
43
44 struct Scanner
45 {
46         int cs, act;
47         char *tokstart, *tokend;
48
49         void token( int tok );
50         void run();
51
52         void init( );
53         void execute( char *data, int len );
54         int finish( );
55 };
56
57 %%{
58         machine Scanner;
59
60         main := |*
61
62         # Single and double literals.
63         ( 'L'? "'" ( [^'\\\n] | /\\./ )* "'" ) 
64                 => { token( TK_Slit );};
65         ( 'L'? '"' ( [^"\\\n] | /\\./ )* '"' ) 
66                 => { token( TK_Dlit );};
67
68         # Identifiers
69         ( [a-zA-Z_] [a-zA-Z0-9_]* ) 
70                 =>{ token( TK_Id );};
71
72         # Floating literals.
73         fract_const = digit* '.' digit+ | digit+ '.';
74         exponent = [eE] [+\-]? digit+;
75         float_suffix = [flFL];
76
77         ( fract_const exponent? float_suffix? |
78                 digit+ exponent float_suffix? ) 
79                 => { token( TK_Float );};
80         
81         # Integer decimal. Leading part buffered by float.
82         ( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} ) 
83                 => { token( TK_IntegerDecimal );};
84
85         # Integer octal. Leading part buffered by float.
86         ( '0' [0-9]+ [ulUL]{0,2} ) 
87                 => { token( TK_IntegerOctal );};
88
89         # Integer hex. Leading 0 buffered by float.
90         ( '0' ( 'x' [0-9a-fA-F]+ [ulUL]{0,2} ) ) 
91                 => { token( TK_IntegerHex );};
92
93         # Only buffer the second item, first buffered by symbol. */
94         '::' => {token( TK_NameSep );};
95         '==' => {token( TK_EqualsEquals );};
96         '!=' => {token( TK_NotEquals );};
97         '&&' => {token( TK_AndAnd );};
98         '||' => {token( TK_OrOr );};
99         '*=' => {token( TK_MultAssign );};
100         '/=' => {token( TK_DivAssign );};
101         '%=' => {token( TK_PercentAssign );};
102         '+=' => {token( TK_PlusAssign );};
103         '-=' => {token( TK_MinusAssign );};
104         '&=' => {token( TK_AmpAssign );};
105         '^=' => {token( TK_CaretAssign );};
106         '|=' => {token( TK_BarAssign );};
107         '++' => {token( TK_PlusPlus );};
108         '--' => {token( TK_MinusMinus );};
109         '->' => {token( TK_Arrow );};
110         '->*' => {token( TK_ArrowStar );};
111         '.*' => {token( TK_DotStar );};
112
113         # Three char compounds, first item already buffered. */
114         '...' => { token( TK_DotDotDot );};
115
116         # Single char symbols.
117         ( punct - [_"'] ) => { token( tokstart[0] );};
118
119         action comment {
120                 token( TK_Comment );
121         }
122
123         # Comments and whitespace.
124         '/*' ( any* $0 '*/' @1 ) => comment;
125         '//' ( any* $0 '\n' @1 ) => comment;
126         ( any - 33..126 )+ => { token( TK_Whitespace );};
127
128         *|;
129 }%%
130
131 %% write data;
132
133 void Scanner::init( )
134 {
135         %% write init;
136 }
137
138 /* Returns the count of bytes still in the buffer 
139  * (shifted to the biginning) */
140 void Scanner::execute( char *data, int len )
141 {
142         char *p = data;
143         char *pe = data + len;
144
145         %% write exec;
146
147         cout << "P: " << (p - data) << endl;
148 }
149
150 int Scanner::finish( )
151 {
152         %% write eof;
153         if ( cs == Scanner_error )
154                 return -1;
155         if ( cs >= Scanner_first_final )
156                 return 1;
157         return 0;
158 }
159
160
161 void Scanner::token( int tok )
162 {
163         const char *data = tokstart;
164         int len = tokend - tokstart;
165         cout << "<" << tok << "> ";
166         for ( int i = 0; i < len; i++ )
167                 cout << data[i];
168         cout << '\n';
169 }
170
171 void test( char *buf )
172 {
173         int len = strlen( buf );
174         std::ios::sync_with_stdio(false);
175         Scanner scanner;
176         scanner.init();
177
178         scanner.execute( buf, len );
179         if ( scanner.cs == Scanner_error ) {
180                 /* Machine failed before finding a token. */
181                 cout << "PARSE ERROR" << endl;
182         }
183
184         /* FIXME: Last token may get lost. */
185         scanner.finish();
186 }
187
188 int main()
189 {
190         test(
191                 "\"\\\"hi\" /*\n"
192                 "*/\n"
193                 "44 .44\n"
194                 "44. 44\n"
195                 "44 . 44\n"
196                 "44.44\n"
197                 "_hithere22\n"
198                 "\n"
199         );
200
201         test(
202                 "'\\''\"\\n\\d'\\\"\"\n"
203                 "hi\n"
204                 "99\n"
205                 ".99\n"
206                 "99e-4\n"
207                 "->*\n"
208                 "||\n"
209                 "0x98\n"
210                 "0x\n"
211                 "//\n"
212                 "/* * */\n"
213         );
214
215         test(
216                 "'\n"
217                 "'\n"
218         );
219
220 }
221
222 #ifdef _____OUTPUT_____
223 <192> "\"hi"
224 <241>  
225 <242> /*
226 */
227 <241> 
228
229 <218> 44
230 <241>  
231 <194> .44
232 <241> 
233
234 <194> 44.
235 <241>  
236 <218> 44
237 <241> 
238
239 <218> 44
240 <241>  
241 <46> .
242 <241>  
243 <218> 44
244 <241> 
245
246 <194> 44.44
247 <241> 
248
249 <195> _hithere22
250 P: 53
251 <193> '\''
252 <192> "\n\d'\""
253 <241> 
254
255 <195> hi
256 <241> 
257
258 <218> 99
259 <241> 
260
261 <194> .99
262 <241> 
263
264 <194> 99e-4
265 <241> 
266
267 <214> ->*
268 <241> 
269
270 <226> ||
271 <241> 
272
273 <220> 0x98
274 <241> 
275
276 <218> 0
277 <195> x
278 <241> 
279
280 <242> //
281
282 <242> /* * */
283 P: 56
284 P: 1
285 PARSE ERROR
286 #endif