pratt: eval: add exponentiation operator
This showcases right-associative operators
This commit is contained in:
parent
3ce0bcf140
commit
ee2d8d1e9d
19
src/eval.c
19
src/eval.c
|
@ -38,6 +38,8 @@ struct token {
|
||||||
LeftFunc(Name)
|
LeftFunc(Name)
|
||||||
#define INFIX(Name) \
|
#define INFIX(Name) \
|
||||||
LeftFunc(Name)
|
LeftFunc(Name)
|
||||||
|
#define POWER(Name) \
|
||||||
|
LeftFunc(Name)
|
||||||
#define TERN(Name) \
|
#define TERN(Name) \
|
||||||
LeftFunc(Name)
|
LeftFunc(Name)
|
||||||
#define PAREN(Name) \
|
#define PAREN(Name) \
|
||||||
|
@ -72,6 +74,8 @@ static const struct {
|
||||||
[Name] = {OP_STRING(__VA_ARGS__), OP_SIZE(__VA_ARGS__), NulPrio, LeftPrio, NulFunc(Name), LeftFunc(Name), },
|
[Name] = {OP_STRING(__VA_ARGS__), OP_SIZE(__VA_ARGS__), NulPrio, LeftPrio, NulFunc(Name), LeftFunc(Name), },
|
||||||
#define INFIX(Name, NulPrio, LeftPrio, ...) \
|
#define INFIX(Name, NulPrio, LeftPrio, ...) \
|
||||||
[Name] = {OP_STRING(__VA_ARGS__), OP_SIZE(__VA_ARGS__), NulPrio, LeftPrio, NULL, LeftFunc(Name), },
|
[Name] = {OP_STRING(__VA_ARGS__), OP_SIZE(__VA_ARGS__), NulPrio, LeftPrio, NULL, LeftFunc(Name), },
|
||||||
|
#define POWER(Name, NulPrio, LeftPrio, ...) \
|
||||||
|
[Name] = {OP_STRING(__VA_ARGS__), OP_SIZE(__VA_ARGS__), NulPrio, LeftPrio, NULL, LeftFunc(Name), },
|
||||||
#define TERN(Name, NulPrio, LeftPrio, ...) \
|
#define TERN(Name, NulPrio, LeftPrio, ...) \
|
||||||
[Name] = {OP_STRING(__VA_ARGS__), OP_SIZE(__VA_ARGS__), NulPrio, LeftPrio, NULL, LeftFunc(Name), },
|
[Name] = {OP_STRING(__VA_ARGS__), OP_SIZE(__VA_ARGS__), NulPrio, LeftPrio, NULL, LeftFunc(Name), },
|
||||||
#define PAREN(Name, NulPrio, LeftPrio, ...) \
|
#define PAREN(Name, NulPrio, LeftPrio, ...) \
|
||||||
|
@ -244,6 +248,21 @@ bool eval_string(const char *input, int *res) {
|
||||||
*res = lhs Operator *res; \
|
*res = lhs Operator *res; \
|
||||||
return true; \
|
return true; \
|
||||||
}
|
}
|
||||||
|
static int my_pow(int lhs, int rhs) {
|
||||||
|
if (!rhs)
|
||||||
|
return 1;
|
||||||
|
int rec = my_pow(lhs * lhs, rhs / 2);
|
||||||
|
if (rhs & 1)
|
||||||
|
rec *= lhs;
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
|
#define POWER(Name, NulPrio, LeftPrio, Operator) \
|
||||||
|
LeftFunc(Name) { \
|
||||||
|
if (!parse_until(input, res, LeftPrio - 1)) \
|
||||||
|
return false; \
|
||||||
|
*res = my_pow(lhs, *res); \
|
||||||
|
return true; \
|
||||||
|
}
|
||||||
#define TERN(Name, NulPrio, LeftPrio, Operator) \
|
#define TERN(Name, NulPrio, LeftPrio, Operator) \
|
||||||
LeftFunc(Name) { \
|
LeftFunc(Name) { \
|
||||||
int true_val; \
|
int true_val; \
|
||||||
|
|
|
@ -8,12 +8,13 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Simple operators
|
// Simple operators
|
||||||
OP( PLUS_PLUS, 120, 110, PREFIX_POSTFIX, ++, '+', '+', 0)
|
OP( PLUS_PLUS, 130, 120, PREFIX_POSTFIX, ++, '+', '+', 0)
|
||||||
OP(MINUS_MINUS, 120, 110, PREFIX_POSTFIX, --, '-', '-', 0)
|
OP(MINUS_MINUS, 130, 120, PREFIX_POSTFIX, --, '-', '-', 0)
|
||||||
OP( NOT, 120, -1, PREFIX, !, '!', 0)
|
OP( NOT, 130, -1, PREFIX, !, '!', 0)
|
||||||
OP( BIT_NOT, 120, -1, PREFIX, ~, '~', 0)
|
OP( BIT_NOT, 130, -1, PREFIX, ~, '~', 0)
|
||||||
OP( PLUS, 110, 90, PREFIX_INFIX, +, '+', 0)
|
OP( PLUS, 120, 90, PREFIX_INFIX, +, '+', 0)
|
||||||
OP( MINUS, 110, 90, PREFIX_INFIX, -, '-', 0)
|
OP( MINUS, 120, 90, PREFIX_INFIX, -, '-', 0)
|
||||||
|
OP( POWER, -1, 110, POWER, PLACEHOLDER, '*', '*', 0)
|
||||||
OP( TIMES, -1, 100, INFIX, *, '*', 0)
|
OP( TIMES, -1, 100, INFIX, *, '*', 0)
|
||||||
OP( DIVIDES, -1, 100, INFIX, /, '/', 0)
|
OP( DIVIDES, -1, 100, INFIX, /, '/', 0)
|
||||||
OP( MODULO, -1, 100, INFIX, %, '%', 0)
|
OP( MODULO, -1, 100, INFIX, %, '%', 0)
|
||||||
|
@ -40,6 +41,7 @@ OP( NUMBER, 0, -1, NOT_OP, PLACEHOLDER, 0)
|
||||||
#undef PREFIX
|
#undef PREFIX
|
||||||
#undef PREFIX_INFIX
|
#undef PREFIX_INFIX
|
||||||
#undef INFIX
|
#undef INFIX
|
||||||
|
#undef POWER
|
||||||
#undef TERN
|
#undef TERN
|
||||||
#undef PAREN
|
#undef PAREN
|
||||||
#undef NOT_OP
|
#undef NOT_OP
|
||||||
|
|
Loading…
Reference in a new issue