fixes
[henge/apc.git] / src / lexer.rl
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include "parser.tab.h"
6 #include "apc.h"
7 #include <unistdio.h>
8 #include <unistr.h>
9 extern //lexer.c
10 void lexer_pushtok(int, YYSTYPE);
11 /* Public */
12 int lexer_setdirection(uint8_t*, int);
13 int lexer_lexfile(const uint8_t*);
14 int lexer_lexstring(const uint8_t*, int);
15 int lexer_setstr(uint8_t*, int);
16 //apc.c
17 extern
18 yypstate* apc_pstate;
19 extern
20 yycstate* apc_cstate;
21 #define PUSHTOK(T,L) yypush_parse(apc_pstate, T, (YYSTYPE*)(L), apc_cstate)
22 #define LEXTOK(T,L) do { \
23 PUSHTOK(T,L); \
24 ntok++; \
25 } while (0);
26 #define LEXFACE(F) do { \
27 lval.face = F; \
28 LEXTOK(FACING, &lval.face); \
29 } while (0);
30
31 /* Lexstring is the main lexer for APC and is generated by ragel. It lexes file names of files
32 that have been scanned and pushes their types and values into the tok_stack, which yyparse
33 eventually calls during parsing. */
34
35 %%{
36 machine lexstring;
37
38 # set up yylval and tok_t to be pushed to stack
39 action push_ref { te = NULL; errno = 0;
40 lval.ref = strtoll((char*)ts,(char**)&te,16);
41 if (errno | (te != NULL))
42 { fprintf(stderr, "Invalid hex number in file %s\n",(char*)str);
43 if (te != NULL)
44 { while (str++ < te)
45 fputc(' ', stderr);
46 fputc('^', stderr);
47 }
48 exit(1);
49 }
50 LEXTOK(REF, &lval.ref);
51 }
52 action push_link { lval.val = 0;
53 PUSHTOK(LINK, &lval.val); }
54 action push_val { te = NULL; errno = 0;
55 lval.val = strtoll((char*)ts,(char**)&te,10);
56 if (errno)
57 { fprintf(stderr, "strtoll could not parse %s\n", (char*)str);
58 exit(1);
59 }
60 LEXTOK(NUM, &lval.val);
61 }
62 action push_name { printf("Lexer_lexstring:: action:push_name: from %s to %s\n", ts, p);
63 LEXTOK(NAME, ts);
64 }
65 action push_map { printf("Lexer_lexstring:: action:push_map: pushing map token\n");
66 LEXTOK(MAP, "~");
67 }
68 action set_ts { printf("Lexer_lexstring:: action:set_ts. ts = %s\n", p); ts = p; }
69 action push_SS { printf("Lexer_lexstring:: action:push_SS. p = %s\n",p);
70 LEXTOK(SS, "SS");
71 }
72 action push_S { printf("Lexer_lexstring:: action:push_S. p = %s\n", p);
73 LEXFACE(SFACE);
74 }
75 action push_SW { printf("Lexer_lexstring:: action:push_SW. p = %s\n", p);
76 LEXFACE(SWFACE);
77 }
78 action push_W { printf("Lexer_lexstring:: action:push_W. p = %s\n", p);
79 LEXFACE(WFACE);
80 }
81 action push_NW { printf("Lexer_lexstring:: action:push_NW. p = %s\n", p);
82 LEXFACE(NWFACE);
83 }
84 action push_N { printf("Lexer_lexstring:: action:push_N. p = %s\n", p);
85 LEXFACE(NFACE);
86 }
87 action push_NE { printf("Lexer_lexstring:: action:push_NE. p = %s\n", p);
88 LEXFACE(NEFACE);
89 }
90 action push_E { printf("Lexer_lexstring:: action:push_N. p = %s\n", p);
91 LEXFACE(EFACE);
92 }
93 action push_SE { printf("Lexer_lexstring:: action:push_N. p = %s\n", p);
94 LEXFACE(SEFACE);
95 }
96 action ref_error { printf("ref from %s to %s has an inappropriate amount of hex digits, it must have eight.\n", ts, p);
97 exit(1);
98 }
99 action p { printf("Lexer_lexstring:: p = %s\n", p);}
100
101 N = 'N' %push_N;
102 W = 'W' %push_W;
103 S = 'S' %push_S;
104 E = 'E' %push_E;
105 NW = 'NW' %push_NW;
106 NE = 'NE' %push_NW;
107 SW = 'SW' %push_SW;
108 SE = 'SE' %push_SE;
109
110 tok_delimiter = [_];
111
112 direction = (N | W | S | E | NW | NE | SW | SE) ;
113 dimensions = (digit+ - '0') >set_ts %push_val 'x' (digit+ - '0') >set_ts %push_val;
114 link = '#' %push_link;
115 SS = ('+SS' %to(push_SS)) | ('+SS' %to(push_SS) link ) ;
116 ref = '0x' >set_ts alnum{8} $err(ref_error) %push_ref ;
117 val = digit+ >set_ts %push_val ;
118 name = (lower+ >set_ts) %push_name ;
119 map = '+MAP' %to(push_map);
120 tok = (name | val | ref | dimensions | map | link | SS | direction);
121
122
123 main := (tok tok_delimiter)+ tok [\0];
124
125 write data nofinal noerror noprefix;
126
127 }%%
128
129 int lexer_lexstring
130 ( const uint8_t* str,
131 int size
132 )
133 { const uint8_t *p;
134 const uint8_t *ts, *pe, *te, *eof;
135 int cs, ntok;
136 YYSTYPE lval;
137
138 ntok = 0;
139 p = ts = str;
140 pe = eof = p + size + 1;
141
142
143 printf("|---Begin lexstring on p = %s, pe = %s.\n",p, pe);
144
145 %%write init;
146 %%write exec;
147
148 printf("Ending lexstring of file %s, pushed %d tokens.\n",str, ntok);
149
150 return ntok;
151 }
152
153 /* Lexical analysis of a file
154 Strips a filename to its base name, then sends it to lexer_lexstring before
155 pushing a PATH token with the filename
156 Returns the number of tokens pushed to the parser.
157 */
158 int lexer_lexfile
159 ( uint8_t const* filename )
160 { uint8_t const* last_period,* iter;
161 int ntok;
162 last_period = NULL;
163 for (iter = filename; *iter; iter++)
164 if (*iter == '.')
165 last_period = iter;
166 ntok = (last_period) ?
167 lexer_lexstring(filename, (int)(last_period - filename))
168 : lexer_lexstring(filename, (int)(iter - filename));
169 PUSHTOK(PATH,&filename);
170 return ntok + 1;
171 return en_main == 1;
172 }
173
174 /**************************/
175 /****Abandon All Hope******/
176 /**************************/
177 /*** ***/
178 /*** ***/
179 /*** ***/
180 /*** ***/
181
182
183 #if 0
184
185 %%{
186 machine setdirection;
187
188 action ret_north {printf("Lexer_setdirection:: direction is north, returning 4\n"); return 4;; }
189 action ret_west { printf("Lexer_setdirection:: direction is west, returning 2\n");return 2;}
190 action ret_east { printf("Lexer_setdirection:: direction is east, returning 6\n");return 6;}
191 action ret_south { printf("Lexer_setdirection:: direction is south, returning 0\n");return 0;}
192 action ret_northeast { printf("Lexer_setdirection:: direction is northeast, returning 5\n");return 5 ;}
193 action ret_northwest { printf("Lexer_setdirection:: direction is northwest, returning 3\n");return 3;}
194 action ret_southeast { printf("Lexer_setdirection:: direction is southeast, returning 7\n");return 7;}
195 action ret_southwest { printf("Lexer_setdirection:: direction is southwest, returning 1\n");return 1;}
196
197 def = [_\0] %to(ret_south);
198 N = 'N'[_\0] %to(ret_north);
199 W = 'W' [_\0] %to(ret_west);
200 S = 'S' [_\0] %to(ret_south);
201 E = 'E' [_\0] %to(ret_east);
202 NW = 'NW' [_\0] %to(ret_northwest);
203 NE = 'NE' [_\0] %to(ret_northeast);
204 SW = 'SW' [_\0] %to(ret_southwest);
205 SE = 'SE' [_\0] %to(ret_southeast);
206
207 direction = (N | W | S | E | NW | NE | SW | SE | def);
208
209 main := direction;
210
211 write data nofinal noprefix noerror;
212
213
214 }%%
215
216
217 int
218 lexer_setdirection
219 (uint8_t* str, int size)
220 { uint8_t *p, *pe, *eof;
221 int cs;
222
223
224 p = str;
225 pe = str + size + 1;
226
227 printf("|--- Begin lexer_setdirection str = %s, p = %s, pe = %s ---|\n", str,p, pe);
228
229 %%write init;
230 %%write exec noend;
231
232 printf("|--- Error in: lexer_setdirection ---|\n");
233
234 return -1;
235 }
236
237
238
239 %%{
240 machine setstr;
241
242
243 action lex_setvlink {printf("Lexer_setstr:: Returning setvlink filetype for %s\n", str); type = 5; newstrt = lexer_lexsetvlink(str); fbreak;}
244 action lex_elevlink {printf("Lexer_setstr:: Returning elevlink filetype for %s\n", str); type = 6; newstrt = lexer_lexelevlink(str); fbreak;}
245 action lex_setmodel {printf("Lexer_setstr:: Returning setmodel filetype\n"); newstrt = lexer_lexsetmodel(str); type = 1; fbreak;}
246 action lex_setmap {printf("Lexer_setstr:: Returning setmap filetype\n"); newstrt = lexer_lexsetmap(str); type = 2; fbreak;}
247 action lex_elemodel {printf("Lexer_setstr:: Returning elemodel filetype for %s\n", str); newstrt = lexer_lexelemodel(str); type = 3; fbreak;}
248 action lex_elemap {printf("Lexer_setstr:: Returning elemap filetype for %s\n", str); newstrt = lexer_lexelemap(str); type = 4; fbreak;}
249 action lex_setolink { printf("Lexer_setstr:: Returning setolink filetype\n"); type = 8; newstrt = lexer_lexsetolink(str); fbreak;}
250 action lex_eleolink { printf("Lexer_setstr:: Returning eleolink filetype\n"); type = 7; newstrt = lexer_lexeleolink(str); fbreak;}
251 action p {printf("p = %s \n",p);}
252 action name_error {printf("In %s, there is a syntactic error. Make sure your set/element names dont conflict with the reserved keywords.\n", str);}
253
254
255 N = 'N';
256 W = 'W';
257 S = 'S';
258 E = 'E';
259 NW = 'NW';
260 NE = 'NE';
261 SW = 'SW';
262 SE = 'SE';
263
264 SS = 'SS';
265 direction = (N | W | S | E | NW | NE | SW | SE) $p;
266
267 SSD = SS direction;
268
269
270
271 name = alpha+ $p - SSD $p;
272 num = digit+ $p;
273 ref = '0x' $p alnum+ $p;
274
275
276 set_label = name | (name '_' ref);
277 ele_label = name | (name '_' ref);
278
279 model_types = (name) | (name '_' num '_' num) | (name '_' num);
280
281
282 set_model = set_label '_' SS %to(lex_setmodel);
283 set_map = set_label '_' '~' %to(lex_setmap);
284 ele_model = set_label '_' ele_label '_' SS %to(lex_elemodel);
285 ele_map = set_label '_' ele_label '_' '~' %to(lex_elemap);
286 set_olink = ref %to(lex_setolink) [\0] ;
287 ele_olink = set_label '_' '~' '_' ref [\0] %to(lex_eleolink);
288 set_vlink = set_label '_' '#' '_' (ref | ref '_' name) [\0] %to(lex_setvlink);
289 ele_vlink = set_label '_' ele_label '_' '#' '_' (ref | ref '_' name) [\0] %to(lex_elevlink);
290
291 main := (ele_map | set_model | set_map |ele_model | ele_vlink | set_vlink | set_olink | ele_olink);
292
293 write data;
294
295
296 }%%
297
298 int
299 lexer_setstr
300 (uint8_t* str, int size)
301 { uint8_t *p, *pe, *eof;
302 int cs, type, newstrt;
303
304 type = newstrt = 0;
305
306 p = str;
307 pe = str + size + 1;
308
309 printf("|--- Begin lexer_setstr with str = %s, p = %s, pe = %s ---|\n", str,p, pe);
310
311 %%write init;
312 %%write exec noend;
313
314 printf("|--- End lexer_setstr. Incrementing str by %d, type is %d ---|\n", newstrt, type);
315
316 return newstrt;
317 }
318
319 #endif
320
321
322 /* %%{ */
323 /* machine file_matcher; */
324
325 /* action call_ml { ts = p; fgoto set_hw ;} */
326 /* action call_tl { return 0;} */
327 /* action set_height {height = ttov(p, p-ts+1); ts = p;} */
328 /* action set_width { width = ttov(p, p-ts+1);} */
329 /* action call_lmf {lexer_lexmapfile(height, width); } */
330 /* action lex_error {printf("input error: character %c in filename %s is invalid\n = %s\n", fc, str, p);} */
331
332 /* #This machine determines the type of file we are lexing */
333 /* #and calls the appropriate machine to handle it. */
334
335 /* #TODO add mapping name */
336 /* width = digit+ %set_width; */
337 /* height = digit+ %set_height; */
338
339 /* set_hw := height . '_' . width [\0] %to(call_lmf); */
340
341 /* tok_segment = alnum; */
342 /* map_end = 'm' . '_' %to(call_ml); */
343 /* tok_end = alnum+ . [\0] %to(call_tl); */
344
345 /* file_matcher := (tok_segment+ . '_' )+ ( map_end | tok_end ); */
346
347 /* write data; */
348 /* }%% */
349
350 /* int */
351 /* lexer_matchfile */
352 /* (char* str, int size) */
353 /* { *p, *pe; */
354 /* char* ts; */
355 /* int cs, ntok, height, width; */
356
357 /* p = str; */
358 /* pe = p + size; */
359 /* height = width = 0; */
360
361 /* printf("Checking if filename is a map file:: filename = %s, p = %c, pe = %c\n", str, *p, *pe); */
362
363 /* %%write init; */
364 /* %%write exec noend; */
365
366 /* printf("Ending lexer_ismapfile on %s\n", str); */
367
368 /* return ntok; */
369 /* } */
370
371 /* %%{ */
372 /* machine vartype; */
373
374 /* action isele {return 0;} */
375 /* action ismodel {return 1;} */
376
377 /* set_name = alpha+; */
378 /* ele_name = alpha+; */
379 /* model_name = alpha+; */
380
381 /* ele = set_name '_' model_name '_' ele_name %isele; */
382 /* model = set_name '_' model_name [\0] %ismodel; */
383
384
385 /* ismodel := (ele | model); */
386
387 /* write data; */
388
389 /* }%% */
390
391 /* int */
392 /* lexer_ismodel */
393 /* (uint8_t* str, int size) */
394 /* { uint8_t *p, *pe, *eof; */
395 /* int cs; */
396
397 /* p = str; */
398 /* pe = p + size + 1; */
399
400 /* %%write init; */
401 /* %%write exec; */
402
403
404 /* } */