flex-bison-in-action/analyzers/polynomials/stack/stack.c

128 lines
4.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "stack.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void initStack(Stack *s) {
s->top = -1;
}
bool isEmpty(Stack *s) {
return s->top == -1;
}
bool isFull(Stack *s) {
return s->top == MAX_STACK_SIZE - 1;
}
bool push(Stack *s, const char *value, char type) {
if (isFull(s)) {
fprintf(stderr, "Stack overflow!\n");
return false;
}
char *new_str = malloc(strlen(value) + 1);
if (new_str == NULL) {
fprintf(stderr, "Memory allocation failed!\n");
return false;
}
strcpy(new_str, value);
s->top++;
s->data[s->top].str_ptr = new_str;
s->data[s->top].type = type;
return true;
}
bool pop(Stack *s, Element *out) {
if (isEmpty(s)) {
fprintf(stderr, "Stack is empty!\n");
return false;
}
*out = s->data[s->top--];
return true;
}
bool peek(Stack *s, Element *out) {
if (isEmpty(s)) {
fprintf(stderr, "Stack is empty!\n");
return false;
}
*out = s->data[s->top];
return true;
}
void clearStack(Stack *s) {
while (s->top >= 0) {
free(s->data[s->top].str_ptr);
s->top--;
}
}
char* calulate(Element* tokens, int tokens_count) {
#define MAX_ELEMENT_STRING_SIZE 100
Stack s_operands;
initStack(&s_operands);
for (int i = 0; i < tokens_count; ++i) {
Element token = tokens[i];
if (token.type == 'n' || token.type == 'v') {
// если число или выражение с переменной - добавляю в стек
push(&s_operands, token.str_ptr, token.type);
} else {
// если оператор
char op = token.str_ptr[0];
// беру со стека 2 последних операнда
Element second_operand; pop(&s_operands, &second_operand);
Element first_operand; pop(&s_operands, &first_operand);
char result[MAX_ELEMENT_STRING_SIZE] = { 0 };
if (first_operand.type == 'n' && second_operand.type == 'n') {
// оба операнда - числа => вычисляю значение выражения и его закидываю в стек
int first_num = atoi(first_operand.str_ptr);
int second_num = atoi(second_operand.str_ptr);
switch (op) {
case '+': {
int result_num = first_num + second_num;
//printf("%i + %i = %i\n", first_num, second_num, result_num);
snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num);
push(&s_operands, result, 'n');
break;
}
case '-': {
int result_num = first_num - second_num;
//printf("%i - %i = %i\n", first_num, second_num, result_num);
snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num);
push(&s_operands, result, 'n');
break;
}
case '*': {
int result_num = first_num * second_num;
//printf("%i * %i = %i\n", first_num, second_num, result_num);
snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num);
push(&s_operands, result, 'n');
break;
}
}
} else {
// хотя бы один операнд содержит переменную
snprintf(result, MAX_ELEMENT_STRING_SIZE, "(%s%c%s)", first_operand.str_ptr, op, second_operand.str_ptr);
//printf("%s %c %s = %s\n", first_operand.str_ptr, op, second_operand.str_ptr, result);
push(&s_operands, result, 'v'); // Помечаю как выражение с переменной
}
free(first_operand.str_ptr);
free(second_operand.str_ptr);
}
}
if (!isEmpty(&s_operands)) {
Element result;
pop(&s_operands, &result);
//printf("Result: %s\n", result.str_ptr);
return result.str_ptr;
}
return NULL;
}