Skip to content

Instantly share code, notes, and snippets.

@uael
Created August 16, 2017 08:53
Show Gist options
  • Save uael/6401a0638b69e544995994f65f383dfd to your computer and use it in GitHub Desktop.
Save uael/6401a0638b69e544995994f65f383dfd to your computer and use it in GitHub Desktop.
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
typedef enum e_priority {
PRIMARY = 0,
UNARY,
MULTIPLICATIVE,
ADDITIVE,
SHIFT,
RELATIONAL,
EQUALITY,
AND,
XOR,
OR,
LAND,
LOR,
CONDITIONAL,
ASSIGN,
EXPR,
MAX = EXPR
} t_priority;
int stack[4096] = {0};
int idx = 0;
int ustack[4096] = {0};
#define ISWS(c) ((c) == ' ' || ((c) >= '\t' && (c) <= '\r'))
#define OPEND(c) (isdigit(c) || ISWS(c) || (c) == '$')
int *eval(char **s, t_priority p) {
int *a;
if (p == PRIMARY) {
while (ISWS(**s)) ++*s;
if (**s == '(')
return (a = eval((++*s, s), MAX)), ++*s, a;
if (**s == '$') {
int i = 0;
++*s;
while (isdigit(**s)) i = i * 10 + *(*s)++ - '0';
return ustack + i;
}
a = stack + idx++;
*a = 0;
while (isdigit(**s)) *a = *a * 10 + *(*s)++ - '0';
return a;
}
if (p == UNARY) {
a = stack + idx;
while (ISWS(**s)) ++*s;
if (**s == '-' && OPEND(*(*s + 1)))
return (*a = -*eval((++*s, s), p - 1)), a;
if (**s == '+' && OPEND(*(*s + 1)))
return eval((++*s, s), p - 1);
if (**s == '~' && OPEND(*(*s + 1)))
return (*a = ~*eval((++*s, s), p - 1)), a;
if (**s == '!' && OPEND(*(*s + 1)))
return (*a = !*eval((++*s, s), p - 1)), a;
if (**s == '+' && *(*s + 1) == '+' && OPEND(*(*s + 2)))
return (*a = ++*eval((*s += 2, s), p - 1)), a;
if (**s == '-' && *(*s + 1) == '-' && OPEND(*(*s + 2)))
return (*a = --*eval((*s += 2, s), p - 1)), a;
return eval(s, p - 1);
}
a = eval(s, p - 1);
int *i = stack + idx;
while (1) {
if (ISWS(**s))
++*s;
else if (**s == '\0')
return a;
else if (p == MULTIPLICATIVE) {
if (**s == '*' && OPEND(*(*s + 1)))
a = ((*i = *a * *eval((++*s, s), p - 1)), i);
else if (**s == '/' && OPEND(*(*s + 1)))
a = ((*i = *a / *eval((++*s, s), p - 1)), i);
else if (**s == '%' && OPEND(*(*s + 1)))
a = ((*i = *a % *eval((++*s, s), p - 1)), i);
else
return a;
} else if (p == ADDITIVE) {
if (**s == '-' && OPEND(*(*s + 1)))
a = ((*i = *a - *eval((++*s, s), p - 1)), i);
else if (**s == '+' && OPEND(*(*s + 1)))
a = ((*i = *a + *eval((++*s, s), p - 1)), i);
else
return a;
} else if (p == SHIFT) {
if (**s == '<' && *(*s + 1) == '<' && OPEND(*(*s + 2)))
a = ((*i = *a << *eval((*s += 2, s), p - 1)), i);
else if (**s == '>' && *(*s + 1) == '>' && OPEND(*(*s + 2)))
a = ((*i = *a >> *eval((*s += 2, s), p - 1)), i);
else
return a;
} else if (p == RELATIONAL) {
if (**s == '<' && OPEND(*(*s + 1)))
a = ((*i = *a < *eval((++*s, s), p - 1)), i);
else if (**s == '>' && OPEND(*(*s + 1)))
a = ((*i = *a > *eval((++*s, s), p - 1)), i);
else if (**s == '<' && *(*s + 1) == '=' && OPEND(*(*s + 2)))
a = ((*i = *a <= *eval((*s += 2, s), p - 1)), i);
else if (**s == '>' && *(*s + 1) == '=' && OPEND(*(*s + 2)))
a = ((*i = *a >= *eval((*s += 2, s), p - 1)), i);
else
return a;
} else if (p == EQUALITY) {
if (**s == '=' && *(*s + 1) == '=' && OPEND(*(*s + 2)))
a = ((*i = *a == *eval((*s += 2, s), p - 1)), i);
else if (**s == '!' && *(*s + 1) == '=' && OPEND(*(*s + 2)))
a = ((*i = *a != *eval((*s += 2, s), p - 1)), i);
else
return a;
} else if (p == AND) {
if (**s == '&' && OPEND(*(*s + 1)))
a = ((*i = *a & *eval((++*s, s), p - 1)), i);
else
return a;
} else if (p == XOR) {
if (**s == '^' && OPEND(*(*s + 1)))
a = ((*i = *a ^ *eval((++*s, s), p - 1)), i);
else
return a;
} else if (p == OR) {
if (**s == '|' && OPEND(*(*s + 1)))
a = ((*i = *a | *eval((++*s, s), p - 1)), i);
else
return a;
} else if (p == LAND) {
if (**s == '&' && *(*s + 1) == '&' && OPEND(*(*s + 2)))
a = ((*i = *a && *eval((*s += 2, s), p - 1)), i);
else
return a;
} else if (p == LOR) {
if (**s == '|' && *(*s + 1) == '|' && OPEND(*(*s + 2)))
a = ((*i = *a || *eval((*s += 2, s), p - 1)), i);
else
return a;
} else if (p == CONDITIONAL) {
if (**s == '?' && *(*s + 1) == ':' && OPEND(*(*s + 2))) {
int *b = eval((*s += 2, s), MAX);
a = ((*i = *a ? *a : *b), i);
} else if (**s == '?' && OPEND(*(*s + 1))) {
int *b = eval((++*s, s), MAX);
while (ISWS(**s)) ++*s;
int *c = eval((++*s, s), MAX);
a = ((*i = *a ? *b : *c), i);
} else
return a;
} else if (p == ASSIGN) {
if (**s == '=' && OPEND(*(*s + 1)))
*a = *eval((++*s, s), p - 1);
else
return a;
} else if (p == EXPR) {
if (**s == ',' && OPEND(*(*s + 1)))
a = eval((++*s, s), p - 1);
else
return a;
}
}
}
int eval_expr(char *str) {
return *(eval(&str, MAX));
}
int main(int ac, char **av) {
printf("%d\n", eval_expr("($1 = ($2 = 3) + 42 * (1 - 2 / ($2 + 4) - 1 % 21) + $2) ? $1 + (1 >= 1 ? (1, 30 + 6) : 0) : 1"));
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment