1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
/*
* expr.h - Expressions and values
*
* Written 2009 by Werner Almesberger
* Copyright 2009 by Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef EXPR_H
#define EXPR_H
#include <math.h>
#define UNDEF HUGE_VAL
struct frame;
struct expr;
struct value;
enum num_type {
nt_none,
nt_mm,
nt_mil,
};
struct num {
enum num_type type;
int exponent;
double n;
};
typedef struct num (*op_type)(const struct expr *self,
const struct frame *frame);
struct expr {
op_type op;
union {
struct num num;
const char *var;
char *str;
struct {
struct expr *a;
struct expr *b;
} op;
} u;
int lineno;
};
extern struct num undef;
#define is_undef(num) ((num).type == nt_none)
#define is_dimensionless(num) (!(num).exponent)
static inline int is_distance(struct num num)
{
return (num.type == nt_mm || num.type == nt_mil) && num.exponent == 1;
}
void fail_expr(const struct expr *expr);
const char *str_unit(struct num n);
static inline struct num make_num(double n)
{
struct num res;
res.type = nt_mm;
res.exponent = 0;
res.n = n;
return res;
}
static inline struct num make_mm(double mm)
{
struct num res;
res.type = nt_mm;
res.exponent = 1;
res.n = mm;
return res;
}
static inline struct num make_mil(double mil)
{
struct num res;
res.type = nt_mil;
res.exponent = 1;
res.n = mil;
return res;
}
int to_unit(struct num *n);
struct num op_num(const struct expr *self, const struct frame *frame);
struct num op_var(const struct expr *self, const struct frame *frame);
struct num op_string(const struct expr *self, const struct frame *frame);
struct num op_sin(const struct expr *self, const struct frame *frame);
struct num op_cos(const struct expr *self, const struct frame *frame);
struct num op_sqrt(const struct expr *self, const struct frame *frame);
struct num op_minus(const struct expr *self, const struct frame *frame);
struct num op_add(const struct expr *self, const struct frame *frame);
struct num op_sub(const struct expr *self, const struct frame *frame);
struct num op_mult(const struct expr *self, const struct frame *frame);
struct num op_div(const struct expr *self, const struct frame *frame);
struct expr *new_op(op_type op);
struct expr *binary_op(op_type op, struct expr *a, struct expr *b);
struct num eval_var(const struct frame *frame, const char *name);
/*
* eval_str returns NULL if the result isn't a string. Evaluation may then
* be attempted with eval_num, and the result can be converted accordingly.
*/
const char *eval_str(const struct expr *expr, const struct frame *frame);
struct num eval_num(const struct expr *expr, const struct frame *frame);
/* if frame == NULL, we only check the syntax without expanding */
char *expand(const char *name, const struct frame *frame);
struct expr *new_num(struct num num);
struct expr *parse_expr(const char *s);
void free_expr(struct expr *expr);
int parse_var(const char *s, const char **id, struct value **values,
int max_values);
int parse_values(const char *s, struct value **values);
void free_values(struct value *values, int keep_expr);
#endif /* !EXPR_H */
|