00001 #include <setjmp.h>
00002 #include <string.h>
00003
00004 #include "parse.h"
00005
00006
00007
00008 #define MAX_PREC_TOKS 6
00009 static const struct precedence {
00010 int toks[MAX_PREC_TOKS];
00011 int rule;
00012 } PRECEDENCE[] = {
00013 { { TOK_SEMI, TOK_COMMA }, PREC_REVERSE },
00014 { { TOK_ELLIPSIS }, PREC_SUFFIX },
00015 { { TOK_RETURN, TOK_BREAK, TOK_CONTINUE }, PREC_PREFIX },
00016 { { TOK_ASSIGN, TOK_PLUSEQ, TOK_MINUSEQ,
00017 TOK_MULEQ, TOK_DIVEQ, TOK_CATEQ }, PREC_REVERSE },
00018 { { TOK_COLON, TOK_QUESTION }, PREC_REVERSE },
00019 { { TOK_VAR }, PREC_PREFIX },
00020 { { TOK_OR }, PREC_BINARY },
00021 { { TOK_AND }, PREC_BINARY },
00022 { { TOK_EQ, TOK_NEQ }, PREC_BINARY },
00023 { { TOK_LT, TOK_LTE, TOK_GT, TOK_GTE }, PREC_BINARY },
00024 { { TOK_PLUS, TOK_MINUS, TOK_CAT }, PREC_BINARY },
00025 { { TOK_MUL, TOK_DIV }, PREC_BINARY },
00026 { { TOK_MINUS, TOK_NEG, TOK_NOT }, PREC_PREFIX },
00027 { { TOK_LPAR, TOK_LBRA }, PREC_SUFFIX },
00028 { { TOK_DOT }, PREC_BINARY },
00029 };
00030 #define PRECEDENCE_LEVELS (sizeof(PRECEDENCE)/sizeof(struct precedence))
00031
00032 void naParseError(struct Parser* p, char* msg, int line)
00033 {
00034 if(line > 0) p->errLine = line;
00035 p->err = msg;
00036 longjmp(p->jumpHandle, 1);
00037 }
00038
00039 static void oops(struct Parser* p) { naParseError(p, "parse error", -1); }
00040
00041 void naParseInit(struct Parser* p)
00042 {
00043 memset(p, 0, sizeof(*p));
00044 p->tree.type = TOK_TOP;
00045 p->tree.line = 1;
00046 }
00047
00048 void naParseDestroy(struct Parser* p)
00049 {
00050 int i;
00051 for(i=0; i<p->nChunks; i++) naFree(p->chunks[i]);
00052 naFree(p->chunks);
00053 naFree(p->chunkSizes);
00054 p->buf = 0;
00055 }
00056
00057 void* naParseAlloc(struct Parser* p, int bytes)
00058 {
00059 char* result;
00060 bytes = (bytes+7) & (~7);
00061
00062 if(p->leftInChunk < bytes) {
00063 void* newChunk;
00064 void** newChunks;
00065 int* newChunkSizes;
00066 int sz, i;
00067
00068 sz = p->len;
00069 if(sz < bytes) sz = bytes;
00070 newChunk = naAlloc(sz);
00071
00072 p->nChunks++;
00073
00074 newChunks = naAlloc(p->nChunks * sizeof(void*));
00075 for(i=1; i<p->nChunks; i++) newChunks[i] = p->chunks[i-1];
00076 newChunks[0] = newChunk;
00077 naFree(p->chunks);
00078 p->chunks = newChunks;
00079
00080 newChunkSizes = naAlloc(p->nChunks * sizeof(int));
00081 for(i=1; i<p->nChunks; i++) newChunkSizes[i] = p->chunkSizes[i-1];
00082 newChunkSizes[0] = sz;
00083 naFree(p->chunkSizes);
00084 p->chunkSizes = newChunkSizes;
00085
00086 p->leftInChunk = sz;
00087 }
00088
00089 result = (char *)p->chunks[0] + p->chunkSizes[0] - p->leftInChunk;
00090 p->leftInChunk -= bytes;
00091 return result;
00092 }
00093
00094 static void addChild(struct Token *par, struct Token *ch)
00095 {
00096 if(par->lastChild) {
00097 ch->prev = par->lastChild;
00098 par->lastChild->next = ch;
00099 } else
00100 par->children = ch;
00101 par->lastChild = ch;
00102 }
00103
00104 static int endBrace(int tok)
00105 {
00106 if(tok == TOK_LBRA) return TOK_RBRA;
00107 if(tok == TOK_LPAR) return TOK_RPAR;
00108 if(tok == TOK_LCURL) return TOK_RCURL;
00109 return -1;
00110 }
00111
00112 static int isOpenBrace(int t)
00113 {
00114 return t==TOK_LPAR || t==TOK_LBRA || t==TOK_LCURL;
00115 }
00116
00117 static int isLoopoid(int t)
00118 {
00119 return t==TOK_FOR || t==TOK_FOREACH || t==TOK_WHILE || t==TOK_FORINDEX;
00120 }
00121
00122 static int isBlockoid(int t)
00123 {
00124 return isLoopoid(t)||t==TOK_IF||t==TOK_ELSIF||t==TOK_ELSE||t==TOK_FUNC;
00125 }
00126
00127
00128
00129 static int isBlockEnd(int t)
00130 {
00131 return t==TOK_RPAR||t==TOK_RBRA||t==TOK_RCURL||t==TOK_ELSIF||t==TOK_ELSE;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140 static int needsSemi(struct Token* t, struct Token* next)
00141 {
00142 if(!next || next->type == TOK_SEMI || isBlockEnd(next->type)) return 0;
00143 if(t->type == TOK_IF) return !t->prev || t->prev->type == TOK_SEMI;
00144 if(t->type == TOK_FUNC) return t->prev && t->prev->type == TOK_ASSIGN;
00145 if(isLoopoid(t->type)) return 1;
00146 return 0;
00147 }
00148
00149 static struct Token* newToken(struct Parser* p, int type)
00150 {
00151 struct Token* t = naParseAlloc(p, sizeof(struct Token));
00152 memset(t, 0, sizeof(*t));
00153 t->type = type;
00154 t->line = -1;
00155 return t;
00156 }
00157
00158 static struct Token* parseToken(struct Parser* p, struct Token** list);
00159
00160 static void parseBlock(struct Parser* p, struct Token *top,
00161 int end, struct Token** list)
00162 {
00163 struct Token *t;
00164 while(*list) {
00165 if(isBlockEnd((*list)->type) && (*list)->type != end) break;
00166 if(end == TOK_SEMI && (*list)->type == TOK_COMMA) break;
00167 t = parseToken(p, list);
00168 if(t->type == end) return;
00169 addChild(top, t);
00170 if(needsSemi(t, *list))
00171 addChild(top, newToken(p, TOK_SEMI));
00172 }
00173
00174
00175
00176 if(end != TOK_SEMI && end != -1) oops(p);
00177 }
00178
00179 static struct Token* parseToken(struct Parser* p, struct Token** list)
00180 {
00181 struct Token *t = *list;
00182 *list = t->next;
00183 if(t->next) t->next->prev = 0;
00184 t->next = t->prev = 0;
00185 p->errLine = t->line;
00186
00187 if(!t) return 0;
00188 if(isOpenBrace(t->type)) {
00189 parseBlock(p, t, endBrace(t->type), list);
00190 } else if(isBlockoid(t->type)) {
00191
00192 if(!*list) oops(p);
00193 if((*list)->type == TOK_LPAR)
00194 addChild(t, parseToken(p, list));
00195
00196
00197 if(!*list) oops(p);
00198 if((*list)->type == TOK_LCURL) {
00199 addChild(t, parseToken(p, list));
00200 } else {
00201
00202
00203
00204
00205 struct Token *blk = newToken(p, TOK_LCURL);
00206 if(isBlockoid((*list)->type)) addChild(blk, parseToken(p, list));
00207 else parseBlock(p, blk, TOK_SEMI, list);
00208 addChild(t, blk);
00209 }
00210
00211
00212 if(t->type == TOK_IF) {
00213 while(*list && ((*list)->type == TOK_ELSIF))
00214 addChild(t, parseToken(p, list));
00215 if(*list && (*list)->type == TOK_ELSE)
00216 addChild(t, parseToken(p, list));
00217 }
00218
00219
00220 if(t->type != TOK_FUNC) {
00221 if(t->type == TOK_ELSE && t->children->type != TOK_LCURL) oops(p);
00222 if(t->type != TOK_ELSE && t->children->type != TOK_LPAR) oops(p);
00223 }
00224 }
00225 return t;
00226 }
00227
00228
00229 static int tokInLevel(struct Token* tok, int level)
00230 {
00231 int i;
00232 for(i=0; i<MAX_PREC_TOKS; i++)
00233 if(PRECEDENCE[level].toks[i] == tok->type)
00234 return 1;
00235 return 0;
00236 }
00237
00238 static struct Token* parsePrecedence(struct Parser* p, struct Token* start,
00239 struct Token* end, int level);
00240
00241 static void precChildren(struct Parser* p, struct Token* t)
00242 {
00243 struct Token* top = parsePrecedence(p, t->children, t->lastChild, 0);
00244 t->children = top;
00245 t->lastChild = top;
00246 }
00247
00248
00249
00250
00251 static void precBlock(struct Parser* p, struct Token* block)
00252 {
00253 struct Token* t = block->children;
00254 while(t) {
00255 if(isOpenBrace(t->type))
00256 precChildren(p, t);
00257 else if(isBlockoid(t->type))
00258 precBlock(p, t);
00259 t = t->next;
00260 }
00261 }
00262
00263
00264 static int oneSidedBinary(int t)
00265 { return t == TOK_SEMI || t == TOK_COMMA || t == TOK_COLON; }
00266
00267 static struct Token* parsePrecedence(struct Parser* p,
00268 struct Token* start, struct Token* end,
00269 int level)
00270 {
00271 int rule;
00272 struct Token *t, *top, *left, *right;
00273 struct Token *a, *b, *c, *d;
00274
00275
00276 if(level >= PRECEDENCE_LEVELS && start != end)
00277 naParseError(p, "parse error", start->line);
00278
00279
00280 if(end == 0 && start == 0)
00281 return newToken(p, TOK_EMPTY);
00282
00283
00284
00285
00286 if(end == 0) end = start;
00287 if(start == 0) start = end;
00288 if(start->prev) start->prev->next = 0;
00289 if(end->next) end->next->prev = 0;
00290 start->prev = end->next = 0;
00291
00292
00293
00294 if(start == end) {
00295 if (isOpenBrace(start->type)) precChildren(p, start);
00296 else if(isBlockoid(start->type)) precBlock(p, start);
00297 return start;
00298 }
00299
00300 if(oneSidedBinary(start->type)) {
00301 t = newToken(p, TOK_EMPTY);
00302 start->prev = t;
00303 t->next = start;
00304 start = t;
00305 }
00306 if(oneSidedBinary(end->type)) {
00307 t = newToken(p, TOK_EMPTY);
00308 end->next = t;
00309 t->prev = end;
00310 end = t;
00311 }
00312
00313
00314
00315
00316
00317
00318 if(PRECEDENCE[level].toks[0] == TOK_DOT)
00319 if(end->type == TOK_LPAR || end->type == TOK_LBRA)
00320 level--;
00321
00322 top = left = right = 0;
00323 rule = PRECEDENCE[level].rule;
00324 switch(rule) {
00325 case PREC_PREFIX:
00326 if(tokInLevel(start, level) && start->next) {
00327 a = start->children;
00328 b = start->lastChild;
00329 c = start->next;
00330 d = end;
00331 top = start;
00332 if(a) left = parsePrecedence(p, a, b, 0);
00333 right = parsePrecedence(p, c, d, level);
00334 }
00335 break;
00336 case PREC_SUFFIX:
00337 if(tokInLevel(end, level) && end->prev) {
00338 a = start;
00339 b = end->prev;
00340 c = end->children;
00341 d = end->lastChild;
00342 top = end;
00343 left = parsePrecedence(p, a, b, level);
00344 if(c) right = parsePrecedence(p, c, d, 0);
00345 }
00346 break;
00347 case PREC_BINARY:
00348 t = end->prev;
00349 while(t->prev) {
00350 if(tokInLevel(t, level)) {
00351 a = t->prev ? start : 0;
00352 b = t->prev;
00353 c = t->next;
00354 d = t->next ? end : 0;
00355 top = t;
00356 left = parsePrecedence(p, a, b, level);
00357 right = parsePrecedence(p, c, d, level+1);
00358 break;
00359 }
00360 t = t->prev;
00361 }
00362 break;
00363 case PREC_REVERSE:
00364 t = start->next;
00365 while(t->next) {
00366 if(tokInLevel(t, level)) {
00367 a = t->prev ? start : 0;
00368 b = t->prev;
00369 c = t->next;
00370 d = t->next ? end : 0;
00371 top = t;
00372 left = parsePrecedence(p, a, b, level+1);
00373 right = parsePrecedence(p, c, d, level);
00374 break;
00375 }
00376 t = t->next;
00377 }
00378 break;
00379 }
00380
00381
00382 if(!top)
00383 return parsePrecedence(p, start, end, level+1);
00384
00385 top->rule = rule;
00386
00387 if(left) {
00388 left->next = right;
00389 left->prev = 0;
00390 }
00391 top->children = left;
00392
00393 if(right) {
00394 right->next = 0;
00395 right->prev = left;
00396 }
00397 top->lastChild = right;
00398
00399 top->next = top->prev = 0;
00400 return top;
00401 }
00402
00403 naRef naParseCode(struct Context* c, naRef srcFile, int firstLine,
00404 char* buf, int len, int* errLine)
00405 {
00406 naRef codeObj;
00407 struct Token* t;
00408 struct Parser p;
00409
00410
00411 naTempSave(c, srcFile);
00412
00413 naParseInit(&p);
00414
00415
00416 p.errLine = *errLine = 1;
00417 if(setjmp(p.jumpHandle)) {
00418 strncpy(c->error, p.err, sizeof(c->error));
00419 *errLine = p.errLine;
00420 naParseDestroy(&p);
00421 return naNil();
00422 }
00423
00424 p.context = c;
00425 p.srcFile = srcFile;
00426 p.firstLine = firstLine;
00427 p.buf = buf;
00428 p.len = len;
00429
00430
00431 naLex(&p);
00432
00433
00434 t = p.tree.children;
00435 p.tree.children = p.tree.lastChild = 0;
00436 parseBlock(&p, &p.tree, -1, &t);
00437 if(t) oops(&p);
00438
00439
00440 t = parsePrecedence(&p, p.tree.children, p.tree.lastChild, 0);
00441 t->prev = t->next = 0;
00442 p.tree.children = t;
00443 p.tree.lastChild = t;
00444
00445
00446 codeObj = naCodeGen(&p, &(p.tree), 0);
00447
00448
00449 naParseDestroy(&p);
00450 naTempSave(c, codeObj);
00451
00452 return codeObj;
00453 }