Last active
November 28, 2022 22:42
-
-
Save oluigipo/59ab027b79a92993cbd1f376002e0d31 to your computer and use it in GitHub Desktop.
simple expression parser in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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