compiler0.c (36519B)
1 // Copyright 2022, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0. 3 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <stdarg.h> 7 #include <stdint.h> 8 #include <stdbool.h> 9 #include <string.h> 10 11 #include <fcntl.h> 12 #include <unistd.h> 13 14 // builtin types 15 #define nil 0 16 typedef uint32_t u32; 17 typedef int32_t i32; 18 typedef uint8_t u8; 19 20 typedef uint32_t token_t; 21 22 void error(const char *fmt, ...); 23 24 // ------------------------------------------------------------------ 25 // structures 26 27 typedef struct String String; 28 typedef struct Symbol Symbol; 29 typedef struct Scope Scope; 30 typedef struct Type Type; 31 32 struct String { 33 String *next; 34 u32 len; 35 char text[0]; 36 }; 37 38 struct Symbol { 39 Symbol *next; 40 String *name; 41 Type *type; 42 u32 kind; 43 }; 44 enum { 45 SYMBOL_VAR, 46 SYMBOL_FLD, // struct field 47 SYMBOL_PTR, // struct *field 48 SYMBOL_DEF, // enum 49 SYMBOL_FN, 50 }; 51 52 struct Scope { 53 Scope *parent; 54 Symbol *first; 55 Symbol *last; 56 u32 kind; 57 }; 58 enum { 59 SCOPE_GLOBAL, 60 SCOPE_FUNC, 61 SCOPE_BLOCK, 62 SCOPE_LOOP, 63 SCOPE_STRUCT, 64 }; 65 66 struct Type { 67 Type *next; 68 String *name; 69 Type *of; // for: slice, array, ptr 70 Symbol *fields; // for: struct 71 u32 kind; 72 u32 count; // for: arrays 73 }; 74 enum { 75 TYPE_VOID, 76 TYPE_BOOL, 77 TYPE_U8, 78 TYPE_U32, 79 // TYPE_NIL, 80 // TYPE_POINTER, 81 TYPE_ARRAY, 82 TYPE_SLICE, 83 TYPE_STR, 84 TYPE_STRUCT, 85 // TYPE_FUNC, 86 TYPE_ENUM, 87 TYPE_UNDEFINED, 88 }; 89 90 typedef struct Ctx Ctx; 91 92 // ------------------------------------------------------------------ 93 // compiler global context 94 95 struct Ctx { 96 const char* filename; // filename of active source 97 const char* outname; // base name for output files 98 int fd; 99 100 FILE *fp_decl; // output files 101 FILE *fp_type; 102 FILE *fp_impl; 103 104 int nl_decl; // flag to update #line 105 int nl_type; 106 int nl_impl; 107 108 u8 iobuffer[1024]; // scanner file io buffer 109 u32 ionext; 110 u32 iolast; 111 112 u32 linenumber; // line number of most recent line 113 u32 lineoffset; // position of start of most recent line 114 u32 byteoffset; // position of the most recent character 115 u32 flags; 116 u32 cc; // scanner: next character 117 118 token_t tok; // most recent token 119 u32 num; // used for tNUM 120 char tmp[256]; // used for tIDN, tSTR; 121 String *ident; // used for tIDN 122 123 String *stringlist; // all strings 124 Type *typelist; // all types 125 126 Scope *scope; // scope stack 127 Scope *fn; // args of active function being parsed 128 129 Scope global; 130 131 String *idn_if; // identifier strings 132 String *idn_fn; 133 String *idn_for; 134 String *idn_var; 135 String *idn_nil; 136 String *idn_new; 137 String *idn_case; 138 String *idn_else; 139 String *idn_enum; 140 String *idn_true; 141 String *idn_break; 142 String *idn_while; 143 String *idn_false; 144 String *idn_switch; 145 String *idn_struct; 146 String *idn_return; 147 String *idn_continue; 148 149 Type *type_void; // base types 150 Type *type_bool; 151 Type *type_str; 152 Type *type_u32; 153 Type *type_i32; 154 Type *type_u8; 155 156 char *outptr; 157 char outbuf[4096]; 158 }; 159 160 Ctx ctx; 161 162 // ------------------------------------------------------------------ 163 164 String *string_make(const char* text, u32 len) { 165 // obviously this wants to be a hash table 166 String *str = ctx.stringlist; 167 while (str != nil) { 168 if ((str->len == len) && (memcmp(text, str->text, len) == 0)) { 169 return str; 170 } 171 str = str->next; 172 } 173 174 str = malloc(sizeof(String) + len + 1); 175 str->len = len; 176 memcpy(str->text, text, len); 177 str->text[len] = 0; 178 str->next = ctx.stringlist; 179 ctx.stringlist = str; 180 181 return str; 182 } 183 184 Scope *scope_push(u32 kind) { 185 Scope *scope = malloc(sizeof(Scope)); 186 scope->first = nil; 187 scope->last = nil; 188 scope->parent = ctx.scope; 189 scope->kind = kind; 190 ctx.scope = scope; 191 return scope; 192 } 193 194 Scope *scope_pop(void) { 195 Scope *scope = ctx.scope; 196 ctx.scope = scope->parent; 197 return scope; 198 } 199 200 Scope *scope_find(u32 scope_kind) { 201 Scope *scope = ctx.scope; 202 while (scope != nil) { 203 if (scope->kind == scope_kind) { 204 return scope; 205 } 206 scope = scope->parent; 207 } 208 return nil; 209 } 210 211 Symbol *symbol_find_in(String *name, Scope *scope) { 212 for (Symbol *sym = scope->first; sym != nil; sym = sym->next) { 213 if (sym->name == name) { 214 return sym; 215 } 216 } 217 return nil; 218 } 219 220 // find the first surrounding scope of a specified kind 221 Symbol *symbol_find(String *name) { 222 for (Scope *scope = ctx.scope; scope != nil; scope = scope->parent) { 223 Symbol *sym = symbol_find_in(name, scope); 224 if (sym != nil) { 225 return sym; 226 } 227 } 228 return nil; 229 } 230 231 Symbol *symbol_make_in_scope(String *name, Type *type, Scope *scope) { 232 Symbol *sym = malloc(sizeof(Symbol)); 233 sym->name = name; 234 sym->type = type; 235 sym->next = nil; 236 sym->kind = SYMBOL_VAR; 237 if (scope->first == nil) { 238 scope->first = sym; 239 } else { 240 scope->last->next = sym; 241 } 242 scope->last = sym; 243 return sym; 244 } 245 246 Symbol *symbol_make_global(String *name, Type *type) { 247 return symbol_make_in_scope(name, type, &ctx.global); 248 } 249 250 Symbol *symbol_make(String *name, Type *type) { 251 return symbol_make_in_scope(name, type, ctx.scope); 252 } 253 254 Type *type_make(String *name, u32 kind, Type *of, Symbol *fields, u32 count) { 255 Type *type = malloc(sizeof(Type)); 256 type->name = name; 257 type->of = of; 258 type->fields = fields; 259 type->kind = kind; 260 type->count = count; 261 if (name != nil) { 262 type->next = ctx.typelist; 263 ctx.typelist = type; 264 } else { 265 type->next = nil; 266 } 267 return type; 268 } 269 270 Type *type_find(String *name) { 271 for (Type *t = ctx.typelist; t != nil; t = t->next) { 272 if (t->name == name) { 273 return t; 274 } 275 } 276 return nil; 277 } 278 279 Symbol *type_find_field(Type *type, String *name) { 280 if (type->kind != TYPE_STRUCT) { 281 error("not a struct"); 282 } 283 for (Symbol *s = type->fields; s != nil; s = s->next) { 284 if (s->name == name) { 285 return s; 286 } 287 } 288 error("struct has no such field '%s'", name->text); 289 return nil; 290 } 291 292 // ================================================================ 293 294 enum { 295 cfVisibleEOL = 1, 296 cfAbortOnError = 2, 297 cfTraceCodeGen = 3, 298 }; 299 300 void ctx_init() { 301 memset(&ctx, 0, sizeof(ctx)); 302 303 // pre-intern keywords 304 ctx.idn_if = string_make("if", 2); 305 ctx.idn_fn = string_make("fn", 2); 306 ctx.idn_for = string_make("for", 3); 307 ctx.idn_var = string_make("var", 3); 308 ctx.idn_nil = string_make("nil", 3); 309 ctx.idn_new = string_make("new", 3); 310 ctx.idn_case = string_make("case", 4); 311 ctx.idn_else = string_make("else", 4); 312 ctx.idn_enum = string_make("enum", 4); 313 ctx.idn_true = string_make("true", 4); 314 ctx.idn_break = string_make("break", 5); 315 ctx.idn_while = string_make("while", 5); 316 ctx.idn_false = string_make("false", 5); 317 ctx.idn_switch = string_make("switch", 6); 318 ctx.idn_struct = string_make("struct", 6); 319 ctx.idn_return = string_make("return", 6); 320 ctx.idn_continue = string_make("continue", 8); 321 322 ctx.type_void = type_make(string_make("void", 4), TYPE_VOID, nil, nil, 0); 323 ctx.type_bool = type_make(string_make("bool", 4), TYPE_BOOL, nil, nil, 0); 324 ctx.type_str = type_make(string_make("str", 3), TYPE_STR, nil, nil, 0); 325 ctx.type_u32 = type_make(string_make("u32", 3), TYPE_U32, nil, nil, 0); 326 ctx.type_i32 = type_make(string_make("i32", 3), TYPE_U32, nil, nil, 0); 327 ctx.type_u8 = type_make(string_make("u8", 2), TYPE_U8, nil, nil, 0); 328 329 ctx.scope = &(ctx.global); 330 331 ctx.outptr = ctx.outbuf; 332 } 333 334 void dump_file_line(const char* fn, u32 offset); 335 void dump_error_ctxt(); 336 337 void error(const char *fmt, ...) { 338 va_list ap; 339 340 fprintf(stderr,"\n%s:%d: ", ctx.filename, ctx.linenumber); 341 va_start(ap, fmt); 342 vfprintf(stderr, fmt, ap); 343 va_end(ap); 344 345 if (ctx.linenumber > 0) { 346 // dump_file_line(ctx.filename, ctx.lineoffset); 347 } 348 fprintf(stderr, "\n"); 349 350 #if 0 351 dump_error_ctxt(); 352 #endif 353 354 if (ctx.flags & cfAbortOnError) { 355 abort(); 356 } else { 357 exit(1); 358 } 359 } 360 361 #define DECL ctx.fp_decl 362 #define TYPE ctx.fp_type 363 #define IMPL ctx.fp_impl 364 365 void emit(FILE* fp, const char *fmt, ...) { 366 va_list ap; 367 va_start(ap, fmt); 368 vfprintf(fp, fmt, ap); 369 va_end(ap); 370 } 371 372 int indent = 0; 373 374 void emit_impl(const char *fmt, ...) { 375 va_list ap; 376 va_start(ap, fmt); 377 int n = vsnprintf(ctx.outptr, sizeof(ctx.outbuf) - (ctx.outptr - ctx.outbuf), fmt, ap); 378 va_end(ap); 379 ctx.outptr += n; 380 if (fmt[strlen(fmt) - 1] == '\n') { 381 unsigned len = ctx.outptr - ctx.outbuf; 382 // any }s reduce the indent level of the current line 383 for (unsigned n = 0; n < len; n++) { 384 if (ctx.outbuf[n] == '}') indent--; 385 } 386 for (int n = 0; n < indent; n++) { 387 fwrite(" ", 1, 4, ctx.fp_impl); 388 } 389 fwrite(ctx.outbuf, 1, len, ctx.fp_impl); 390 // any {s increase the indent level of the next line 391 for (unsigned n = 0; n < len; n++) { 392 if (ctx.outbuf[n] == '{') indent++; 393 } 394 ctx.outptr = ctx.outbuf; 395 ctx.outbuf[0] = 0; 396 } 397 } 398 399 void emit_impl_str(void) { 400 u32 n = 0; 401 emit_impl("(void*) \""); 402 while (n < 256) { 403 u32 ch = ctx.tmp[n]; 404 if (ch == 0) { 405 break; 406 } else if ((ch < ' ') || (ch > '~') || (ch == '"') || (ch == '\\')) { 407 emit_impl("\\x%02x", ch); 408 } else { 409 emit_impl("%c", ch); 410 } 411 n++; 412 } 413 emit_impl("\""); 414 } 415 416 #define emit_decl(fmt...) emit(DECL, fmt) 417 #define emit_type(fmt...) emit(TYPE, fmt) 418 419 #define KEEP_PARENS 0x10000 420 421 unsigned emit_impl_oparen(void) { 422 unsigned idx = ctx.outptr - ctx.outbuf; 423 *ctx.outptr++ = '('; 424 *ctx.outptr = 0; 425 return idx; 426 } 427 428 void emit_impl_cparen(unsigned idx) { 429 if (idx & KEEP_PARENS) { 430 *ctx.outptr++ = ')'; 431 *ctx.outptr = 0; 432 } else { 433 unsigned len = ctx.outptr - ctx.outbuf; 434 idx &= 0xFFFF; 435 memmove(ctx.outbuf + idx, ctx.outbuf + idx + 1, len - idx); 436 ctx.outptr--; 437 } 438 } 439 440 void ctx_open_source(const char* filename) { 441 ctx.filename = filename; 442 ctx.linenumber = 0; 443 444 if (ctx.fd >= 0) { 445 close(ctx.fd); 446 } 447 ctx.fd = open(filename, O_RDONLY); 448 if (ctx.fd < 0) { 449 error("cannot open file '%s'", filename); 450 } 451 ctx.ionext = 0; 452 ctx.iolast = 0; 453 ctx.linenumber = 1; 454 ctx.lineoffset = 0; 455 ctx.byteoffset = 0; 456 } 457 458 void ctx_open_output(void) { 459 char tmp[1024]; 460 ctx.nl_decl = 1; 461 ctx.nl_type = 1; 462 ctx.nl_impl = 1; 463 464 sprintf(tmp, "%s.decl.h", ctx.outname); 465 if ((ctx.fp_decl = fopen(tmp, "w")) == NULL) { 466 error("cannot open output '%s'", tmp); 467 } 468 469 sprintf(tmp, "%s.type.h", ctx.outname); 470 if ((ctx.fp_type = fopen(tmp, "w")) == NULL) { 471 error("cannot open output '%s'", tmp); 472 } 473 474 sprintf(tmp, "%s.impl.c", ctx.outname); 475 if ((ctx.fp_impl = fopen(tmp, "w")) == NULL) { 476 error("cannot open output '%s'", tmp); 477 } 478 479 emit_impl("#include <builtin.type.h>\n"); 480 emit_impl("#include \"%s.type.h\"\n", ctx.outname); 481 emit_impl("#include \"%s.decl.h\"\n", ctx.outname); 482 } 483 484 485 // ================================================================ 486 // lexical scanner 487 488 // token classes (tok & tcMASK) 489 enum { 490 tcRELOP = 0x08, tcADDOP = 0x10, tcMULOP = 0x18, 491 tcAEQOP = 0x20, tcMEQOP = 0x28, tcMASK = 0xF8, 492 }; 493 494 enum { 495 // EndMarks, Braces, Brackets Parens 496 tEOF, tEOL, tOBRACE, tCBRACE, tOBRACK, tCBRACK, tOPAREN, tCPAREN, 497 // RelOps (do not reorder) 498 tEQ, tNE, tLT, tLE, tGT, tGE, tx0E, tx0F, 499 // AddOps (do not reorder) 500 tPLUS, tMINUS, tPIPE, tCARET, tx14, tx15, tx16, tx17, 501 // MulOps (do not reorder) 502 tSTAR, tSLASH, tPERCENT, tAMP, tLEFT, tRIGHT, tx1E, tx1F, 503 // AsnOps (do not reorder) 504 tADDEQ, tSUBEQ, tOREQ, tXOREQ, tx24, tx25, tx26, tx27, 505 tMULEQ, tDIVEQ, tMODEQ, tANDEQ, tLSEQ, tRSEQ, t2E, t2F, 506 // Various, UnaryNot, LogicalOps, 507 tSEMI, tCOLON, tDOT, tCOMMA, tNOT, tAND, tOR, tBANG, 508 tASSIGN, tINC, tDEC, 509 tAT, 510 // Keywords 511 tNEW, tFN, tSTRUCT, tVAR, tENUM, 512 tIF, tELSE, tWHILE, 513 tBREAK, tCONTINUE, tRETURN, 514 tFOR, tSWITCH, tCASE, 515 tTRUE, tFALSE, tNIL, 516 tIDN, tNUM, tSTR, 517 // used internal to the lexer but never returned 518 tSPC, tINV, tDQT, tSQT, tMSC, 519 }; 520 521 const char *tnames[] = { 522 "<EOF>", "<EOL>", "{", "}", "[", "]", "(", ")", 523 "==", "!=", "<", "<=", ">", ">=", "", "", 524 "+", "-", "|", "^", "", "", "", "", 525 "*", "/", "%", "&", "<<", ">>", "", "", 526 "+=", "-=", "|=", "^=", "", "", "", "", 527 "*=", "/=", "%=", "&=", "<<=", ">>=", "", "", 528 ";", ":", ".", ",", "~", "&&", "||", "!", 529 "=", "++", "--", 530 "@", 531 "new", "fn", "struct", "var", "enum", 532 "if", "else", "while", 533 "break", "continue", "return", 534 "for", "switch", "case", 535 "true", "false", "nil", 536 "<ID>", "<NUM>", "<STR>", 537 "<SPC>", "<INV>", "<DQT>", "<SQT>", "<MSC>", 538 }; 539 540 u8 lextab[256] = { 541 tEOF, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 542 tINV, tSPC, tEOL, tSPC, tINV, tSPC, tINV, tINV, 543 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 544 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 545 tSPC, tBANG, tDQT, tMSC, tMSC, tPERCENT, tAMP, tSQT, 546 tOPAREN, tCPAREN, tSTAR, tPLUS, tCOMMA, tMINUS, tDOT, tSLASH, 547 tNUM, tNUM, tNUM, tNUM, tNUM, tNUM, tNUM, tNUM, 548 tNUM, tNUM, tCOLON, tSEMI, tLT, tASSIGN, tGT, tMSC, 549 tAT, tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, 550 tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, 551 tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, 552 tIDN, tIDN, tIDN, tOBRACK, tMSC, tCBRACK, tCARET, tIDN, 553 tMSC, tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, 554 tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, 555 tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, tIDN, 556 tIDN, tIDN, tIDN, tOBRACE, tPIPE, tCBRACE, tNOT, tINV, 557 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 558 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 559 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 560 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 561 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 562 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 563 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 564 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 565 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 566 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 567 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 568 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 569 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 570 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 571 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 572 tINV, tINV, tINV, tINV, tINV, tINV, tINV, tINV, 573 }; 574 575 i32 unhex(u32 ch) { 576 if ((ch >= '0') && (ch <= '9')) { 577 return ch - '0'; 578 } 579 if ((ch >= 'a') && (ch <= 'f')) { 580 return ch - 'a' + 10; 581 } 582 if ((ch >= 'A') && (ch <= 'F')) { 583 return ch - 'A' + 10; 584 } 585 return -1; 586 } 587 588 u32 scan() { 589 while (ctx.ionext == ctx.iolast) { 590 if (ctx.fd < 0) { 591 ctx.cc = 0; 592 return ctx.cc; 593 } 594 int r = read(ctx.fd, ctx.iobuffer, sizeof(ctx.iobuffer)); 595 if (r <= 0) { 596 ctx.fd = -1; 597 } else { 598 ctx.iolast = r; 599 ctx.ionext = 0; 600 } 601 } 602 ctx.cc = ctx.iobuffer[ctx.ionext]; 603 ctx.ionext++; 604 ctx.byteoffset++; 605 return ctx.cc; 606 } 607 608 u32 unescape(u32 n) { 609 if (n == 'n') { 610 return 10; 611 } else if (n == 'r') { 612 return 13; 613 } else if (n == 't') { 614 return 9; 615 } else if (n == '"') { 616 return '"'; 617 } else if (n == '\'') { 618 return '\''; 619 } else if (n == '\\') { 620 return '\\'; 621 } else if (n == 'x') { 622 int x0 = unhex(scan()); 623 int x1 = unhex(scan()); 624 if ((x0 < 0) || (x1 < 0)) { 625 error("invalid hex escape"); 626 } 627 return (x0 << 4) | x1; 628 } else { 629 error("invalid escape 0x%02x", n); 630 return 0; 631 } 632 } 633 634 token_t scan_string(u32 cc, u32 nc) { 635 u32 n = 0; 636 while (true) { 637 if (nc == '"') { 638 nc = scan(); 639 break; 640 } else if (nc == 0) { 641 error("unterminated string"); 642 } else if (nc == '\\') { 643 ctx.tmp[n] = unescape(scan()); 644 } else { 645 ctx.tmp[n] = nc; 646 } 647 nc = scan(); 648 n++; 649 if (n == 255) { 650 error("constant string too large"); 651 } 652 } 653 ctx.tmp[n] = 0; 654 return tSTR; 655 } 656 657 token_t scan_keyword(u32 len) { 658 ctx.tmp[len] = 0; 659 String *idn = string_make(ctx.tmp, len); 660 ctx.ident = idn; 661 662 if (len == 2) { 663 if (idn == ctx.idn_if) { return tIF; }; 664 if (idn == ctx.idn_fn) { return tFN; } 665 } else if (len == 3) { 666 if (idn == ctx.idn_for) { return tFOR; } 667 if (idn == ctx.idn_var) { return tVAR; } 668 if (idn == ctx.idn_nil) { return tNIL; } 669 if (idn == ctx.idn_new) { return tNEW; } 670 } else if (len == 4) { 671 if (idn == ctx.idn_case) { return tCASE; } 672 if (idn == ctx.idn_else) { return tELSE; } 673 if (idn == ctx.idn_enum) { return tENUM; } 674 if (idn == ctx.idn_true) { return tTRUE; } 675 } else if (len == 5) { 676 if (idn == ctx.idn_break) { return tBREAK; } 677 if (idn == ctx.idn_while) { return tWHILE; } 678 if (idn == ctx.idn_false) { return tFALSE; } 679 } else if (len == 6) { 680 if (idn == ctx.idn_switch) { return tSWITCH; } 681 if (idn == ctx.idn_struct) { return tSTRUCT; } 682 if (idn == ctx.idn_return) { return tRETURN; } 683 } else if (len == 8) { 684 if (idn == ctx.idn_continue) { return tCONTINUE; } 685 } 686 return tIDN; 687 } 688 689 token_t scan_number(u32 cc, u32 nc) { 690 u32 n = 1; 691 u32 val = cc - '0'; 692 693 if ((cc == '0') && (nc == 'b')) { // binary 694 nc = scan(); 695 while ((nc == '0') || (nc == '1')) { 696 val = (val << 1) | (nc - '0'); 697 nc = scan(); 698 n++; 699 if (n == 34) { 700 error("binary constant too large"); 701 } 702 } 703 } else if ((cc == '0') && (nc == 'x')) { // hex 704 nc = scan(); 705 while (true) { 706 int tmp = unhex(nc); 707 if (tmp == -1) { 708 break; 709 } 710 val = (val << 4) | tmp; 711 nc = scan(); 712 n++; 713 if (n == 10) { 714 error("hex constant too large"); 715 } 716 } 717 } else { // decimal 718 while (lextab[nc] == tNUM) { 719 u32 tmp = (val * 10) + (nc - '0'); 720 if (tmp <= val) { 721 error("decimal constant too large"); 722 } 723 val = tmp; 724 nc = scan(); 725 n++; 726 } 727 } 728 ctx.num = val; 729 return tNUM; 730 } 731 732 token_t scan_ident(u32 cc, u32 nc) { 733 ctx.tmp[0] = cc; 734 u32 n = 1; 735 736 while (true) { 737 u32 tok = lextab[nc]; 738 if ((tok == tIDN) || (tok == tNUM)) { 739 ctx.tmp[n] = nc; 740 n++; 741 if (n == 32) { error("identifier too large"); } 742 nc = scan(); 743 } else { 744 break; 745 } 746 } 747 return scan_keyword(n); 748 } 749 750 token_t _next() { 751 u8 nc = ctx.cc; 752 while (true) { 753 u8 cc = nc; 754 nc = scan(); 755 u32 tok = lextab[cc]; 756 if (tok == tNUM) { // 0..9 757 return scan_number(cc, nc); 758 } else if (tok == tIDN) { // _ A..Z a..z 759 return scan_ident(cc, nc); 760 } else if (tok == tDQT) { // " 761 return scan_string(cc, nc); 762 } else if (tok == tSQT) { // ' 763 ctx.num = nc; 764 if (nc == '\\') { 765 ctx.num = unescape(scan()); 766 } 767 nc = scan(); 768 if (nc != '\'') { 769 error("unterminated character constant"); 770 } 771 nc = scan(); 772 return tNUM; 773 } else if (tok == tPLUS) { 774 if (nc == '+') { tok = tINC; nc = scan(); } 775 } else if (tok == tMINUS) { 776 if (nc == '-') { tok = tDEC; nc = scan(); } 777 } else if (tok == tAMP) { 778 if (nc == '&') { tok = tAND; nc = scan(); } 779 } else if (tok == tPIPE) { 780 if (nc == '|') { tok = tOR; nc = scan(); } 781 } else if (tok == tGT) { 782 if (nc == '=') { tok = tGE; nc = scan(); } 783 else if (nc == '>') { tok = tRIGHT; nc = scan(); } 784 } else if (tok == tLT) { 785 if (nc == '=') { tok = tLE; nc = scan(); } 786 else if (nc == '<') { tok = tLEFT; nc = scan(); } 787 } else if (tok == tASSIGN) { 788 if (nc == '=') { tok = tEQ; nc = scan(); } 789 } else if (tok == tBANG) { 790 if (nc == '=') { tok = tNE; nc = scan(); } 791 } else if (tok == tSLASH) { 792 if (nc == '/') { 793 // comment -- consume until EOL or EOF 794 while ((nc != '\n') && (nc != 0)) { 795 nc = scan(); 796 } 797 continue; 798 } 799 } else if (tok == tEOL) { 800 ctx.linenumber++; 801 ctx.lineoffset = ctx.byteoffset; 802 if (ctx.flags & cfVisibleEOL) { 803 return tEOL; 804 } 805 continue; 806 } else if (tok == tSPC) { 807 continue; 808 } else if ((tok == tMSC) || (tok == tINV)) { 809 error("unknown character 0x%02x", cc); 810 } 811 812 // if we're an AddOp or MulOp, followed by an '=' 813 if (((tok & 0xF0) == 0x10) && (nc == '=')) { 814 nc = scan(); 815 // transform us to a XEQ operation 816 tok = tok + 0x10; 817 } 818 819 return tok; 820 } 821 } 822 823 void token_printstr(FILE *fp) { 824 u32 n = 0; 825 printf("\""); 826 while (n < 256) { 827 u32 ch = ctx.tmp[n]; 828 if (ch == 0) { 829 break; 830 } else if ((ch < ' ') || (ch > '~')) { 831 fprintf(fp, "\\x%02x", ch); 832 } else if ((ch == '"') || (ch == '\\')) { 833 fprintf(fp, "\\%c", ch); 834 } else { 835 fprintf(fp, "%c", ch); 836 } 837 n++; 838 } 839 printf("\""); 840 } 841 842 void token_print(FILE *fp) { 843 if (ctx.tok == tNUM) { 844 fprintf(fp, "#%u ", ctx.num); 845 } else if (ctx.tok == tIDN) { 846 fprintf(fp, "@%s ", ctx.tmp); 847 } else if (ctx.tok == tEOL) { 848 fprintf(fp, "\n"); 849 } else if (ctx.tok == tSTR) { 850 token_printstr(fp); 851 } else { 852 fprintf(fp, "%s ", tnames[ctx.tok]); 853 } 854 } 855 856 token_t next() { 857 #if 1 858 return (ctx.tok = _next()); 859 #else 860 ctx.tok = _next(); 861 token_print(stderr); 862 fprintf(stderr,"\n"); 863 return ctx.tok; 864 #endif 865 } 866 867 void expected(const char* what) { 868 error("expected %s, found %s", what, tnames[ctx.tok]); 869 } 870 871 void expect(token_t tok) { 872 if (ctx.tok != tok) { 873 error("expected %s, found %s", tnames[tok], tnames[ctx.tok]); 874 } 875 } 876 877 void require(token_t tok) { 878 expect(tok); 879 next(); 880 } 881 882 String *parse_name(const char* what) { 883 if (ctx.tok != tIDN) { 884 error("expected %s, found %s %u", what, tnames[ctx.tok], ctx.tok); 885 } 886 String *str = ctx.ident; 887 next(); 888 return str; 889 } 890 891 void parse_expr(void); 892 893 // fwd_ref_ok indicates that an undefined typename 894 // may be treated as a forward reference. This is 895 // only used for pointers (because their size does 896 // not depend on their target). 897 Type *parse_type(bool fwd_ref_ok); 898 899 int is_type(const char* typename) { 900 String *name = ctx.ident; 901 Symbol *sym = symbol_find(name); 902 if (sym == nil) { 903 error("undefined identifier '%s'", name->text); 904 } 905 return !strcmp(sym->type->name->text, typename); 906 } 907 908 // cheesy varargs for a few special purpose functions 909 void parse_va_call(const char* fn) { 910 emit_impl("({ int fd = fn_%s_begin();", fn); 911 while (ctx.tok != tCPAREN) { 912 if (ctx.tok == tAT) { 913 next(); 914 Type *type = parse_type(false); 915 if (type == ctx.type_str) { 916 emit_impl(" fn_writes(fd,"); 917 } else if (type == ctx.type_u32) { 918 emit_impl(" fn_writex(fd,"); 919 } else if (type == ctx.type_i32) { 920 emit_impl(" fn_writei(fd,"); 921 } else { 922 error("unsupported type '%s'", type->name->text); 923 } 924 } else if (ctx.tok == tSTR) { 925 emit_impl(" fn_writes(fd,"); 926 } else if (ctx.tok == tIDN) { 927 emit_impl(" fn_write%s(fd,", is_type("str") ? "s" : "x"); 928 } else { 929 emit_impl(" fn_writex(fd,"); 930 } 931 parse_expr(); 932 emit_impl(");"); 933 if (ctx.tok != tCPAREN) { 934 require(tCOMMA); 935 } 936 } 937 next(); 938 emit_impl(" fn_%s_end(); })", fn); 939 } 940 941 void parse_ident(void) { 942 String *name = ctx.ident; 943 Symbol *sym = symbol_find(name); 944 next(); 945 946 if ((sym == nil) && (ctx.tok != tOPAREN)) { 947 error("undefined identifier '%s'", name->text); 948 } 949 950 if (ctx.tok == tOPAREN) { 951 // function call 952 next(); 953 if (!strcmp(name->text, "error")) { 954 parse_va_call("error"); 955 return; 956 } 957 emit_impl("fn_%s(", name->text); 958 while (ctx.tok != tCPAREN) { 959 parse_expr(); 960 if (ctx.tok != tCPAREN) { 961 require(tCOMMA); 962 emit_impl(", "); 963 } 964 } 965 next(); 966 emit_impl(")"); 967 } else { 968 // variable access 969 if (sym->kind == SYMBOL_DEF) { 970 emit_impl("c$%s", sym->name->text); 971 } else { 972 emit_impl("$%s", sym->name->text); 973 } 974 } 975 976 while (1) { 977 if (ctx.tok == tDOT) { 978 // field access 979 next(); 980 String *fieldname = parse_name("field name"); 981 emit_impl("->%s", fieldname->text); 982 } else if (ctx.tok == tOBRACK) { 983 // array access 984 next(); 985 emit_impl("["); 986 parse_expr(); 987 emit_impl("]"); 988 require(tCBRACK); 989 } else { 990 return; 991 } 992 } 993 } 994 995 void parse_primary_expr(void) { 996 if (ctx.tok == tNUM) { 997 emit_impl("0x%x", ctx.num); 998 } else if (ctx.tok == tSTR) { 999 emit_impl_str(); 1000 } else if (ctx.tok == tTRUE) { 1001 emit_impl("1"); 1002 } else if (ctx.tok == tFALSE) { 1003 emit_impl("0"); 1004 } else if (ctx.tok == tNIL) { 1005 emit_impl("0"); 1006 } else if (ctx.tok == tOPAREN) { 1007 next(); 1008 parse_expr(); 1009 require(tCPAREN); 1010 return; 1011 } else if (ctx.tok == tNEW) { 1012 next(); 1013 require(tOPAREN); 1014 String *typename = parse_name("type name"); 1015 require(tCPAREN); 1016 emit_impl("calloc(1,sizeof(t$%s))", typename->text); 1017 return; 1018 } else if (ctx.tok == tIDN) { 1019 parse_ident(); 1020 return; 1021 } else { 1022 error("invalid expression"); 1023 } 1024 next(); 1025 } 1026 1027 void parse_unary_expr(void) { 1028 u32 op = ctx.tok; 1029 if (op == tPLUS) { 1030 next(); 1031 parse_unary_expr(); 1032 } else if (op == tMINUS) { 1033 emit_impl("(-"); 1034 next(); 1035 parse_unary_expr(); 1036 emit_impl(")"); 1037 } else if (op == tBANG) { 1038 emit_impl("(!"); 1039 next(); 1040 parse_unary_expr(); 1041 emit_impl(")"); 1042 } else if (op == tNOT) { 1043 emit_impl("(~"); 1044 next(); 1045 parse_unary_expr(); 1046 emit_impl(")"); 1047 } else if (op == tAMP) { 1048 error("dereference not supported"); 1049 next(); 1050 parse_unary_expr(); 1051 } else { 1052 return parse_primary_expr(); 1053 } 1054 } 1055 1056 void parse_mul_expr(void) { 1057 unsigned x = emit_impl_oparen(); 1058 parse_unary_expr(); 1059 while ((ctx.tok & tcMASK) == tcMULOP) { 1060 emit_impl(" %s ", tnames[ctx.tok]); 1061 next(); 1062 parse_unary_expr(); 1063 x |= KEEP_PARENS; 1064 } 1065 emit_impl_cparen(x); 1066 } 1067 1068 void parse_add_expr(void) { 1069 unsigned x = emit_impl_oparen(); 1070 parse_mul_expr(); 1071 while ((ctx.tok & tcMASK) == tcADDOP) { 1072 emit_impl(" %s ", tnames[ctx.tok]); 1073 next(); 1074 parse_mul_expr(); 1075 x |= KEEP_PARENS; 1076 } 1077 emit_impl_cparen(x); 1078 } 1079 1080 void parse_rel_expr(void) { 1081 unsigned x = emit_impl_oparen(); 1082 parse_add_expr(); 1083 if ((ctx.tok & tcMASK) == tcRELOP) { 1084 emit_impl(" %s ", tnames[ctx.tok]); 1085 next(); 1086 parse_add_expr(); 1087 x |= KEEP_PARENS; 1088 } 1089 emit_impl_cparen(x); 1090 } 1091 1092 void parse_and_expr(void) { 1093 unsigned x = emit_impl_oparen(); 1094 parse_rel_expr(); 1095 if (ctx.tok == tAND) { 1096 while (ctx.tok == tAND) { 1097 emit_impl(" && "); 1098 next(); 1099 parse_rel_expr(); 1100 } 1101 x |= KEEP_PARENS; 1102 } 1103 emit_impl_cparen(x); 1104 } 1105 1106 void parse_expr(void) { 1107 unsigned x = emit_impl_oparen(); 1108 parse_and_expr(); 1109 if (ctx.tok == tOR) { 1110 while (ctx.tok == tOR) { 1111 emit_impl(" || "); 1112 next(); 1113 parse_and_expr(); 1114 } 1115 x |= KEEP_PARENS; 1116 } 1117 emit_impl_cparen(x); 1118 } 1119 1120 Type *parse_struct_type(String *name) { 1121 Type *rectype = type_find(name); 1122 1123 if (rectype) { 1124 if (rectype->kind == TYPE_UNDEFINED) { 1125 // resolve forward ref 1126 rectype->kind = TYPE_STRUCT; 1127 } else { 1128 error("Cannot redefine struct '%s'", name->text); 1129 } 1130 } else { 1131 rectype = type_make(name, TYPE_STRUCT, nil, nil, 0); 1132 }; 1133 scope_push(SCOPE_STRUCT); 1134 require(tOBRACE); 1135 emit_type("typedef struct t$%s t$%s;\n", name->text, name->text); 1136 emit_decl("struct t$%s {\n", name->text); 1137 while (true) { 1138 if (ctx.tok == tCBRACE) { 1139 next(); 1140 break; 1141 } 1142 String *fname = parse_name("field name"); 1143 bool ptr = (ctx.tok == tSTAR); 1144 if (ptr) next(); 1145 Type *type = parse_type(true); 1146 emit_decl(" t$%s %s%s;\n", type->name->text, ptr ? "*" : "", fname->text); 1147 Symbol *sym = symbol_make(fname, type); 1148 sym->kind = ptr ? SYMBOL_PTR : SYMBOL_FLD; 1149 if (ctx.tok != tCBRACE) { 1150 require(tCOMMA); 1151 } 1152 } 1153 emit_decl("};\n"); // xxx was _type 1154 rectype->fields = scope_pop()->first; 1155 return rectype; 1156 } 1157 1158 Type *parse_array_type(void) { 1159 Type *type; 1160 u32 nelem = 0; 1161 char tmp[256]; 1162 if (ctx.tok == tCBRACK) { 1163 next(); 1164 type = type_make(nil, TYPE_ARRAY, parse_type(false), nil, 0); 1165 } else { 1166 if (ctx.tok != tNUM) { 1167 error("array size must be numeric"); 1168 } 1169 nelem = ctx.num; 1170 next(); 1171 require(tCBRACK); 1172 type = type_make(nil, TYPE_ARRAY, parse_type(false), nil, nelem); 1173 } 1174 sprintf(tmp, "%s$%u", type->of->name->text, nelem); 1175 type->name = string_make(tmp, strlen(tmp)); 1176 if (nelem == 0) { 1177 emit_type("typedef t$%s t$%s[];\n", type->of->name->text, type->name->text); 1178 } else { 1179 emit_type("typedef t$%s t$%s[%u];\n", type->of->name->text, type->name->text, nelem); 1180 } 1181 return type; 1182 } 1183 1184 Type *parse_type(bool fwd_ref_ok) { 1185 if (ctx.tok == tSTAR) { // pointer-to 1186 error("pointer types not supported"); 1187 //next(); 1188 //return type_make(nil, TYPE_POINTER, parse_type(true), nil, 0); 1189 } else if (ctx.tok == tOBRACK) { // array-of 1190 next(); 1191 return parse_array_type(); 1192 } else if (ctx.tok == tFN) { 1193 error("func types not supported"); 1194 //next(); 1195 //return parse_func_type(); 1196 } else if (ctx.tok == tSTRUCT) { 1197 error ("anonymous struct types not supported"); 1198 //next(); 1199 //return parse_struct_type(nil); 1200 } else if (ctx.tok == tIDN) { 1201 String *name = ctx.ident; 1202 next(); 1203 Type *type = type_find(name); 1204 if (type == nil) { 1205 if (fwd_ref_ok) { 1206 type = type_make(name, TYPE_UNDEFINED, nil, nil, 0); 1207 } else { 1208 error("undefined type '%s' not usable here", name->text); 1209 } 1210 } 1211 return type; 1212 } else { 1213 expected("type"); 1214 } 1215 return nil; 1216 } 1217 1218 void parse_block(void); 1219 1220 void parse_while(void) { 1221 emit_impl("while ("); 1222 parse_expr(); 1223 require(tOBRACE); 1224 scope_push(SCOPE_LOOP); 1225 emit_impl(") {\n"); 1226 parse_block(); 1227 scope_pop(); 1228 emit_impl("}\n"); 1229 } 1230 1231 void parse_if(void) { 1232 // if expr { block } 1233 emit_impl("if ("); 1234 parse_expr(); 1235 emit_impl(") {\n"); 1236 require(tOBRACE); 1237 scope_push(SCOPE_BLOCK); 1238 parse_block(); 1239 scope_pop(); 1240 while (ctx.tok == tELSE) { 1241 next(); 1242 // ... else ... 1243 if (ctx.tok == tIF) { 1244 // ... if expr { block } 1245 emit_impl("} else if "); 1246 next(); 1247 parse_expr(); 1248 require(tOBRACE); 1249 emit_impl(" {\n"); 1250 scope_push(SCOPE_BLOCK); 1251 parse_block(); 1252 scope_pop(); 1253 } else { 1254 // ... { block } 1255 emit_impl("} else {\n"); 1256 require(tOBRACE); 1257 scope_push(SCOPE_BLOCK); 1258 parse_block(); 1259 scope_pop(); 1260 break; 1261 } 1262 } 1263 emit_impl("}\n"); 1264 } 1265 1266 void parse_return(void) { 1267 if (ctx.tok == tSEMI) { 1268 // error("function requires return type"); 1269 next(); 1270 emit_impl("return;\n"); 1271 } else { 1272 // error("return types do not match"); 1273 emit_impl("return "); 1274 parse_expr(); 1275 emit_impl(";\n"); 1276 require(tSEMI); 1277 } 1278 } 1279 1280 void parse_break(void) { 1281 // XXX break-to-labeled-loop support 1282 Scope *scope = scope_find(SCOPE_LOOP); 1283 if (scope == nil) { 1284 error("break must be used from inside a looping construct"); 1285 } 1286 require(tSEMI); 1287 emit_impl("break;\n"); 1288 } 1289 1290 void parse_continue(void) { 1291 // XXX continue-to-labeled-loop support 1292 Scope *scope = scope_find(SCOPE_LOOP); 1293 if (scope == nil) { 1294 error("continue must be used from inside a looping construct"); 1295 } 1296 require(tSEMI); 1297 emit_impl("continue;\n"); 1298 } 1299 1300 void parse_struct_init(Symbol *var) { 1301 while (true) { 1302 if (ctx.tok == tCBRACE) { 1303 next(); 1304 break; 1305 } 1306 String *name = parse_name("field name"); 1307 Symbol *field = var->type->fields; 1308 while (true) { 1309 if (field == nil) { 1310 error("structure has no '%s' field", name->text); 1311 } 1312 if (field->name == name) { 1313 break; 1314 } 1315 field = field->next; 1316 } 1317 require(tCOLON); 1318 if (ctx.tok == tOBRACE) { 1319 next(); 1320 emit_impl("{"); 1321 parse_struct_init(field); 1322 emit_impl("}"); 1323 } else { 1324 parse_expr(); 1325 //emit_impl( "0x%x", ctx.num); 1326 } 1327 emit_impl( ","); 1328 if (ctx.tok != tCBRACE) { 1329 require(tCOMMA); 1330 } 1331 } 1332 } 1333 1334 void parse_array_init(Symbol *var) { 1335 while (true) { 1336 if (ctx.tok == tCBRACE) { 1337 next(); 1338 break; 1339 } 1340 parse_expr(); 1341 emit_impl(","); 1342 if (ctx.tok != tCBRACE) { 1343 require(tCOMMA); 1344 } 1345 } 1346 } 1347 1348 void parse_var(void) { 1349 String *name = parse_name("variable name"); 1350 Type *type = parse_type(false); 1351 Symbol *var = symbol_make(name, type); 1352 1353 if (ctx.tok == tASSIGN) { 1354 next(); 1355 if (ctx.tok == tOBRACE) { 1356 next(); 1357 if (type->kind == TYPE_STRUCT) { 1358 emit_impl("t$%s $$%s = {\n", type->name->text, name->text); 1359 parse_struct_init(var); 1360 emit_impl("\n};\nt$%s *$%s = &$$%s;\n", 1361 type->name->text, name->text, name->text); 1362 } else if (type->kind == TYPE_ARRAY) { 1363 emit_impl("t$%s $%s = {\n", type->name->text, name->text); 1364 parse_array_init(var); 1365 emit_impl("\n};\n"); 1366 } else { 1367 error("type %s cannot be initialized with {} expr", type->name->text); 1368 } 1369 } else { 1370 emit_impl("t$%s %s$%s = ", type->name->text, 1371 (type->kind == TYPE_STRUCT) ? "*" : "", 1372 name->text); 1373 parse_expr(); 1374 emit_impl(";\n"); 1375 } 1376 } else { 1377 if (type->kind == TYPE_ARRAY) { 1378 emit_impl("t$%s $%s = { 0, };\n", type->name->text, name->text); 1379 } else { 1380 emit_impl("t$%s %s$%s = 0;\n", type->name->text, 1381 (type->kind == TYPE_STRUCT) ? "*" : "", 1382 name->text); 1383 } 1384 } 1385 require(tSEMI); 1386 1387 } 1388 1389 void parse_expr_statement(void) { 1390 parse_expr(); 1391 if (ctx.tok == tASSIGN) { 1392 emit_impl(" = "); 1393 next(); 1394 parse_expr(); 1395 } else if ((ctx.tok & tcMASK) == tcAEQOP) { 1396 emit_impl(" %s ", tnames[ctx.tok]); 1397 next(); 1398 parse_expr(); 1399 } else if ((ctx.tok & tcMASK) == tcMEQOP) { 1400 emit_impl(" %s ", tnames[ctx.tok]); 1401 next(); 1402 parse_expr(); 1403 } else if ((ctx.tok == tINC) || (ctx.tok == tDEC)) { 1404 emit_impl(" %s", tnames[ctx.tok]); 1405 next(); 1406 } 1407 require(tSEMI); 1408 emit_impl(";\n"); 1409 } 1410 1411 void parse_block(void) { 1412 while (true) { 1413 if (ctx.tok == tCBRACE) { 1414 next(); 1415 break; 1416 } else if (ctx.tok == tRETURN) { 1417 next(); 1418 parse_return(); 1419 } else if (ctx.tok == tBREAK) { 1420 next(); 1421 parse_break(); 1422 } else if (ctx.tok == tCONTINUE) { 1423 next(); 1424 parse_continue(); 1425 } else if (ctx.tok == tWHILE) { 1426 next(); 1427 parse_while(); 1428 } else if (ctx.tok == tIF) { 1429 next(); 1430 parse_if(); 1431 } else if (ctx.tok == tVAR) { 1432 next(); 1433 parse_var(); 1434 } else if (ctx.tok == tSEMI) { 1435 next(); 1436 // empty statement 1437 continue; 1438 } else { 1439 parse_expr_statement(); 1440 } 1441 } 1442 } 1443 1444 Symbol *parse_param(String *fname) { 1445 String *pname = parse_name("parameter name"); 1446 Type *ptype = parse_type(false); 1447 1448 // arrays and structs are always passed as reference parameters 1449 //if ((ptype->kind == TYPE_ARRAY) || (ptype->kind == TYPE_RECORD)) { 1450 // ptype = type_make_ptr(ptype); 1451 //} 1452 1453 if (symbol_find(pname)) { 1454 error("duplicate parameter name '%s'", pname->text); 1455 } 1456 1457 return symbol_make(pname, ptype); 1458 } 1459 1460 void parse_function(void) { 1461 String *fname = parse_name("function name"); 1462 Type *rtype = ctx.type_void; 1463 1464 scope_push(SCOPE_FUNC); 1465 1466 require(tOPAREN); 1467 if (ctx.tok != tCPAREN) { 1468 parse_param(fname); 1469 while (ctx.tok == tCOMMA) { 1470 next(); 1471 parse_param(fname); 1472 } 1473 } 1474 require(tCPAREN); 1475 1476 if (ctx.tok != tOBRACE) { 1477 rtype = parse_type(false); 1478 } 1479 1480 emit_decl("t$%s%s fn_%s(", rtype->name->text, 1481 rtype->kind == TYPE_STRUCT ? "*" : "", fname->text); 1482 emit_impl("t$%s%s fn_%s(", rtype->name->text, 1483 rtype->kind == TYPE_STRUCT ? "*" : "", fname->text); 1484 for (Symbol *s = ctx.scope->first; s != nil; s = s->next) { 1485 emit_decl("t$%s %s$%s%s", 1486 s->type->name->text, 1487 s->type->kind == TYPE_STRUCT ? "*" : "", 1488 s->name->text, s->next ? ", " : ""); 1489 emit_impl("t$%s %s$%s%s", 1490 s->type->name->text, 1491 s->type->kind == TYPE_STRUCT ? "*" : "", 1492 s->name->text, s->next ? ", " : ""); 1493 } 1494 emit_decl("%s);\n", ctx.scope->first ? "" : "t$void"); 1495 emit_impl("%s) {\n", ctx.scope->first ? "" : "t$void"); 1496 1497 // TODO: more complete type if needed... 1498 Symbol *sym = symbol_make_global(fname, rtype); 1499 sym->kind = SYMBOL_FN; 1500 1501 require(tOBRACE); 1502 1503 scope_push(SCOPE_BLOCK); 1504 parse_block(); 1505 scope_pop(); 1506 1507 emit_impl("}\n"); 1508 1509 scope_pop(); 1510 } 1511 1512 void parse_enum_def(void) { 1513 if (ctx.tok == tIDN) { 1514 String *name = parse_name("enum name"); 1515 type_make(name, TYPE_ENUM, nil, nil, 0); 1516 emit_type("typedef t$u32 t$%s; // enum\n", name->text); 1517 } 1518 1519 require(tOBRACE); 1520 u32 val = 0; 1521 while (ctx.tok != tCBRACE) { 1522 String *name = parse_name("enum tag name"); 1523 Symbol *sym = symbol_find(name); 1524 if (sym != nil) { 1525 error("cannot redefine %s as enum tag\n", name->text); 1526 } 1527 symbol_make_global(name, ctx.type_u32)->kind = SYMBOL_DEF; 1528 emit_impl("#define c$%s ", name->text, val); 1529 if (ctx.tok == tASSIGN) { 1530 next(); 1531 parse_expr(); 1532 emit_impl("\n"); 1533 } else { 1534 emit_impl("0x%x\n", val); 1535 val++; 1536 } 1537 require(tCOMMA); 1538 } 1539 require(tCBRACE); 1540 require(tSEMI); 1541 } 1542 1543 void parse_begin() { 1544 emit_impl("\n#include <library.impl.h>\n"); 1545 } 1546 1547 void parse_program() { 1548 next(); 1549 for (;;) { 1550 if (ctx.tok == tENUM) { 1551 next(); 1552 parse_enum_def(); 1553 } else if (ctx.tok == tSTRUCT) { 1554 next(); 1555 String *name = parse_name("struct name"); 1556 parse_struct_type(name); 1557 require(tSEMI); 1558 } else if (ctx.tok == tFN) { 1559 next(); 1560 parse_function(); 1561 } else if (ctx.tok == tVAR) { 1562 next(); 1563 parse_var(); 1564 } else if (ctx.tok == tEOF) { 1565 return; 1566 } else { 1567 expected("function, variable, or type definition"); 1568 } 1569 } 1570 1571 } 1572 1573 void parse_end() { 1574 emit_impl("\n#include <library.impl.c>\n"); 1575 } 1576 1577 // ================================================================ 1578 1579 int main(int argc, char **argv) { 1580 bool first = true; 1581 1582 ctx_init(); 1583 ctx.filename = "<commandline>"; 1584 ctx.outname = nil; 1585 1586 while (argc > 1) { 1587 if (!strcmp(argv[1],"-o")) { 1588 if (argc < 2) { 1589 error("option -o requires argument"); 1590 } 1591 ctx.outname = argv[2]; 1592 argc--; 1593 argv++; 1594 } else if (!strcmp(argv[1], "-A")) { 1595 ctx.flags |= cfAbortOnError; 1596 } else if (argv[1][0] == '-') { 1597 error("unknown option: %s", argv[1]); 1598 } else { 1599 ctx.filename = argv[1]; 1600 if (ctx.outname == nil) { 1601 ctx.outname = ctx.filename; 1602 } 1603 1604 ctx_open_source(ctx.filename); 1605 ctx.linenumber = 1; 1606 ctx.lineoffset = 0; 1607 1608 // prime the lexer 1609 scan(); 1610 1611 if (first) { 1612 first = false; 1613 ctx_open_output(); 1614 parse_begin(); 1615 } 1616 parse_program(); 1617 } 1618 argc--; 1619 argv++; 1620 } 1621 1622 if (ctx.filename == nil) { 1623 printf( 1624 "usage: compiler [ <option> | <sourcefilename> ]*\n" 1625 "\n" 1626 "options: -o <filename> output base name (default source name)\n" 1627 " -A abort on error\n"); 1628 return 0; 1629 } 1630 1631 parse_end(); 1632 1633 return 0; 1634 }