185 lines
4.3 KiB
C
185 lines
4.3 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[];
|
|
} 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;
|
|
}
|