workaround for old libffi
[m6w6/ext-psi] / src / parser.re
1 #include <stdio.h>
2 #include <assert.h>
3
4 #include "parser.h"
5 #include "parser_proc.h"
6
7 void *PSI_ParserProcAlloc(void*(unsigned long));
8 void PSI_ParserProcFree(void*, void(*)(void*));
9 void PSI_ParserProc(void *, token_t, PSI_Token *, PSI_Parser *);
10 void PSI_ParserProcTrace(FILE *, const char*);
11
12 PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags)
13 {
14 FILE *fp;
15
16 if (!P) {
17 P = malloc(sizeof(*P));
18 }
19 memset(P, 0, sizeof(*P));
20
21 fp = fopen(filename, "r");
22
23 if (!fp) {
24 perror(filename);
25 return NULL;
26 }
27
28 if (!P) {
29 P = malloc(sizeof(*P));
30 }
31 memset(P, 0, sizeof(*P));
32
33 P->psi.file.fn = strdup(filename);
34 P->fp = fp;
35 P->col = 1;
36 P->line = 1;
37 P->error = error;
38 P->flags = flags;
39
40 P->proc = PSI_ParserProcAlloc(malloc);
41 if (flags & PSI_PARSER_DEBUG) {
42 PSI_ParserProcTrace(stderr, "PSI> ");
43 }
44
45 PSI_ParserFill(P, 0);
46
47 return P;
48 }
49
50 void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...) {
51 char buf[0x1000] = {0};
52 va_list argv;
53
54 va_start(argv, msg);
55 vsnprintf(buf, 0x1000-1, msg, argv);
56 va_end(argv);
57
58 P->error(PSI_WARNING, "PSI syntax error on line %zu in '%s'%s%s",
59 ln, fn, msg ? ": ": "", buf);
60
61 ++P->errors;
62 }
63
64 size_t PSI_ParserFill(PSI_Parser *P, size_t n)
65 {
66 if (P->flags & PSI_PARSER_DEBUG) {
67 fprintf(stderr, "PSI> Fill: n=%zu\n", n);
68 }
69 if (!n) {
70 P->cur = P->tok = P->lim = P->mrk = P->buf;
71 P->eof = NULL;
72 }
73
74 if (!P->eof) {
75 size_t consumed = P->tok - P->buf;
76 size_t reserved = P->lim - P->tok;
77 size_t available = BSIZE - reserved;
78 size_t didread;
79
80 if (consumed) {
81 memmove(P->buf, P->tok, reserved);
82 P->tok -= consumed;
83 P->cur -= consumed;
84 P->lim -= consumed;
85 P->mrk -= consumed;
86 }
87
88 didread = fread(P->lim, 1, available, P->fp);
89 P->lim += didread;
90 if (didread < available) {
91 P->eof = P->lim;
92 }
93
94 if (P->flags & PSI_PARSER_DEBUG) {
95 fprintf(stderr, "PSI> Fill: consumed=%zu reserved=%zu available=%zu didread=%zu\n",
96 consumed, reserved, available, didread);
97 }
98 }
99 if (P->flags & PSI_PARSER_DEBUG) {
100 fprintf(stderr, "PSI> Fill: avail=%zu\n", P->lim - P->cur);
101 }
102 return P->lim - P->cur;
103 }
104
105 void PSI_ParserParse(PSI_Parser *P, PSI_Token *T)
106 {
107 if (T) {
108 PSI_ParserProc(P->proc, T->type, T, P);
109 } else {
110 PSI_ParserProc(P->proc, 0, NULL, P);
111 }
112 }
113
114 void PSI_ParserDtor(PSI_Parser *P)
115 {
116 PSI_ParserProcFree(P->proc, free);
117
118 if (P->fp) {
119 fclose(P->fp);
120 }
121
122 PSI_DataDtor((PSI_Data *) P);
123
124 memset(P, 0, sizeof(*P));
125 }
126
127 void PSI_ParserFree(PSI_Parser **P)
128 {
129 if (*P) {
130 PSI_ParserDtor(*P);
131 free(*P);
132 *P = NULL;
133 }
134 }
135
136 /*!max:re2c*/
137 #define BSIZE 256
138
139 #if BSIZE < YYMAXFILL
140 # error BSIZE must be greater than YYMAXFILL
141 #endif
142
143 #define PSI_T(n) \
144 (n) == PSI_T_NAME ? "NAME" : \
145 (n) == PSI_T_PLUS ? "PLUS" : \
146 (n) == PSI_T_MINUS ? "MINUS" : \
147 (n) == PSI_T_SLASH ? "SLASH" : \
148 (n) == PSI_T_ASTERISK ? "ASTERISK" : \
149 (n) == PSI_T_TEMP ? "TEMP" : \
150 (n) == PSI_T_FREE ? "FREE" : \
151 (n) == PSI_T_SET ? "SET" : \
152 (n) == PSI_T_LET ? "LET" : \
153 (n) == PSI_T_RETURN ? "RETURN" : \
154 (n) == PSI_T_LIB ? "LIB" : \
155 (n) == PSI_T_INT ? "INT" : \
156 (n) == PSI_T_UNSIGNED ? "UNSIGNED" : \
157 (n) == PSI_T_EOF ? "EOF" : \
158 (n) == PSI_T_QUOTED_STRING ? "QUOTED_STRING" : \
159 (n) == PSI_T_EOS ? "EOS" : \
160 (n) == PSI_T_STRUCT ? "STRUCT" : \
161 (n) == PSI_T_LBRACE ? "LBRACE" : \
162 (n) == PSI_T_RBRACE ? "RBRACE" : \
163 (n) == PSI_T_COLON ? "COLON" : \
164 (n) == PSI_T_LPAREN ? "LPAREN" : \
165 (n) == PSI_T_NUMBER ? "NUMBER" : \
166 (n) == PSI_T_RPAREN ? "RPAREN" : \
167 (n) == PSI_T_BOOL ? "BOOL" : \
168 (n) == PSI_T_FLOAT ? "FLOAT" : \
169 (n) == PSI_T_STRING ? "STRING" : \
170 (n) == PSI_T_CONST ? "CONST" : \
171 (n) == PSI_T_NSNAME ? "NSNAME" : \
172 (n) == PSI_T_EQUALS ? "EQUALS" : \
173 (n) == PSI_T_TYPEDEF ? "TYPEDEF" : \
174 (n) == PSI_T_VOID ? "VOID" : \
175 (n) == PSI_T_LBRACKET ? "LBRACKET" : \
176 (n) == PSI_T_RBRACKET ? "RBRACKET" : \
177 (n) == PSI_T_COMMA ? "COMMA" : \
178 (n) == PSI_T_ELLIPSIS ? "ELLIPSIS" : \
179 (n) == PSI_T_DOUBLE ? "DOUBLE" : \
180 (n) == PSI_T_INT8 ? "INT8" : \
181 (n) == PSI_T_UINT8 ? "UINT8" : \
182 (n) == PSI_T_INT16 ? "INT16" : \
183 (n) == PSI_T_UINT16 ? "UINT16" : \
184 (n) == PSI_T_INT32 ? "INT32" : \
185 (n) == PSI_T_UINT32 ? "UINT32" : \
186 (n) == PSI_T_INT64 ? "INT64" : \
187 (n) == PSI_T_UINT64 ? "UINT64" : \
188 (n) == PSI_T_FUNCTION ? "FUNCTION" : \
189 (n) == PSI_T_NULL ? "NULL" : \
190 (n) == PSI_T_TRUE ? "TRUE" : \
191 (n) == PSI_T_FALSE ? "FALSE" : \
192 (n) == PSI_T_DOLLAR ? "DOLLAR" : \
193 (n) == PSI_T_CALLOC ? "CALLOC" : \
194 (n) == PSI_T_OBJVAL ? "OBJVAL" : \
195 (n) == PSI_T_ARRVAL ? "ARRVAL" : \
196 (n) == PSI_T_PATHVAL ? "PATHVAL" : \
197 (n) == PSI_T_STRLEN ? "STRLEN" : \
198 (n) == PSI_T_STRVAL ? "STRVAL" : \
199 (n) == PSI_T_FLOATVAL ? "FLOATVAL" : \
200 (n) == PSI_T_INTVAL ? "INTVAL" : \
201 (n) == PSI_T_BOOLVAL ? "BOOLVAL" : \
202 (n) == PSI_T_TO_OBJECT ? "TO_OBJECT" : \
203 (n) == PSI_T_TO_ARRAY ? "TO_ARRAY" : \
204 (n) == PSI_T_TO_STRING ? "TO_STRING" : \
205 (n) == PSI_T_TO_INT ? "TO_INT" : \
206 (n) == PSI_T_TO_FLOAT ? "TO_FLOAT" : \
207 (n) == PSI_T_TO_BOOL ? "TO_BOOL" : \
208 (n) == PSI_T_MIXED ? "MIXED" : \
209 (n) == PSI_T_ARRAY ? "ARRAY" : \
210 (n) == PSI_T_OBJECT ? "OBJECT" : \
211 (n) == PSI_T_AMPERSAND ? "AMPERSAND" : \
212 <UNKNOWN>
213
214 #define RETURN(t) do { \
215 P->num = t; \
216 if (P->flags & PSI_PARSER_DEBUG) { \
217 fprintf(stderr, "PSI> TOKEN: %d %.*s (EOF=%d %s:%zu:%zu)\n", \
218 P->num, (int) (P->cur-P->tok), P->tok, P->num == PSI_T_EOF, \
219 P->psi.file.fn, P->line, P->col); \
220 } \
221 return t; \
222 } while(1)
223
224 #define ADDCOLS \
225 P->col += P->cur - P->tok
226
227 #define NEWLINE \
228 P->col = 1; \
229 ++P->line; \
230 goto nextline
231
232 token_t PSI_ParserScan(PSI_Parser *P)
233 {
234 for (;;) {
235 ADDCOLS;
236 nextline:
237 P->tok = P->cur;
238 /*!re2c
239 re2c:indent:top = 2;
240 re2c:define:YYCTYPE = "unsigned char";
241 re2c:define:YYCURSOR = P->cur;
242 re2c:define:YYLIMIT = P->lim;
243 re2c:define:YYMARKER = P->mrk;
244 re2c:define:YYFILL = "{ if (!PSI_ParserFill(P,@@)) RETURN(PSI_T_EOF); }";
245 re2c:yyfill:parameter = 0;
246
247 B = [^a-zA-Z0-9_];
248 W = [a-zA-Z0-9_];
249 NAME = [a-zA-Z_]W*;
250 NSNAME = (NAME)? ("\\" NAME)+;
251 QUOTED_STRING = "\"" ([^\"])+ "\"";
252 NUMBER = [+-]? [0-9]* "."? [0-9]+ ([eE] [+-]? [0-9]+)?;
253
254 ("#"|"//") .* "\n" { NEWLINE; }
255 "(" {RETURN(PSI_T_LPAREN);}
256 ")" {RETURN(PSI_T_RPAREN);}
257 ";" {RETURN(PSI_T_EOS);}
258 "," {RETURN(PSI_T_COMMA);}
259 ":" {RETURN(PSI_T_COLON);}
260 "{" {RETURN(PSI_T_LBRACE);}
261 "}" {RETURN(PSI_T_RBRACE);}
262 "[" {RETURN(PSI_T_LBRACKET);}
263 "]" {RETURN(PSI_T_RBRACKET);}
264 "=" {RETURN(PSI_T_EQUALS);}
265 "$" {RETURN(PSI_T_DOLLAR);}
266 "*" {RETURN(PSI_T_ASTERISK);}
267 "&" {RETURN(PSI_T_AMPERSAND);}
268 "+" {RETURN(PSI_T_PLUS);}
269 "-" {RETURN(PSI_T_MINUS);}
270 "/" {RETURN(PSI_T_SLASH);}
271 "..." {RETURN(PSI_T_ELLIPSIS);}
272 [\r\n] { NEWLINE; }
273 [\t ]+ { continue; }
274 'TRUE' {RETURN(PSI_T_TRUE);}
275 'FALSE' {RETURN(PSI_T_FALSE);}
276 'NULL' {RETURN(PSI_T_NULL);}
277 'MIXED' {RETURN(PSI_T_MIXED);}
278 'VOID' {RETURN(PSI_T_VOID);}
279 'BOOL' {RETURN(PSI_T_BOOL);}
280 'INT' {RETURN(PSI_T_INT);}
281 'FLOAT' {RETURN(PSI_T_FLOAT);}
282 'DOUBLE' {RETURN(PSI_T_DOUBLE);}
283 'INT8_T' {RETURN(PSI_T_INT8);}
284 'UINT8_T' {RETURN(PSI_T_UINT8);}
285 'INT16_T' {RETURN(PSI_T_INT16);}
286 'UINT16_T' {RETURN(PSI_T_UINT16);}
287 'INT32_T' {RETURN(PSI_T_INT32);}
288 'UINT32_T' {RETURN(PSI_T_UINT32);}
289 'INT64_T' {RETURN(PSI_T_INT64);}
290 'UINT64_T' {RETURN(PSI_T_UINT64);}
291 'UNSIGNED' {RETURN(PSI_T_UNSIGNED);}
292 'STRING' {RETURN(PSI_T_STRING);}
293 'ARRAY' {RETURN(PSI_T_ARRAY);}
294 'OBJECT' {RETURN(PSI_T_OBJECT);}
295 'FUNCTION' {RETURN(PSI_T_FUNCTION);}
296 'TYPEDEF' {RETURN(PSI_T_TYPEDEF);}
297 'STRUCT' {RETURN(PSI_T_STRUCT);}
298 'CONST' {RETURN(PSI_T_CONST);}
299 'LIB' {RETURN(PSI_T_LIB);}
300 'LET' {RETURN(PSI_T_LET);}
301 'SET' {RETURN(PSI_T_SET);}
302 'RETURN' {RETURN(PSI_T_RETURN);}
303 'FREE' {RETURN(PSI_T_FREE);}
304 'TEMP' {RETURN(PSI_T_TEMP);}
305 'STRLEN' {RETURN(PSI_T_STRLEN);}
306 'STRVAL' {RETURN(PSI_T_STRVAL);}
307 'PATHVAL' {RETURN(PSI_T_PATHVAL);}
308 'INTVAL' {RETURN(PSI_T_INTVAL);}
309 'FLOATVAL' {RETURN(PSI_T_FLOATVAL);}
310 'BOOLVAL' {RETURN(PSI_T_BOOLVAL);}
311 'ARRVAL' {RETURN(PSI_T_ARRVAL);}
312 'OBJVAL' {RETURN(PSI_T_OBJVAL);}
313 'CALLOC' {RETURN(PSI_T_CALLOC);}
314 'TO_OBJECT' {RETURN(PSI_T_TO_OBJECT);}
315 'TO_ARRAY' {RETURN(PSI_T_TO_ARRAY);}
316 'TO_STRING' {RETURN(PSI_T_TO_STRING);}
317 'TO_INT' {RETURN(PSI_T_TO_INT);}
318 'TO_FLOAT' {RETURN(PSI_T_TO_FLOAT);}
319 'TO_BOOL' {RETURN(PSI_T_TO_BOOL);}
320 NUMBER {RETURN(PSI_T_NUMBER);}
321 NAME {RETURN(PSI_T_NAME);}
322 NSNAME {RETURN(PSI_T_NSNAME);}
323 QUOTED_STRING {RETURN(PSI_T_QUOTED_STRING);}
324 [^] {break;}
325 */
326 }
327 return -1;
328 }