#include #include #include #include #include "lexer.h" #include "common.h" #include "error.h" #include "logic.h" #include "gate.h" static FILE* fd; static struct token *cursor; static const char *filename; #define EXPECT_AND_DISCARD_CRITICAL(type)\ do { \ EXPECT_CRITICAL(type) \ kerchunk(); \ } while (0); #define EXPECT_CRITICAL(type)\ do { \ if (expect(type)) { \ return 1; \ } \ } while (0); /* FIXME change to varadic fuction */ #define emit(...) \ if (cursor) { \ fprintf(stderr, "%s at (%zd,%zd): ", filename, cursor->loc.line, cursor->loc.column); \ fprintf(stderr, __VA_ARGS__); \ indicate_file_area(fd, cursor->loc.line, cursor->loc.column - cursor->loc.leading_whitespace_len, cursor->span); \ } else { \ fprintf(stderr, "%s: ", filename); \ fprintf(stderr, __VA_ARGS__); \ } //static struct op_lookup uop_handlers[] = { // {.str = "not", .handler = logic_nand}, //}; // //static struct op_lookup bop_handlers[] = { // {.str = "and", .handler = logic_and}, // {.str = "or", .handler = logic_or}, // {.str = "nand", .handler = logic_nand}, // {.str = "nor", .handler = logic_nor}, // {.str = "xor", .handler = logic_xor} //}; // //static struct tok_lookup tok_handlers[] = { // {.str = "input", .handler = parse_input}, // {.str = "module", .handler = parse_module}, // {.str = "expr", .handler = parse_expr} //}; static int expect(enum TOKEN_TYPE e) { char *expected_desc = "(internal error)"; char *observed_desc = "(internal error)"; if (!cursor || cursor->type != e) { expected_desc = get_token_description(e); if (cursor) { observed_desc = get_token_description(cursor->type); } else { observed_desc = "end of file"; } emit("Error: Expected %s, got %s\n", expected_desc, observed_desc); return 1; } return 0; } static void kerchunk() { if (cursor) { cursor = cursor->next; } } int parse_expr(void) { /* FIXME write wrapper to exit on fail */ EXPECT_AND_DISCARD_CRITICAL(TOK_EXPR); EXPECT_AND_DISCARD_CRITICAL(TOK_IDENT); /* FIXME do something, don't discard */ EXPECT_AND_DISCARD_CRITICAL(TOK_COLON); switch(cursor->type) { /* FIXME do some things */ case TOK_OR : /* fallthrough */ case TOK_AND: /* fallthrough */ case TOK_XOR: kerchunk(); EXPECT_AND_DISCARD_CRITICAL(TOK_IDENT); /* FIXME don't discard */ EXPECT_AND_DISCARD_CRITICAL(TOK_IDENT); /* FIXME don't discard */ break; case TOK_NOT: kerchunk(); EXPECT_AND_DISCARD_CRITICAL(TOK_IDENT); /* FIXME don't discard */ break; default: emit("Error: Unexpected %s\n", get_token_description(cursor->type)); } } int parse(const char *fname, FILE *f, struct token *t) { fd = f; filename = fname; cursor = t; /* Eat leading EOL tokens */ while (cursor && cursor->type == TOK_EOL) { kerchunk(); } EXPECT_AND_DISCARD_CRITICAL(TOK_MODULE); EXPECT_CRITICAL(TOK_IDENT); emit("Debug: module is named %s\n", cursor->value); /* FIXME do something */ kerchunk(); EXPECT_AND_DISCARD_CRITICAL(TOK_EOL); while (cursor) { switch(cursor->type) { case TOK_EOL: kerchunk(); break; case TOK_INPUT: kerchunk(); expect(TOK_IDENT); emit("Debug: input is named %s\n", cursor->value); /* FIXME do something */ kerchunk(); break; case TOK_EXPR: parse_expr(); break; default: emit("Error: Unexpected %s\n", get_token_description(cursor->type)); return 1; } } return 0; }