flex-bison-in-action/analyzers/polynomials/test/poly.c

218 lines
6.0 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// Структура для представления узла выражения
typedef struct Node {
char type;
union {
int num;
char var;
struct {
struct Node *left;
struct Node *right;
} expr;
};
} Node;
Node* new_num_node(int num);
Node* new_var_node(char var);
Node* new_expr_node(char type, Node *left, Node *right);
void free_node(Node *node);
void print_node(Node *node);
Node* simplify(Node *node);
Node* parse_expression(char **expr);
Node* parse_term(char **expr);
Node* parse_factor(char **expr);
Node* parse_primary(char **expr);
// Функция для создания нового узла числа
Node* new_num_node(int num) {
Node *node = (Node*)malloc(sizeof(Node));
node->type = 'N';
node->num = num;
return node;
}
// Функция для создания нового узла переменной
Node* new_var_node(char var) {
Node *node = (Node*)malloc(sizeof(Node));
node->type = 'V';
node->var = var;
return node;
}
// Функция для создания нового узла выражения
Node* new_expr_node(char type, Node *left, Node *right) {
Node *node = (Node*)malloc(sizeof(Node));
node->type = type;
node->expr.left = left;
node->expr.right = right;
return node;
}
// Функция для освобождения памяти узла
void free_node(Node *node) {
if (!node) return;
if (node->type == '+' || node->type == '-' || node->type == '*' || node->type == '/' || node->type == '^') {
free_node(node->expr.left);
free_node(node->expr.right);
}
free(node);
}
// Функция для печати узла (отладочная)
void print_node(Node *node) {
if (!node) return;
switch (node->type) {
case 'N':
printf("%d", node->num);
break;
case 'V':
printf("%c", node->var);
break;
case '+':
case '-':
case '*':
case '/':
case '^':
printf("(");
print_node(node->expr.left);
printf(" %c ", node->type);
print_node(node->expr.right);
printf(")");
break;
}
}
// Функция для упрощения выражения
Node* simplify(Node *node) {
if (!node) return NULL;
if (node->type == '*') {
Node *left = simplify(node->expr.left);
Node *right = simplify(node->expr.right);
if (left->type == 'N' && right->type == 'N') {
return new_num_node(left->num * right->num);
} else if (left->type == 'N' && left->num == 0) {
return new_num_node(0);
} else if (right->type == 'N' && right->num == 0) {
return new_num_node(0);
} else if (left->type == 'N' && left->num == 1) {
return right;
} else if (right->type == 'N' && right->num == 1) {
return left;
} else if (left->type == 'V' && right->type == 'V' && left->var == right->var) {
return new_expr_node('^', left, new_num_node(2));
}
return new_expr_node('*', left, right);
} else if (node->type == '+') {
Node *left = simplify(node->expr.left);
Node *right = simplify(node->expr.right);
if (left->type == 'N' && right->type == 'N') {
return new_num_node(left->num + right->num);
} else if (left->type == 'N' && left->num == 0) {
return right;
} else if (right->type == 'N' && right->num == 0) {
return left;
}
return new_expr_node('+', left, right);
} else if (node->type == '-') {
Node *left = simplify(node->expr.left);
Node *right = simplify(node->expr.right);
if (left->type == 'N' && right->type == 'N') {
return new_num_node(left->num - right->num);
} else if (right->type == 'N' && right->num == 0) {
return left;
}
return new_expr_node('-', left, right);
}
return node;
}
// Функция для парсинга выражения
Node* parse_expression(char **expr) {
Node *left = parse_term(expr);
while (**expr == '+' || **expr == '-') {
char op = *((*expr)++);
Node *right = parse_term(expr);
left = new_expr_node(op, left, right);
}
return left;
}
// Функция для парсинга терма
Node* parse_term(char **expr) {
Node *left = parse_factor(expr);
while (**expr == '*' || **expr == '/') {
char op = *((*expr)++);
Node *right = parse_factor(expr);
left = new_expr_node(op, left, right);
}
return left;
}
// Функция для парсинга фактора
Node* parse_factor(char **expr) {
Node *left = parse_primary(expr);
if (**expr == '^') {
*expr += 1;
Node *right = parse_factor(expr);
left = new_expr_node('^', left, right);
}
return left;
}
// Функция для парсинга первичного выражения
Node* parse_primary(char **expr) {
if (isdigit(**expr)) {
int num = 0;
while (isdigit(**expr)) {
num = num * 10 + *((*expr)++) - '0';
}
return new_num_node(num);
} else if (isalpha(**expr)) {
char var = *((*expr)++);
return new_var_node(var);
} else if (**expr == '(') {
*expr += 1;
Node *node = parse_expression(expr);
if (**expr == ')') {
*expr += 1;
}
return node;
}
return NULL;
}
int main() {
char expr[256];
printf("Enter an expression: ");
fgets(expr, sizeof(expr), stdin);
char *ptr = expr;
Node *root = parse_expression(&ptr);
printf("Original expression: ");
print_node(root);
printf("\n");
Node *simplified = simplify(root);
printf("Simplified expression: ");
print_node(simplified);
printf("\n");
free_node(root);
free_node(simplified);
return 0;
}