This repository has been archived on 2021-10-31. You can view files and clone it, but cannot push or open issues or pull requests.
sys_prog/bexp/bexp_calculator.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;
}