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)
|
||||
#define INFIX(Name) \
|
||||
LeftFunc(Name)
|
||||
#define POWER(Name) \
|
||||
LeftFunc(Name)
|
||||
#define TERN(Name) \
|
||||
LeftFunc(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), },
|
||||
#define INFIX(Name, NulPrio, LeftPrio, ...) \
|
||||
[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, ...) \
|
||||
[Name] = {OP_STRING(__VA_ARGS__), OP_SIZE(__VA_ARGS__), NulPrio, LeftPrio, NULL, LeftFunc(Name), },
|
||||
#define PAREN(Name, NulPrio, LeftPrio, ...) \
|
||||
|
@ -244,6 +248,21 @@ bool eval_string(const char *input, int *res) {
|
|||
*res = lhs Operator *res; \
|
||||
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) \
|
||||
LeftFunc(Name) { \
|
||||
int true_val; \
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
#endif
|
||||
|
||||
// Simple operators
|
||||
OP( PLUS_PLUS, 120, 110, PREFIX_POSTFIX, ++, '+', '+', 0)
|
||||
OP(MINUS_MINUS, 120, 110, PREFIX_POSTFIX, --, '-', '-', 0)
|
||||
OP( NOT, 120, -1, PREFIX, !, '!', 0)
|
||||
OP( BIT_NOT, 120, -1, PREFIX, ~, '~', 0)
|
||||
OP( PLUS, 110, 90, PREFIX_INFIX, +, '+', 0)
|
||||
OP( MINUS, 110, 90, PREFIX_INFIX, -, '-', 0)
|
||||
OP( PLUS_PLUS, 130, 120, PREFIX_POSTFIX, ++, '+', '+', 0)
|
||||
OP(MINUS_MINUS, 130, 120, PREFIX_POSTFIX, --, '-', '-', 0)
|
||||
OP( NOT, 130, -1, PREFIX, !, '!', 0)
|
||||
OP( BIT_NOT, 130, -1, PREFIX, ~, '~', 0)
|
||||
OP( PLUS, 120, 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( DIVIDES, -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_INFIX
|
||||
#undef INFIX
|
||||
#undef POWER
|
||||
#undef TERN
|
||||
#undef PAREN
|
||||
#undef NOT_OP
|
||||
|
|
Loading…
Reference in a new issue