130 lines
2.3 KiB
C
130 lines
2.3 KiB
C
#include "calculator.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
static const char *ptr;
|
|
|
|
|
|
|
|
static void skip_spaces(void) {
|
|
while (*ptr && isspace(*ptr)) {
|
|
ptr++;
|
|
}
|
|
}
|
|
|
|
static int match(const char *s) {
|
|
int len = strlen(s);
|
|
if (strncmp(ptr, s, len) == 0) {
|
|
ptr += len;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
static double parse_expression(void);
|
|
|
|
static double parse_number(void) {
|
|
skip_spaces();
|
|
char *end;
|
|
double val = strtod(ptr, &end);
|
|
ptr = end;
|
|
return val;
|
|
}
|
|
|
|
static double parse_factor(void) {
|
|
skip_spaces();
|
|
|
|
|
|
if (*ptr == '(') {
|
|
ptr++;
|
|
double val = parse_expression();
|
|
skip_spaces();
|
|
if (*ptr == ')') {
|
|
ptr++;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
|
|
if (match("sin")) {
|
|
skip_spaces();
|
|
return sin(parse_factor());
|
|
}
|
|
if (match("cos")) {
|
|
skip_spaces();
|
|
return cos(parse_factor());
|
|
}
|
|
if (match("sqrt")) {
|
|
skip_spaces();
|
|
return sqrt(parse_factor());
|
|
}
|
|
if (match("log")) {
|
|
skip_spaces();
|
|
return log(parse_factor());
|
|
}
|
|
if (match("pow")) {
|
|
skip_spaces();
|
|
if (*ptr == '(') ptr++;
|
|
double a = parse_expression();
|
|
skip_spaces();
|
|
if (*ptr == ',') ptr++;
|
|
double b = parse_expression();
|
|
skip_spaces();
|
|
if (*ptr == ')') ptr++;
|
|
return pow(a, b);
|
|
}
|
|
|
|
|
|
return parse_number();
|
|
}
|
|
|
|
static double parse_term(void) {
|
|
double val = parse_factor();
|
|
|
|
while (1) {
|
|
skip_spaces();
|
|
if (*ptr == '*') {
|
|
ptr++;
|
|
val *= parse_factor();
|
|
} else if (*ptr == '/') {
|
|
ptr++;
|
|
val /= parse_factor();
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
static double parse_expression(void) {
|
|
double val = parse_term();
|
|
|
|
while (1) {
|
|
skip_spaces();
|
|
if (*ptr == '+') {
|
|
ptr++;
|
|
val += parse_term();
|
|
} else if (*ptr == '-') {
|
|
ptr++;
|
|
val -= parse_term();
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
|
|
|
|
double evaluate_expression(const char *expr) {
|
|
ptr = expr;
|
|
return parse_expression();
|
|
}
|