diff options
Diffstat (limited to 'parse.c')
-rw-r--r-- | parse.c | 155 |
1 files changed, 155 insertions, 0 deletions
@@ -0,0 +1,155 @@ +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "lex.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) { + const char *expected_desc = "(internal error)"; + const 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)); + return 1; + } + return 0; +} + + +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; +} |