// vim: set ts=4 sw=4 et tw=80: #include #include #include "bexp.h" #include "ctype.h" typedef struct stack { value first; struct stack* next; char container[]; } expr_stack_t; static void read_word(); static void read_value(); static void read_command(); static void discard(); static int ensure(char* str); static void print_value(const value* val); static void read_command(); static expr_stack_t* tos = NULL; int main() { while(!feof(stdin)) { read_word(); } } void discard() { fprintf(stderr, "Input malformed. Discarding until space...\n"); while(!isspace(getchar())); return; } void read_word() { char c; while (isspace(c = getchar())); ungetc(c, stdin); if (c == '0' || c == '1') { read_value(); } else { read_command(); } } void read_value() { int str_size = 10; expr_stack_t* new = malloc(sizeof(expr_stack_t) + str_size * sizeof(char)); if (!new) { perror("Cannot allocate new stack element"); return; } new->next = tos; int count = 0; int c; while(!isspace(c = getchar())) { if (c != '0' && c != '1') { free(new); discard(); return; } new->container[count++] = c; if (str_size == count) { str_size *= 2; new = realloc(new, sizeof(expr_stack_t) + str_size * sizeof(char)); if (!new) { perror("Cannot allocate new stack element"); free(new); return; } } } // reverse the string in container to match least to most significant order // in bexp char* i = new->container; char* j = new->container + count - 1; while (i < j) { char tmp = *i; *i = *j; *j = tmp; i++; j--; } new->first.begin = new->container; new->first.end = new->container + count; tos = new; } int ensure(char* str) { while (*str) { if (tolower(getchar()) != *str) { return 0; } str++; } return 1; } void print_value(const value* val) { char* v = val->end - 1; while (v >= val->begin) putchar(*(v--)); putchar('\n'); } void read_command() { operator_t op; switch(getchar()) { case '&': op = AND; break; case '|': op = OR; break; case '^': op = XOR; break; case '+': op = PLUS; break; case '>': op = GREATER_THAN; break; case '<': op = LESS_THAN; break; case '!': op = NOT; break; case '~': op = COMPLEMENT; break; case 't': case 'T': if (!ensure("op")) { discard(); } else { if (tos == NULL) { printf("empty\n"); } else { print_value(&(tos->first)); } } return; case 'p': case 'P': if (!ensure("op")) { discard(); } else { if (tos == NULL) { printf("empty\n"); } else { print_value(&(tos->first)); expr_stack_t* t = tos; tos = tos->next; free(t); } } return; default: discard(); return; } int binary = op != NOT && op != COMPLEMENT; if (tos == NULL || (binary && tos->next == NULL)) { printf("too few values on stack\n"); return; } const static value dummy = { NULL, NULL }; expression ex = { op, tos->first, binary ? tos->next->first : dummy }; int length = bexp_length(&ex); expr_stack_t* new_tos = malloc(sizeof(expr_stack_t) + sizeof(char) * length); if (!new_tos) { perror("Cannot allocate space for result"); return; } new_tos->first.begin = new_tos->container; new_tos->first.end = new_tos->container + length; bexp_evaluate(&new_tos->first, &ex); expr_stack_t* new_next = tos->next; free(tos); tos = new_next; if (binary) { new_next = tos->next; free(tos); tos = new_next; } new_tos->next = tos; tos = new_tos; }