151 lines
3.5 KiB
C
151 lines
3.5 KiB
C
// vim: set ts=4 sw=4 et tw=80:
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "bexp.h"
|
|
#include "ctype.h"
|
|
|
|
typedef struct stack {
|
|
value first;
|
|
struct stack* next;
|
|
char container[];
|
|
} stack_t;
|
|
|
|
stack_t* tos = NULL;
|
|
|
|
void read_value();
|
|
void read_command();
|
|
void discard();
|
|
|
|
void discard() {
|
|
fprintf(stderr, "Value is malformed. Discarding until space...\n");
|
|
while(isspace(getchar()));
|
|
return;
|
|
}
|
|
|
|
int 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;
|
|
stack_t* new = malloc(sizeof(stack_t) + str_size * sizeof(char));
|
|
if (!new) {
|
|
perror("Cannot allocate new stack element");
|
|
return;
|
|
}
|
|
new->next = tos;
|
|
|
|
int count = 0;
|
|
char 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(stack_t) + str_size * sizeof(char));
|
|
if (!new) {
|
|
perror("Cannot allocate new stack element");
|
|
free(new);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
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->begin;
|
|
while (v != val->end) 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));
|
|
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;
|
|
}
|
|
|
|
expression_t ex = { op, tos->value, binary ? tos->next->value : NULL };
|
|
int length = bexp_length(&ex);
|
|
|
|
char* result = malloc(sizeof(stack_t) + sizeof(char) * length);
|
|
if (!result) {
|
|
perror("Cannot allocate space for result");
|
|
return;
|
|
}
|
|
value v_result = { result, result + length };
|
|
|
|
bexp_evaluate(&v_result, &ex);
|
|
stack_t
|
|
|
|
|
|
}
|