evalexpr: initial recursive descent parser
This commit is contained in:
commit
a92e39dbec
8 changed files with 536 additions and 0 deletions
69
src/eval/eval.c
Normal file
69
src/eval/eval.c
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#include "eval.h"
|
||||
|
||||
#define UNREACHABLE() __builtin_unreachable()
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int my_fact(int num)
|
||||
{
|
||||
int ret = 1;
|
||||
while (num > 1)
|
||||
ret *= num--;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int eval_unop(const struct unop_node *un_op)
|
||||
{
|
||||
switch (un_op->op)
|
||||
{
|
||||
case UNOP_IDENTITY:
|
||||
return eval_ast(un_op->tree);
|
||||
case UNOP_NEGATE:
|
||||
return -eval_ast(un_op->tree);
|
||||
case UNOP_FACT:
|
||||
return my_fact(eval_ast(un_op->tree));
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
static int eval_binop(const struct binop_node *bin_op)
|
||||
{
|
||||
#define EVAL_OP(OP, TREE) (eval_ast((TREE)->lhs) OP eval_ast((TREE)->rhs))
|
||||
switch (bin_op->op)
|
||||
{
|
||||
case BINOP_PLUS:
|
||||
return EVAL_OP(+, bin_op);
|
||||
case BINOP_MINUS:
|
||||
return EVAL_OP(-, bin_op);
|
||||
case BINOP_TIMES:
|
||||
return EVAL_OP(*, bin_op);
|
||||
case BINOP_DIVIDES:
|
||||
return EVAL_OP(/, bin_op);
|
||||
case BINOP_POW:
|
||||
return my_pow(eval_ast(bin_op->lhs), eval_ast(bin_op->rhs));
|
||||
}
|
||||
#undef EVAL_OP
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
int eval_ast(const struct ast_node *ast)
|
||||
{
|
||||
switch (ast->kind)
|
||||
{
|
||||
case NODE_NUM:
|
||||
return ast->val.num;
|
||||
case NODE_UNOP:
|
||||
return eval_unop(&ast->val.un_op);
|
||||
case NODE_BINOP:
|
||||
return eval_binop(&ast->val.bin_op);
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
8
src/eval/eval.h
Normal file
8
src/eval/eval.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef EVAL_H
|
||||
#define EVAL_H
|
||||
|
||||
#include "ast/ast.h"
|
||||
|
||||
int eval_ast(const struct ast_node *ast);
|
||||
|
||||
#endif /* !EVAL_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue