usaa25/sk2/calculator.c
2026-01-27 12:32:27 +01:00

127 lines
2.2 KiB
C

#include "calculator.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
static const char *cur;
static void skip_ws(void) {
while (*cur && isspace(*cur)) {
cur++;
}
}
static int starts_with(const char *name) {
int len = strlen(name);
if (strncmp(cur, name, len) == 0) {
cur += len;
return 1;
}
return 0;
}
static double read_expr(void);
static double read_number(void) {
skip_ws();
char *end;
double res = strtod(cur, &end);
cur = end;
return res;
}
static double read_factor(void) {
skip_ws();
if (*cur == '(') {
cur++;
double res = read_expr();
skip_ws();
if (*cur == ')') {
cur++;
}
return res;
}
if (starts_with("sin")) {
skip_ws();
return sin(read_factor());
}
if (starts_with("cos")) {
skip_ws();
return cos(read_factor());
}
if (starts_with("sqrt")) {
skip_ws();
return sqrt(read_factor());
}
if (starts_with("log")) {
skip_ws();
return log(read_factor());
}
if (starts_with("pow")) {
skip_ws();
if (*cur == '(') cur++;
double left = read_expr();
skip_ws();
if (*cur == ',') cur++;
double right = read_expr();
skip_ws();
if (*cur == ')') cur++;
return pow(left, right);
}
return read_number();
}
static double read_term(void) {
double res = read_factor();
while (1) {
skip_ws();
if (*cur == '*') {
cur++;
res *= read_factor();
} else if (*cur == '/') {
cur++;
res /= read_factor();
} else {
break;
}
}
return res;
}
static double read_expr(void) {
double res = read_term();
while (1) {
skip_ws();
if (*cur == '+') {
cur++;
res += read_term();
} else if (*cur == '-') {
cur++;
res -= read_term();
} else {
break;
}
}
return res;
}
double evaluate_expression(const char *expr) {
cur = expr;
return read_expr();
}