#include #include #include #include #include #include "bytecode.h" #include "format.h" #include "io.h" #include "lex.h" #define ELF_HEADER_SIZE 0xb0 enum map_type { MAP_LEFT_TIMES, MAP_RIGHT_TIMES, MAP_LEFT_PLUS, MAP_RIGHT_PLUS, }; static enum map_type maps[16]; static size_t mapi = 0; static char* label_names[2048]; static symbol label_symbols[2048]; static size_t labeli = 0; enum map_type pop(void) { if (mapi <= 0) { fprintf(stderr, "unmatched }\n"); exit(1); } return maps[--mapi]; } void push(enum map_type type) { if (mapi >= 16) { fprintf(stderr, "out of maps\n"); exit(1); } maps[mapi++] = type; } symbol lookup_label(const char* name) { for (size_t i = 0; i < labeli; i++) { if (strcmp(label_names[i], name) == 0) { fprintf(stderr, "%s\n", name); return label_symbols[i]; } } if (labeli >= 2048) { fprintf(stderr, "out of labels\n"); exit(1); } fprintf(stderr, "%s:\n", name); unsigned long len = strlen(name) + 1; label_names[labeli] = malloc(len); memcpy(label_names[labeli], name, len); label_symbols[labeli] = new_symbol(); return label_symbols[labeli++]; } void nomap(void) { if (mapi > 0) { fprintf(stderr, "expected all maps to be closed before new label or EOF\n"); exit(1); } } void begin_map(enum map_type type) { if (next().type != TOK_MAP_BEGIN) { fprintf(stderr, "expected {\n"); exit(1); } push(type); } symbol compile(void) { symbol entry_point = init_bytecode(); while (true) { struct token tok = next(); switch (tok.type) { case TOK_COMM: comm(); break; case TOK_ASSOCL: assocl(); break; case TOK_ASSOCR: assocr(); break; case TOK_DISTL: distl(); break; case TOK_DISTR: distr(); break; case TOK_FACTL: factl(); break; case TOK_FACTR: factr(); break; case TOK_MAPL: begin_map(MAP_LEFT_TIMES); mapl_begin(); break; case TOK_MAPR: begin_map(MAP_RIGHT_TIMES); mapr_begin(); break; case TOK_UNITIL: unitil(); break; case TOK_UNITIR: unitir(); break; case TOK_UNITEL: unitel(); break; case TOK_UNITER: uniter(); break; case TOK_COMM_PLUS: comm_plus(); break; case TOK_ASSOCL_PLUS: assocl_plus(); break; case TOK_ASSOCR_PLUS: assocr_plus(); break; case TOK_MAPL_PLUS: begin_map(MAP_LEFT_PLUS); mapl_plus_begin(); break; case TOK_MAPR_PLUS: begin_map(MAP_RIGHT_PLUS); mapr_plus_begin(); break; case TOK_INL: inl(); break; case TOK_INR: inr(); break; case TOK_OUT: out(); break; case TOK_HALT: halt(); break; case TOK_LABEL: nomap(); define_executable_symbol(lookup_label(tok.identifier)); break; case TOK_JUMP: fprintf(stderr, "!jump %s\n", tok.identifier); nomap(); jump(lookup_label(tok.identifier)); break; case TOK_MAP_BEGIN: fprintf(stderr, "unexpected {\n"); exit(1); break; case TOK_MAP_END: ; enum map_type type = pop(); switch (type) { case MAP_LEFT_TIMES: mapl_end(); break; case MAP_RIGHT_TIMES: mapr_end(); break; case MAP_LEFT_PLUS: mapl_plus_end(); break; case MAP_RIGHT_PLUS: mapr_plus_end(); break; } break; case TOK_EOF: goto eof; case TOK_IF: nomap(); struct token a = next(); struct token b = next(); fprintf(stderr, "!if %s %s\n", a.identifier, b.identifier); symbol aa = lookup_label(a.identifier); symbol bb = lookup_label(b.identifier); if (a.type != TOK_JUMP || b.type != TOK_JUMP) { fprintf(stderr, "arguments to 'if' should be labels\n"); exit(1); } jump_if(aa, bb); break; } } eof: nomap(); finish_bytecode(); return entry_point; } int main(int argc, char** argv) { if (argc != 3) { fprintf(stderr, "usage: %s \n", argv[0]); exit(1); } open_files(argv[2], argv[1]); elf_executable(); symbol entry_point = compile(); finish_executable(entry_point); close_files(); return 0; }