evalexpr: parse: use single 'ops' table

This commit is contained in:
Bruno BELANYI 2020-10-30 18:31:15 +01:00
parent 81f7d30ddd
commit 88b7f50a3a
1 changed files with 16 additions and 36 deletions

View File

@ -10,6 +10,19 @@
#define UNREACHABLE() __builtin_unreachable()
#define ARR_SIZE(Arr) (sizeof(Arr) / sizeof(*Arr))
static const struct {
const char *op;
const int kind; // Because we store different kinds of enum...
const int prio;
const enum { ASSOC_LEFT, ASSOC_RIGHT, ASSOC_NONE } assoc;
const enum { OP_INFIX, OP_PREFIX, OP_POSTFIX } fix;
} ops[] = {
# define BINOP(Op, Kind, Prio, Assoc, Fix) { #Op, Kind, Prio, Assoc, Fix },
# define PREOP(Op, Kind, Prio, Assoc, Fix) { #Op, Kind, Prio, Assoc, Fix },
# define POSTOP(Op, Kind, Prio, Assoc, Fix) { #Op, Kind, Prio, Assoc, Fix },
#include "operators.inc"
};
static struct ast_node *climbing_parse_internal(const char **input, int prec);
static struct ast_node *parse_operand(const char **input);
@ -26,13 +39,8 @@ static void skip_whitespace(const char **input)
static enum binop_kind char_to_binop(char c)
{
static const struct { const char *op; const enum binop_kind kind; } ops[] = {
#define BINOP(Op, Kind, _, __, ___) { #Op, Kind },
#include "operators.inc"
};
for (size_t i = 0; i < ARR_SIZE(ops); ++i)
if (c == ops[i].op[0])
if (ops[i].fix == OP_INFIX && c == ops[i].op[0])
return ops[i].kind;
UNREACHABLE();
@ -40,14 +48,8 @@ static enum binop_kind char_to_binop(char c)
static enum unop_kind char_to_unop(char c)
{
static const struct { const char *op; const enum unop_kind kind; } ops[] = {
#define PREOP(Op, Kind, _, __, ___) { #Op, Kind },
#define POSTOP(Op, Kind, _, __, ___) { #Op, Kind },
#include "operators.inc"
};
for (size_t i = 0; i < ARR_SIZE(ops); ++i)
if (c == ops[i].op[0])
if (ops[i].fix != OP_INFIX && c == ops[i].op[0])
return ops[i].kind;
UNREACHABLE();
@ -55,12 +57,8 @@ static enum unop_kind char_to_unop(char c)
static bool is_binop(char c)
{
static const char *ops[] = {
#define BINOP(Op, _, __, ___, ____) #Op,
#include "operators.inc"
};
for (size_t i = 0; i < ARR_SIZE(ops); ++i)
if (c == ops[i][0])
if (ops[i].fix == OP_INFIX && c == ops[i].op[0])
return true;
return false;
@ -68,13 +66,6 @@ static bool is_binop(char c)
static bool prec_between(const char **input, int min, int max)
{
static const struct { const char *op; const int prio; } ops[] = {
#define BINOP(Op, _, Priority, __, ___) { #Op, Priority },
#define PREOP(Op, _, Priority, __, ___) { #Op, Priority },
#define POSTOP(Op, _, Priority, __, ___) { #Op, Priority },
#include "operators.inc"
};
skip_whitespace(input);
for (size_t i = 0; i < ARR_SIZE(ops); ++i)
@ -84,17 +75,6 @@ static bool prec_between(const char **input, int min, int max)
return false;
}
static const struct {
const char *op;
const int kind; // Because we store different kinds of enum...
const int prio;
const enum { ASSOC_LEFT, ASSOC_RIGHT, ASSOC_NONE } assoc;
const enum { OP_INFIX, OP_PREFIX, OP_POSTFIX } fix;
} ops[] = {
# define BINOP(Op, Kind, Prio, Assoc, Fix) { #Op, Kind, Prio, Assoc, Fix },
#include "operators.inc"
};
static int right_prec(char c)
{
for (size_t i = 0; i < ARR_SIZE(ops); ++i)