flush
[m6w6/ext-psi] / src / parser.re
1 #include <stddef.h>
2 #include <stdio.h>
3 #include <assert.h>
4 #include <errno.h>
5 #include <string.h>
6
7 #include "parser.h"
8 #include "parser_proc.h"
9
10 void *PSI_ParserProcAlloc(void*(unsigned long));
11 void PSI_ParserProcFree(void*, void(*)(void*));
12 void PSI_ParserProc(void *, token_t, PSI_Token *, PSI_Parser *);
13 void PSI_ParserProcTrace(FILE *, const char*);
14
15 PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags)
16 {
17 FILE *fp;
18
19 fp = fopen(filename, "r");
20
21 if (!fp) {
22 if (!(flags & PSI_PARSER_SILENT)) {
23 error(NULL, NULL, PSI_WARNING, "Could not open '%s' for reading: %s",
24 filename, strerror(errno));
25 }
26 return NULL;
27 }
28
29 if (!P) {
30 P = malloc(sizeof(*P));
31 }
32 memset(P, 0, sizeof(*P));
33
34 P->psi.file.fn = strdup(filename);
35 P->fp = fp;
36 P->col = 1;
37 P->line = 1;
38 P->error = error;
39 P->flags = flags;
40
41 P->proc = PSI_ParserProcAlloc(malloc);
42 if (flags & PSI_PARSER_DEBUG) {
43 PSI_ParserProcTrace(stderr, "PSI> ");
44 }
45
46 PSI_ParserFill(P, 0);
47
48 return P;
49 }
50
51 size_t PSI_ParserFill(PSI_Parser *P, size_t n)
52 {
53 if (P->flags & PSI_PARSER_DEBUG) {
54 fprintf(stderr, "PSI> Fill: n=%zu\n", n);
55 }
56 if (!n) {
57 P->cur = P->tok = P->lim = P->mrk = P->buf;
58 P->eof = NULL;
59 }
60
61 if (!P->eof) {
62 size_t consumed = P->tok - P->buf;
63 size_t reserved = P->lim - P->tok;
64 size_t available = BSIZE - reserved;
65 size_t didread;
66
67 if (consumed) {
68 memmove(P->buf, P->tok, reserved);
69 P->tok -= consumed;
70 P->cur -= consumed;
71 P->lim -= consumed;
72 P->mrk -= consumed;
73 }
74
75 didread = fread(P->lim, 1, available, P->fp);
76 P->lim += didread;
77 if (didread < available) {
78 P->eof = P->lim;
79 }
80
81 if (P->flags & PSI_PARSER_DEBUG) {
82 fprintf(stderr, "PSI> Fill: consumed=%zu reserved=%zu available=%zu didread=%zu\n",
83 consumed, reserved, available, didread);
84 }
85 }
86 if (P->flags & PSI_PARSER_DEBUG) {
87 fprintf(stderr, "PSI> Fill: avail=%zu\n", P->lim - P->cur);
88 }
89 return P->lim - P->cur;
90 }
91
92 void PSI_ParserParse(PSI_Parser *P, PSI_Token *T)
93 {
94 if (T) {
95 PSI_ParserProc(P->proc, T->type, T, P);
96 } else {
97 PSI_ParserProc(P->proc, 0, NULL, P);
98 }
99 }
100
101 void PSI_ParserDtor(PSI_Parser *P)
102 {
103 PSI_ParserProcFree(P->proc, free);
104
105 if (P->fp) {
106 fclose(P->fp);
107 }
108
109 PSI_DataDtor((PSI_Data *) P);
110
111 memset(P, 0, sizeof(*P));
112 }
113
114 void PSI_ParserFree(PSI_Parser **P)
115 {
116 if (*P) {
117 PSI_ParserDtor(*P);
118 free(*P);
119 *P = NULL;
120 }
121 }
122
123 /*!max:re2c*/
124 #define BSIZE 256
125
126 #if BSIZE < YYMAXFILL
127 # error BSIZE must be greater than YYMAXFILL
128 #endif
129
130 #define RETURN(t) do { \
131 P->num = t; \
132 if (P->flags & PSI_PARSER_DEBUG) { \
133 fprintf(stderr, "PSI> TOKEN: %d %.*s (EOF=%d %s:%u:%u)\n", \
134 P->num, (int) (P->cur-P->tok), P->tok, P->num == PSI_T_EOF, \
135 P->psi.file.fn, P->line, P->col); \
136 } \
137 return t; \
138 } while(1)
139
140 #define ADDCOLS \
141 P->col += P->cur - P->tok
142
143 #define NEWLINE(label) \
144 P->col = 1; \
145 ++P->line; \
146 goto label
147
148 token_t PSI_ParserScan(PSI_Parser *P)
149 {
150 for (;;) {
151 ADDCOLS;
152 nextline:
153 P->tok = P->cur;
154 /*!re2c
155 re2c:indent:top = 2;
156 re2c:define:YYCTYPE = "unsigned char";
157 re2c:define:YYCURSOR = P->cur;
158 re2c:define:YYLIMIT = P->lim;
159 re2c:define:YYMARKER = P->mrk;
160 re2c:define:YYFILL = "{ if (!PSI_ParserFill(P,@@)) RETURN(PSI_T_EOF); }";
161 re2c:yyfill:parameter = 0;
162
163 B = [^a-zA-Z0-9_];
164 W = [a-zA-Z0-9_];
165 NAME = [a-zA-Z_]W*;
166 NSNAME = (NAME)? ("\\" NAME)+;
167 DOLLAR_NAME = '$' NAME;
168 QUOTED_STRING = "\"" ([^\"])+ "\"";
169 NUMBER = [+-]? [0-9]* "."? [0-9]+ ([eE] [+-]? [0-9]+)?;
170
171 "/*" { goto comment; }
172 ("#"|"//") .* "\n" { NEWLINE(nextline); }
173 "(" {RETURN(PSI_T_LPAREN);}
174 ")" {RETURN(PSI_T_RPAREN);}
175 ";" {RETURN(PSI_T_EOS);}
176 "," {RETURN(PSI_T_COMMA);}
177 ":" {RETURN(PSI_T_COLON);}
178 "{" {RETURN(PSI_T_LBRACE);}
179 "}" {RETURN(PSI_T_RBRACE);}
180 "[" {RETURN(PSI_T_LBRACKET);}
181 "]" {RETURN(PSI_T_RBRACKET);}
182 "=" {RETURN(PSI_T_EQUALS);}
183 "*" {RETURN(PSI_T_ASTERISK);}
184 "&" {RETURN(PSI_T_AMPERSAND);}
185 "+" {RETURN(PSI_T_PLUS);}
186 "-" {RETURN(PSI_T_MINUS);}
187 "/" {RETURN(PSI_T_SLASH);}
188 "..." {RETURN(PSI_T_ELLIPSIS);}
189 [\r\n] { NEWLINE(nextline); }
190 [\t ]+ { continue; }
191 'TRUE' {RETURN(PSI_T_TRUE);}
192 'FALSE' {RETURN(PSI_T_FALSE);}
193 'NULL' {RETURN(PSI_T_NULL);}
194 'MIXED' {RETURN(PSI_T_MIXED);}
195 'CALLABLE' {RETURN(PSI_T_CALLABLE);}
196 'VOID' {RETURN(PSI_T_VOID);}
197 'BOOL' {RETURN(PSI_T_BOOL);}
198 'CHAR' {RETURN(PSI_T_CHAR);}
199 'SHORT' {RETURN(PSI_T_SHORT);}
200 'INT' {RETURN(PSI_T_INT);}
201 'LONG' {RETURN(PSI_T_LONG);}
202 'FLOAT' {RETURN(PSI_T_FLOAT);}
203 'DOUBLE' {RETURN(PSI_T_DOUBLE);}
204 'INT8_T' {RETURN(PSI_T_INT8);}
205 'UINT8_T' {RETURN(PSI_T_UINT8);}
206 'INT16_T' {RETURN(PSI_T_INT16);}
207 'UINT16_T' {RETURN(PSI_T_UINT16);}
208 'INT32_T' {RETURN(PSI_T_INT32);}
209 'UINT32_T' {RETURN(PSI_T_UINT32);}
210 'INT64_T' {RETURN(PSI_T_INT64);}
211 'UINT64_T' {RETURN(PSI_T_UINT64);}
212 'UNSIGNED' {RETURN(PSI_T_UNSIGNED);}
213 'SIGNED' {RETURN(PSI_T_SIGNED);}
214 'STRING' {RETURN(PSI_T_STRING);}
215 'ARRAY' {RETURN(PSI_T_ARRAY);}
216 'OBJECT' {RETURN(PSI_T_OBJECT);}
217 'FUNCTION' {RETURN(PSI_T_FUNCTION);}
218 'TYPEDEF' {RETURN(PSI_T_TYPEDEF);}
219 'STRUCT' {RETURN(PSI_T_STRUCT);}
220 'UNION' {RETURN(PSI_T_UNION);}
221 'ENUM' {RETURN(PSI_T_ENUM);}
222 'CONST' {RETURN(PSI_T_CONST);}
223 'LIB' {RETURN(PSI_T_LIB);}
224 'LET' {RETURN(PSI_T_LET);}
225 'SET' {RETURN(PSI_T_SET);}
226 'RETURN' {RETURN(PSI_T_RETURN);}
227 'FREE' {RETURN(PSI_T_FREE);}
228 'TEMP' {RETURN(PSI_T_TEMP);}
229 'STRLEN' {RETURN(PSI_T_STRLEN);}
230 'STRVAL' {RETURN(PSI_T_STRVAL);}
231 'PATHVAL' {RETURN(PSI_T_PATHVAL);}
232 'INTVAL' {RETURN(PSI_T_INTVAL);}
233 'FLOATVAL' {RETURN(PSI_T_FLOATVAL);}
234 'BOOLVAL' {RETURN(PSI_T_BOOLVAL);}
235 'ARRVAL' {RETURN(PSI_T_ARRVAL);}
236 'OBJVAL' {RETURN(PSI_T_OBJVAL);}
237 'CBVAL' {RETURN(PSI_T_CBVAL);}
238 'CALLOC' {RETURN(PSI_T_CALLOC);}
239 'TO_OBJECT' {RETURN(PSI_T_TO_OBJECT);}
240 'TO_ARRAY' {RETURN(PSI_T_TO_ARRAY);}
241 'TO_STRING' {RETURN(PSI_T_TO_STRING);}
242 'TO_INT' {RETURN(PSI_T_TO_INT);}
243 'TO_FLOAT' {RETURN(PSI_T_TO_FLOAT);}
244 'TO_BOOL' {RETURN(PSI_T_TO_BOOL);}
245 NUMBER {RETURN(PSI_T_NUMBER);}
246 NAME {RETURN(PSI_T_NAME);}
247 NSNAME {RETURN(PSI_T_NSNAME);}
248 DOLLAR_NAME {RETURN(PSI_T_DOLLAR_NAME);}
249 QUOTED_STRING {RETURN(PSI_T_QUOTED_STRING);}
250 [^] {break;}
251 */
252
253 comment:
254 P->tok = P->cur;
255 /*!re2c
256 "\n" { NEWLINE(comment); }
257 "*" "/" { continue; }
258 [^] { goto comment; }
259 */
260 }
261 return -1;
262 }