Skip to content

Instantly share code, notes, and snippets.

@oluigipo
Last active November 28, 2022 22:42
Show Gist options
  • Save oluigipo/59ab027b79a92993cbd1f376002e0d31 to your computer and use it in GitHub Desktop.
Save oluigipo/59ab027b79a92993cbd1f376002e0d31 to your computer and use it in GitHub Desktop.
simple expression parser in C
// Top-level declarations
static double parse_add(void);
static const char* state;
// Checks if state is a valid digit
static int is_digit(void) {
return *state >= '0' && *state <= '9';
}
// Get the digit value of state
static int digit(void) {
return *state - '0';
}
// Parses a number
static double number(void) {
double result = 0;
while (is_digit()) {
int n = digit();
result *= 10;
result += n;
++state;
}
if (*state == '.') {
++state;
double dec = 0.1;
while (is_digit()) {
int n = digit();
result += n * dec;
dec *= 0.1;
++state;
}
}
return result;
}
// Parses a factor (unary, parenthesis, and number)
static double parse_factor(void) {
switch (*state) {
case '+': ++state; return parse_factor();
case '-': ++state; return -parse_factor();
case '(': {
++state; // eat (
double result = parse_add();
++state; // eat )
return result;
}
default: return number();
}
}
// Parses * and /
static double parse_mul(void) {
double left = parse_factor();
while (*state == '*' || *state == '/') {
char op = *state++;
double right = parse_factor();
if (op == '*')
left *= right;
else
left /= right;
}
return left;
}
// Parses + and -
static double parse_add(void) {
double left = parse_mul();
while (*state == '+' || *state == '-') {
char op = *state++;
double right = parse_mul();
if (op == '+')
left += right;
else
left -= right;
}
return left;
}
// Eval function
static double eval(const char* string) {
state = string;
return parse_add();
}
// Simple reading from stdin. Only the stuff above is relevant.
#include <stdio.h>
static int eval_line(void) {
char buffer[1024], c;
int length = 0;
printf("> ");
while (c = getchar(), c != '\n') {
buffer[length] = c;
// Ignore whitespaces
if (c != ' ')
++length;
}
buffer[length] = 0;
if (length > 0)
printf("%f\n", eval(buffer));
return length;
}
int main() {
while (eval_line() > 0);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment