commented debug prints
[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 /* Public */
10 int lexer_init(void);
11 void lexer_quit(void);
12 int lexer_lexfile(uint8_t*);
13 int lexer_lexdir(uint8_t*);
14 int lexer_lexstring(uint8_t*, int);
15 //apc.c
16 static
17 yypstate* pstate;
18 static
19 yycstate* cstate;
20 /* Ring buffer for keeping lexical tokens valid for up to 255 tokens */
21 static
22 YYSTYPE lval_stack[0xFF + 1];
23 static
24 uint8_t lval_offs;
25 #define PUSHTOK(T,L) yypush_parse(pstate, T, (L), cstate)
26 #define LEXTOK(T,Y,L) do { \
27 lval_stack[lval_offs].Y = L; \
28 PUSHTOK(T,lval_stack + lval_offs); \
29 lval_offs++; \
30 ntok++; \
31 } while (0);
32 #define PUSHFACE(F) LEXTOK(FACING, face, F)
33 #define PUSHREF(R) LEXTOK(REF, ref, R)
34 #define PUSHLINK() LEXTOK(LINK, val, 0)
35 #define PUSHNUM(N) LEXTOK(NUM, val, N)
36 #define PUSHNAME(N) LEXTOK(NAME, str, N)
37 #define PUSHOP(O) LEXTOK(O, val, 0)
38 #define PUSHPATH(P) LEXTOK(PATH, str, P)
39
40 /* Lexstring is the main lexer for APC and is generated by ragel. It lexes file names of files
41 that have been scanned and pushes their types and values into the tok_stack, which yyparse
42 eventually calls during parsing. */
43
44 %%{
45 machine lexstring;
46
47 # set up yylval and tok_t to be pushed to stack
48 action push_ref { errno = 0;
49 lval.ref = strtoll((char*)ts,NULL,16);
50 if (errno)
51 { fprintf(stderr, "Invalid hex number in file %s\n",(char*)str);
52 exit(1);
53 }
54 PUSHREF(lval.ref);
55 }
56 action push_link { PUSHLINK(); }
57 action push_val { errno = 0;
58 lval.val = strtoll((char*)ts,NULL,10);
59 if (errno)
60 { fprintf(stderr, "strtoll could not parse %s\n", (char*)str);
61 exit(1);
62 }
63 PUSHNUM(lval.val);
64 }
65 action push_name { //printf("Lexer_lexstring:: action:push_name: from %s to %s\n", ts, p);
66 PUSHNAME(ts);
67 }
68 action push_map { //printf("Lexer_lexstring:: action:push_map: pushing map token\n");
69 PUSHOP(MAP);
70 }
71 action set_ts { //printf("Lexer_lexstring:: action:set_ts. ts = %s\n", p);
72 ts = p; }
73 action push_SS { //printf("Lexer_lexstring:: action:push_SS. p = %s\n",p);
74 PUSHOP(SS);
75 }
76 action push_S { //printf("Lexer_lexstring:: action:push_S. p = %s\n", p);
77 PUSHFACE(SFACE);
78 }
79 action push_SW { //printf("Lexer_lexstring:: action:push_SW. p = %s\n", p);
80 PUSHFACE(SWFACE);
81 }
82 action push_W { //printf("Lexer_lexstring:: action:push_W. p = %s\n", p);
83 PUSHFACE(WFACE);
84 }
85 action push_NW { //printf("Lexer_lexstring:: action:push_NW. p = %s\n", p);
86 PUSHFACE(NWFACE);
87 }
88 action push_N { //printf("Lexer_lexstring:: action:push_N. p = %s\n", p);
89 PUSHFACE(NFACE);
90 }
91 action push_NE { //printf("Lexer_lexstring:: action:push_NE. p = %s\n", p);
92 PUSHFACE(NEFACE);
93 }
94 action push_E { //printf("Lexer_lexstring:: action:push_N. p = %s\n", p);
95 PUSHFACE(EFACE);
96 }
97 action push_SE { //printf("Lexer_lexstring:: action:push_N. p = %s\n", p);
98 PUSHFACE(SEFACE);
99 }
100 action ref_error { //printf("ref from %s to %s has an inappropriate amount of hex digits, it must have eight.\n", ts, p);
101 exit(1);
102 }
103 action p { //printf("Lexer_lexstring:: p = %s\n", p);
104 }
105
106 N = 'N' %push_N;
107 W = 'W' %push_W;
108 S = 'S' %push_S;
109 E = 'E' %push_E;
110 NW = 'NW' %push_NW;
111 NE = 'NE' %push_NW;
112 SW = 'SW' %push_SW;
113 SE = 'SE' %push_SE;
114
115 tok_delimiter = [_];
116
117 direction = (N | W | S | E | NW | NE | SW | SE) ;
118 dimensions = (digit+ - '0') >set_ts %push_val 'x' (digit+ - '0') >set_ts %push_val;
119 link = '#' %push_link;
120 SS = ('+SS' %to(push_SS)) | ('+SS' %to(push_SS) link ) ;
121 ref = '0x' >set_ts alnum{8} $err(ref_error) %push_ref ;
122 val = digit+ >set_ts %push_val ;
123 name = lower >set_ts (lower | digit)* %push_name ;
124 map = '+MAP' %to(push_map);
125 tok = (name | val | ref | dimensions | map | link | SS | direction);
126
127
128 main := (tok tok_delimiter)* tok [\0];
129
130 write data nofinal noerror noprefix;
131
132 }%%
133
134 int lexer_init
135 ( void )
136 { pstate = yypstate_new();
137 cstate = yycstate_new();
138 lval_offs = 0;
139 return !pstate || !cstate;
140 }
141
142 void lexer_quit
143 ( void )
144 { if (pstate) yypstate_delete(pstate);
145 if (cstate) yycstate_delete(cstate);
146 }
147
148 int lexer_lexstring
149 ( uint8_t* str,
150 int size
151 )
152 { uint8_t *p;
153 uint8_t *ts, *pe, *eof;
154 int cs, ntok;
155 YYSTYPE lval;
156
157 ntok = 0;
158 p = ts = str;
159 pe = eof = p + size + 1;
160
161 //printf("|---Begin lexstring on p = %s, pe = %s.\n",p, pe);
162
163 %%write init;
164 %%write exec;
165
166 //printf("Ending lexstring of file %s, pushed %d tokens.\n",str, ntok);
167
168 return ntok;
169 }
170
171 /* Lexical analysis of a file
172 Strips a filename to its base name, then sends it to lexer_lexstring before
173 pushing a PATH token with the filename
174 Returns the number of tokens pushed to the parser.
175 */
176 int lexer_lexfile
177 ( uint8_t* filename )
178 { uint8_t* last_period,* iter,* filename_end;
179 int ntok;
180 last_period = NULL;
181 for (iter = filename; *iter; iter++)
182 switch (*iter)
183 { // Keep track of the last 'dot' in the name
184 case '.' : last_period = iter; continue;
185 // replace '_' with '\0' so bison can use strlen on them as tokens.
186 case '_' : *iter = '\0';
187 default: continue;
188 }
189 // Mark the end of the filename
190 filename_end = iter;
191 // Lex from either the last period, if present, or filename end
192 ntok = (last_period) ?
193 lexer_lexstring(filename, (int)(last_period - filename))
194 : lexer_lexstring(filename, (int)(iter - filename));
195 // Replace nulls with their original '_'
196 for (iter = filename; iter < filename_end; iter++)
197 if (*iter == '\0')
198 *iter = '_';
199 PUSHPATH(filename);
200 return ntok + 1;
201 return en_main == 1;
202 }
203
204 int lexer_lexdir
205 ( uint8_t* dirname )
206 { uint8_t* de = dirname;
207 int ntok;
208 ntok = 0;
209 de = dirname;
210 if (*de) while (*++de);
211 ntok = lexer_lexstring(dirname, (int)(de - dirname));
212 PUSHOP(CLOPEN);
213 return ntok;
214 }
215
216 int lexer_closedir
217 ( void )
218 { int ntok = 0;
219 PUSHOP(CLCLOSE);
220 return ntok;
221 }