#include #include #include #include "common.h" #include "error.h" #include "logic.h" #include "gate.h" int parse_input(char *); int parse_module(char *); int parse_expr(char *); struct tok_lookup { char *str; int (*handler)(char*); }; struct op_lookup { char *str; enum BINARY (*handler)(enum BINARY, enum BINARY); }; 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} }; 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); return 1; } return 0; } char * eat_whitespace(char *string) { while (*string && isspace(*string)) { string++; } return string; } int parse_uop(char *str, char *name, enum BINARY (*handler)(enum BINARY, enum BINARY)) { char *gate_name = str; strtok(gate_name, " "); /* FIXME allow input from other gates, not just inputs */ struct gate *in = gate_get_input_by_name(gate_name); gate_add(name, handler, in, in); return 0; } int parse_bop(char *str, char *name, enum BINARY (*handler)(enum BINARY, enum BINARY)) { char *gate_name1 = str; char *gate_name2 = NULL; strtok(gate_name1, " "); gate_name2 = gate_name1 + strlen(gate_name1) + 1; strtok(gate_name2, " "); /* FIXME allow input from other gates, not just inputs */ struct gate *in1 = gate_get_input_by_name(gate_name1); struct gate *in2 = gate_get_input_by_name(gate_name2); gate_add(name, handler, in1, in2); return 0; } int parse_op(char *str, char *name) { int match = 0; size_t i = 0; strtok(str, " "); match = 0; for (i = 0; i < sizeof(bop_handlers)/sizeof(bop_handlers[0]); i++) { if (strcmp(bop_handlers[i].str, str) == 0) { match = 1; if (parse_bop(str+strlen(str)+1, name, bop_handlers[i].handler)) { return 1; } } } for (i = 0; i < sizeof(uop_handlers)/sizeof(uop_handlers[0]); i++) { if (strcmp(uop_handlers[i].str, str) == 0) { match = 1; if (parse_uop(str+strlen(str)+1, name, uop_handlers[i].handler)) { return 1; } } } if (match == 0) { emit_error("Invalid operator \"%s\"\n", str); return 1; } return 0; } int parse_expr(char *str) { const char *expr_sep = ": "; size_t ident_len = 0; char *ident = NULL; char *op = NULL; /* FIXME magic constant string */ ident_len = strspn(str, "abcdefghijklmnopqrstuvwxyz0123456789"); if (expect(expr_sep, str + ident_len)) { return -1; } str[ident_len] = '\0'; ident = str; op = str + ident_len + strlen(expr_sep); return parse_op(op, ident); } int parse_input(char *str) { strtok(str, " "); str = eat_whitespace(str); emit_info("Add input '%s'\n", str); gate_input_add(str); return 0; } int parse_module(char *str) { printf("FIXME module name is \"%s\" but modules are not implemented\n", str); return 0; } int parse_line(char *line) { size_t i = 0; char *tok = line; char *delim = " "; int match = 0; if ( strlen(line) == 0 || (strlen(line) == 1 && isspace(line[0]))) { return 0; } tok = strtok(line, delim); 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)(&tok[strlen(tok)+1])) { return 1; } } } if (match == 0) { emit_error("invalid token \"%s\"", tok); return 1; } return 0; }