pratt: eval: add exponentiation operator

This showcases right-associative operators
This commit is contained in:
Bruno BELANYI 2020-11-08 18:42:16 +01:00
parent 3ce0bcf140
commit ee2d8d1e9d
2 changed files with 27 additions and 6 deletions

View file

@ -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; \

View file

@ -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