This commit is contained in:
Oleksandr Vyshniakov 2026-01-27 12:32:27 +01:00
parent 02b2f1146c
commit 71e589eb70

View File

@ -5,20 +5,20 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
static const char *ptr; static const char *cur;
static void skip_spaces(void) { static void skip_ws(void) {
while (*ptr && isspace(*ptr)) { while (*cur && isspace(*cur)) {
ptr++; cur++;
} }
} }
static int match(const char *s) { static int starts_with(const char *name) {
int len = strlen(s); int len = strlen(name);
if (strncmp(ptr, s, len) == 0) { if (strncmp(cur, name, len) == 0) {
ptr += len; cur += len;
return 1; return 1;
} }
return 0; return 0;
@ -26,104 +26,101 @@ static int match(const char *s) {
static double parse_expression(void); static double read_expr(void);
static double parse_number(void) { static double read_number(void) {
skip_spaces(); skip_ws();
char *end; char *end;
double val = strtod(ptr, &end); double res = strtod(cur, &end);
ptr = end; cur = end;
return val; return res;
} }
static double parse_factor(void) { static double read_factor(void) {
skip_spaces(); skip_ws();
if (*cur == '(') {
if (*ptr == '(') { cur++;
ptr++; double res = read_expr();
double val = parse_expression(); skip_ws();
skip_spaces(); if (*cur == ')') {
if (*ptr == ')') { cur++;
ptr++;
} }
return val; return res;
} }
if (starts_with("sin")) {
if (match("sin")) { skip_ws();
skip_spaces(); return sin(read_factor());
return sin(parse_factor());
} }
if (match("cos")) { if (starts_with("cos")) {
skip_spaces(); skip_ws();
return cos(parse_factor()); return cos(read_factor());
} }
if (match("sqrt")) { if (starts_with("sqrt")) {
skip_spaces(); skip_ws();
return sqrt(parse_factor()); return sqrt(read_factor());
} }
if (match("log")) { if (starts_with("log")) {
skip_spaces(); skip_ws();
return log(parse_factor()); return log(read_factor());
} }
if (match("pow")) { if (starts_with("pow")) {
skip_spaces(); skip_ws();
if (*ptr == '(') ptr++; if (*cur == '(') cur++;
double a = parse_expression(); double left = read_expr();
skip_spaces(); skip_ws();
if (*ptr == ',') ptr++; if (*cur == ',') cur++;
double b = parse_expression(); double right = read_expr();
skip_spaces(); skip_ws();
if (*ptr == ')') ptr++; if (*cur == ')') cur++;
return pow(a, b); return pow(left, right);
} }
return read_number();
return parse_number();
} }
static double parse_term(void) { static double read_term(void) {
double val = parse_factor(); double res = read_factor();
while (1) { while (1) {
skip_spaces(); skip_ws();
if (*ptr == '*') { if (*cur == '*') {
ptr++; cur++;
val *= parse_factor(); res *= read_factor();
} else if (*ptr == '/') { } else if (*cur == '/') {
ptr++; cur++;
val /= parse_factor(); res /= read_factor();
} else { } else {
break; break;
} }
} }
return val; return res;
} }
static double parse_expression(void) { static double read_expr(void) {
double val = parse_term(); double res = read_term();
while (1) { while (1) {
skip_spaces(); skip_ws();
if (*ptr == '+') { if (*cur == '+') {
ptr++; cur++;
val += parse_term(); res += read_term();
} else if (*ptr == '-') { } else if (*cur == '-') {
ptr++; cur++;
val -= parse_term(); res -= read_term();
} else { } else {
break; break;
} }
} }
return val; return res;
} }
double evaluate_expression(const char *expr) { double evaluate_expression(const char *expr) {
ptr = expr; cur = expr;
return parse_expression(); return read_expr();
} }