diff options
author | David Phillips <david@sighup.nz> | 2018-08-01 01:00:54 +1200 |
---|---|---|
committer | David Phillips <david@sighup.nz> | 2018-08-01 01:00:54 +1200 |
commit | 645acc193a739ab771fb46e8ec2cf6cd87909597 (patch) | |
tree | 482c5d59220af7ae2cc8f34a860174f4b1affd01 /parser.c | |
parent | 96776c831e9d2fcbd69bc1e0faa16026c5ed25b0 (diff) | |
download | hence-645acc193a739ab771fb46e8ec2cf6cd87909597.tar.xz |
WIP: Implement more robust, separated lexer+parser passes
Diffstat (limited to 'parser.c')
-rw-r--r-- | parser.c | 320 |
1 files changed, 36 insertions, 284 deletions
@@ -3,309 +3,61 @@ #include <stdlib.h> #include <string.h> +#include "lexer.h" #include "common.h" #include "error.h" #include "logic.h" #include "gate.h" -int parse_input(char *); -int parse_module(char *); -int parse_expr(char *); +static struct token *cursor; -struct tok_lookup { - char *str; - int (*handler)(char*); -}; +#ifdef emit_error +#warning "Remember to remove the global emit_error" +#undef emit_error +#endif /* ifdef emit_error */ -struct op_lookup { - char *str; - enum BINARY (*handler)(enum BINARY, enum BINARY); -}; +#define emit_error(...) fprintf(stderr, "Error (%zd,%zd): ", cursor->loc.line, cursor->loc.column);\ + 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 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 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)"; -int -rtrim(char *string) { - char *old_end = string + strlen(string); - char *w = NULL; - - string[strcspn(string, "\r\n")] = '\0'; - - /* find first member of right whitespace */ - for (w = old_end; w >= string; w--) { - if (strchr("\t ", *w) == NULL) { - break; - } - *w = '\0'; - } - - return old_end - w; -} - -char * -eat_whitespace(char *string) { - while (*string && isspace(*string)) { - string++; - } - return string; -} - -char * -get_token_special(char *string, char **rest, char *delims) { - size_t tok_len = 0; - char *ret = NULL; - string = eat_whitespace(string); - tok_len = strcspn(string, delims); - if (tok_len == 0) { - emit_error("unexpected end of string"); - return NULL; - } - if (NULL == (ret = strndup(string, tok_len))) { - emit_error("get_token: "); - perror("strndup"); - return NULL; - } - *rest = string + tok_len; - return ret; -} - -char * -get_token(char *string, char **rest) { - return get_token_special(string, rest, " \t"); -} - -int -expect(const char *expect, char *actual) { - int min_len = 0; - - min_len = MIN(strlen(expect), strlen(actual)); - - if (strncmp(expect, actual, min_len) != 0) { - emit_error("Expected '%s' at start of '%s'\n", expect, actual); + if (cursor->type != e) { + expected_desc = get_token_description(e); + observed_desc = get_token_description(cursor->type); + emit_error("Expected %s, got %s\n", expected_desc, observed_desc); return 1; } - return 0; -} - -int parse_uop(char *str, char *name, enum BINARY (*handler)(enum BINARY, enum BINARY)) { - char *source_name = NULL; - char *next = NULL; - - if (NULL == (source_name = get_token(str, &next))) { - return 1; - } - - /* FIXME allow input from other gates, not just inputs */ - struct gate *in = gate_get_input_by_name(source_name); - free(source_name); - return gate_add(name, handler, in, in); - - -} - -int parse_bop(char *str, char *name, enum BINARY (*handler)(enum BINARY, enum BINARY)) { - char *source_name1 = NULL; - char *source_name2 = NULL; - char *next = NULL; - struct gate *in1 = NULL; - struct gate *in2 = NULL; - - if (NULL == (source_name1 = get_token(str, &next))) { - return 1; - } - - if (NULL == (source_name2 = get_token(next, &next))) { - free(source_name1); - return 1; - } - - if (*next != '\0') { - emit_error("superfluous text \"%s\"\n", next); - free(source_name1); - free(source_name2); - return 1; - } - - /* FIXME allow input from other gates, not just inputs */ - in1 = gate_get_input_by_name(source_name1); - in2 = gate_get_input_by_name(source_name2); - - free(source_name1); - free(source_name2); - - if (in1 == NULL || in2 == NULL) { - emit_error("Undeclared identifier in source(s) for expression '%s'\n", - name); - return 1; - } - - return gate_add(name, handler, in1, in2); -} - -int -parse_op(char *str, char *name) { - char *tok = NULL; - char *next = NULL; - int match = 0; - size_t i = 0; - - if (NULL == (tok = get_token(str, &next))) { - return 1; - } - - match = 0; - for (i = 0; i < sizeof(bop_handlers)/sizeof(bop_handlers[0]); i++) { - if (strcmp(bop_handlers[i].str, tok) == 0) { - match = 1; - if (parse_bop(next, name, bop_handlers[i].handler)) { - free(tok); - return 1; - } - } - } - for (i = 0; i < sizeof(uop_handlers)/sizeof(uop_handlers[0]); i++) { - if (strcmp(uop_handlers[i].str, tok) == 0) { - match = 1; - if (parse_uop(next, name, uop_handlers[i].handler)) { - free(tok); - return 1; - } - } - } - if (match == 0) { - emit_error("Invalid operator \"%s\"\n", tok); - free(tok); - return 1; - } - free(tok); return 0; } -int -parse_expr(char *str) { - int ret = 0; - const char *expr_sep = ": "; - char *ident = NULL; - char *next = NULL; - char *op = NULL; - - if (NULL == (ident = get_token_special(str, &next, ": \t"))) { - return 1; - } - - if (expect(expr_sep, next)) { - free(ident); - return 1; - } - - op = next + strlen(expr_sep); - - ret = parse_op(op, ident); - free(ident); - return ret; -} - -int -parse_input(char *str) { - char *ident = NULL; - char *next = NULL; - int ret = 0; - - if (NULL == (ident = get_token(str, &next))) { - return 1; - } - - if (strlen(ident) == 0) { - emit_error("input label must not be empty"); - free(ident); - return 1; - } - - if (*next != '\0') { - emit_error("superfluous text after \"%s\" identifier: \"%s\"\n", - ident, next); - free(ident); - return 1; - } - - emit_info("Add input '%s'\n", ident); - ret = gate_input_add(ident); - free(ident); - return ret; -} - -int -parse_module(char *str) { - char *mod_name = NULL; - char *next = NULL; - if (NULL == (mod_name = get_token(str, &next))) { - return 1; - } - - if (*next != '\0') { - emit_error("superfluous text following module name"); - free(mod_name); - return 1; - } - - printf("FIXME module name is \"%s\" but modules are not implemented\n", mod_name); - free(mod_name); - return 0; -} int -parse_line(char *line) { - size_t i = 0; - char *next = NULL; - char *tok = NULL; - int match = 0; - - rtrim(line); - - if ( strlen(line) == 0 - || (strlen(line) == 1 && isspace(line[0]))) { - return 0; - } - - if (NULL == (tok = get_token(line, &next))) { - return 1; - } - - match = 0; - for (i = 0; i < sizeof(tok_handlers)/sizeof(tok_handlers[0]); i++) { - if (strcmp(tok_handlers[i].str, tok) == 0) { - match = 1; - if ((tok_handlers[i].handler)(next)) { - free(tok); - return 1; - } - } - } - - if (match == 0) { - emit_error("invalid token \"%s\"", tok); - free(tok); - return 1; - } - free(tok); +parse(struct token *t) { + cursor = t; + expect(TOK_MODULE); return 0; } - |