Mathematica-like environment on the mbed using USB keyboard input, VGA output, and a thermal printer.
Dependencies: mbed Thermal 4DGL-uLCD-SE USBHost_Modified uVGAIII
tree.c@6:646d22295054, 2018-12-13 (annotated)
- Committer:
- zrussell3
- Date:
- Thu Dec 13 20:27:21 2018 +0000
- Revision:
- 6:646d22295054
Implemented parsing
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
zrussell3 | 6:646d22295054 | 1 | #include "tree.h" |
zrussell3 | 6:646d22295054 | 2 | #include <stdlib.h> |
zrussell3 | 6:646d22295054 | 3 | #include <stdio.h> |
zrussell3 | 6:646d22295054 | 4 | #include <math.h> |
zrussell3 | 6:646d22295054 | 5 | #include <string.h> |
zrussell3 | 6:646d22295054 | 6 | |
zrussell3 | 6:646d22295054 | 7 | /* Returns a string for each type of operator */ |
zrussell3 | 6:646d22295054 | 8 | float eval_node(struct node* node, int level); |
zrussell3 | 6:646d22295054 | 9 | void set_number_node(struct node* node, float num); |
zrussell3 | 6:646d22295054 | 10 | |
zrussell3 | 6:646d22295054 | 11 | /* local variables */ |
zrussell3 | 6:646d22295054 | 12 | struct node* expr_root_node; |
zrussell3 | 6:646d22295054 | 13 | float Xvalue; |
zrussell3 | 6:646d22295054 | 14 | |
zrussell3 | 6:646d22295054 | 15 | float eval_expr(struct node* node, float x_value) { |
zrussell3 | 6:646d22295054 | 16 | Xvalue = x_value; |
zrussell3 | 6:646d22295054 | 17 | return eval_node(node, 0); |
zrussell3 | 6:646d22295054 | 18 | } |
zrussell3 | 6:646d22295054 | 19 | |
zrussell3 | 6:646d22295054 | 20 | float p(float l) { |
zrussell3 | 6:646d22295054 | 21 | // printf(" op val: %g\n", l); |
zrussell3 | 6:646d22295054 | 22 | return l; |
zrussell3 | 6:646d22295054 | 23 | } |
zrussell3 | 6:646d22295054 | 24 | |
zrussell3 | 6:646d22295054 | 25 | float eval_op (struct node* op, int level) { |
zrussell3 | 6:646d22295054 | 26 | float right = eval_node(op->right, level+1); |
zrussell3 | 6:646d22295054 | 27 | float left = eval_node(op->left, level+1); |
zrussell3 | 6:646d22295054 | 28 | |
zrussell3 | 6:646d22295054 | 29 | switch(op->data.op) { |
zrussell3 | 6:646d22295054 | 30 | case OP_ADD: return p(left + right); |
zrussell3 | 6:646d22295054 | 31 | case OP_SUB: return p(left - right); |
zrussell3 | 6:646d22295054 | 32 | case OP_MUL: return p(left * right); |
zrussell3 | 6:646d22295054 | 33 | case OP_DIV: return p(left / right); |
zrussell3 | 6:646d22295054 | 34 | case OP_EXP: return p(pow(left,right)); |
zrussell3 | 6:646d22295054 | 35 | default: |
zrussell3 | 6:646d22295054 | 36 | fprintf(stderr, "%d not defined as an operator in decode_op_type\n", op->data.op); |
zrussell3 | 6:646d22295054 | 37 | exit(1); |
zrussell3 | 6:646d22295054 | 38 | } |
zrussell3 | 6:646d22295054 | 39 | |
zrussell3 | 6:646d22295054 | 40 | } |
zrussell3 | 6:646d22295054 | 41 | |
zrussell3 | 6:646d22295054 | 42 | void set_root_node(struct node* node) { |
zrussell3 | 6:646d22295054 | 43 | expr_root_node = node; |
zrussell3 | 6:646d22295054 | 44 | } |
zrussell3 | 6:646d22295054 | 45 | |
zrussell3 | 6:646d22295054 | 46 | float eval_node(struct node* node, int level) { |
zrussell3 | 6:646d22295054 | 47 | switch(node->type) { |
zrussell3 | 6:646d22295054 | 48 | case NODE_NUMBER: |
zrussell3 | 6:646d22295054 | 49 | return node->data.fval; |
zrussell3 | 6:646d22295054 | 50 | |
zrussell3 | 6:646d22295054 | 51 | case NODE_VAR: |
zrussell3 | 6:646d22295054 | 52 | // printf("eval var x: %s\n",node->data.name); |
zrussell3 | 6:646d22295054 | 53 | // printf("eval var x: %d\n",node->type); |
zrussell3 | 6:646d22295054 | 54 | // printf("eval var x: %g\n",node->data.fval); |
zrussell3 | 6:646d22295054 | 55 | if (strcmp(node->data.name,"x")==0) { |
zrussell3 | 6:646d22295054 | 56 | return Xvalue; |
zrussell3 | 6:646d22295054 | 57 | } else { |
zrussell3 | 6:646d22295054 | 58 | fprintf(stderr,"Cannot parse variables: %s\n", node->data.name); |
zrussell3 | 6:646d22295054 | 59 | exit(1); |
zrussell3 | 6:646d22295054 | 60 | } |
zrussell3 | 6:646d22295054 | 61 | |
zrussell3 | 6:646d22295054 | 62 | case NODE_BINOP: |
zrussell3 | 6:646d22295054 | 63 | return eval_op(node, level+1); |
zrussell3 | 6:646d22295054 | 64 | |
zrussell3 | 6:646d22295054 | 65 | case NODE_FUNC: |
zrussell3 | 6:646d22295054 | 66 | if (strcmp(node->data.name,"sin")==0) { |
zrussell3 | 6:646d22295054 | 67 | printf("Calling function: sin(...)\n"); |
zrussell3 | 6:646d22295054 | 68 | float y = eval_node(node->left, level+1); |
zrussell3 | 6:646d22295054 | 69 | return sin(y); |
zrussell3 | 6:646d22295054 | 70 | } |
zrussell3 | 6:646d22295054 | 71 | if (strcmp(node->data.name,"cos")==0) { |
zrussell3 | 6:646d22295054 | 72 | printf("Calling function: cos(...)\n"); |
zrussell3 | 6:646d22295054 | 73 | float y = eval_node(node->left, level+1); |
zrussell3 | 6:646d22295054 | 74 | return cos(y); |
zrussell3 | 6:646d22295054 | 75 | } |
zrussell3 | 6:646d22295054 | 76 | if (strcmp(node->data.name,"tan")==0) { |
zrussell3 | 6:646d22295054 | 77 | printf("Calling function: tan(...)\n"); |
zrussell3 | 6:646d22295054 | 78 | float y = eval_node(node->left, level+1); |
zrussell3 | 6:646d22295054 | 79 | return tan(y); |
zrussell3 | 6:646d22295054 | 80 | } |
zrussell3 | 6:646d22295054 | 81 | } |
zrussell3 | 6:646d22295054 | 82 | |
zrussell3 | 6:646d22295054 | 83 | exit(1); |
zrussell3 | 6:646d22295054 | 84 | } |
zrussell3 | 6:646d22295054 | 85 | |
zrussell3 | 6:646d22295054 | 86 | |
zrussell3 | 6:646d22295054 | 87 | struct node* new_number_node(float num){ |
zrussell3 | 6:646d22295054 | 88 | struct node* node = calloc(sizeof(*node),1); |
zrussell3 | 6:646d22295054 | 89 | node->type = NODE_NUMBER; |
zrussell3 | 6:646d22295054 | 90 | node->data.fval = num; |
zrussell3 | 6:646d22295054 | 91 | node->left = NULL; |
zrussell3 | 6:646d22295054 | 92 | node->right = NULL; |
zrussell3 | 6:646d22295054 | 93 | node->parent = NULL; |
zrussell3 | 6:646d22295054 | 94 | return node; |
zrussell3 | 6:646d22295054 | 95 | } |
zrussell3 | 6:646d22295054 | 96 | |
zrussell3 | 6:646d22295054 | 97 | |
zrussell3 | 6:646d22295054 | 98 | struct node* new_var_node(char* str){ |
zrussell3 | 6:646d22295054 | 99 | struct node* node = calloc(sizeof(*node),1); |
zrussell3 | 6:646d22295054 | 100 | node->type = NODE_VAR; |
zrussell3 | 6:646d22295054 | 101 | node->data.name = str; |
zrussell3 | 6:646d22295054 | 102 | node->left = NULL; |
zrussell3 | 6:646d22295054 | 103 | node->right = NULL; |
zrussell3 | 6:646d22295054 | 104 | node->parent = NULL; |
zrussell3 | 6:646d22295054 | 105 | return node; |
zrussell3 | 6:646d22295054 | 106 | } |
zrussell3 | 6:646d22295054 | 107 | |
zrussell3 | 6:646d22295054 | 108 | |
zrussell3 | 6:646d22295054 | 109 | struct node* new_binop_node(enum op_type op, struct node* left, struct node *right){ |
zrussell3 | 6:646d22295054 | 110 | struct node* node = calloc(sizeof(*node),1); |
zrussell3 | 6:646d22295054 | 111 | node->type = NODE_BINOP; |
zrussell3 | 6:646d22295054 | 112 | node->data.op = op; |
zrussell3 | 6:646d22295054 | 113 | node->left = left; |
zrussell3 | 6:646d22295054 | 114 | node->left->parent = node; |
zrussell3 | 6:646d22295054 | 115 | node->right = right; |
zrussell3 | 6:646d22295054 | 116 | node->right->parent = node; |
zrussell3 | 6:646d22295054 | 117 | node->parent = NULL; |
zrussell3 | 6:646d22295054 | 118 | return node; |
zrussell3 | 6:646d22295054 | 119 | } |
zrussell3 | 6:646d22295054 | 120 | |
zrussell3 | 6:646d22295054 | 121 | struct node* new_binop_node_no_right(enum op_type op, struct node* left){ |
zrussell3 | 6:646d22295054 | 122 | struct node* node = calloc(sizeof(*node),1); |
zrussell3 | 6:646d22295054 | 123 | node->type = NODE_BINOP; |
zrussell3 | 6:646d22295054 | 124 | node->data.op = op; |
zrussell3 | 6:646d22295054 | 125 | node->left = left; |
zrussell3 | 6:646d22295054 | 126 | node->left->parent = node; |
zrussell3 | 6:646d22295054 | 127 | node->right = NULL; |
zrussell3 | 6:646d22295054 | 128 | node->parent = NULL; |
zrussell3 | 6:646d22295054 | 129 | return node; |
zrussell3 | 6:646d22295054 | 130 | } |
zrussell3 | 6:646d22295054 | 131 | |
zrussell3 | 6:646d22295054 | 132 | struct node* new_func_node(char* name, struct node* left){ |
zrussell3 | 6:646d22295054 | 133 | struct node* node = calloc(sizeof(*node),1); |
zrussell3 | 6:646d22295054 | 134 | node->type = NODE_FUNC; |
zrussell3 | 6:646d22295054 | 135 | node->data.name = name; |
zrussell3 | 6:646d22295054 | 136 | node->left = left; |
zrussell3 | 6:646d22295054 | 137 | node->left->parent = node; |
zrussell3 | 6:646d22295054 | 138 | node->right = NULL; |
zrussell3 | 6:646d22295054 | 139 | node->parent = NULL; |
zrussell3 | 6:646d22295054 | 140 | return node; |
zrussell3 | 6:646d22295054 | 141 | } |
zrussell3 | 6:646d22295054 | 142 | |
zrussell3 | 6:646d22295054 | 143 | struct node* new_func_node_no_left(char* name) { |
zrussell3 | 6:646d22295054 | 144 | struct node* node = calloc(sizeof(*node),1); |
zrussell3 | 6:646d22295054 | 145 | node->type = NODE_FUNC; |
zrussell3 | 6:646d22295054 | 146 | node->data.name = name; |
zrussell3 | 6:646d22295054 | 147 | node->left = NULL; |
zrussell3 | 6:646d22295054 | 148 | node->right = NULL; |
zrussell3 | 6:646d22295054 | 149 | node->parent = NULL; |
zrussell3 | 6:646d22295054 | 150 | return node; |
zrussell3 | 6:646d22295054 | 151 | } |
zrussell3 | 6:646d22295054 | 152 | |
zrussell3 | 6:646d22295054 | 153 | // Try to match a number token |
zrussell3 | 6:646d22295054 | 154 | // >0 success |
zrussell3 | 6:646d22295054 | 155 | // 0 no match |
zrussell3 | 6:646d22295054 | 156 | // -1 syntax error |
zrussell3 | 6:646d22295054 | 157 | int isNumber(const char* expr) { |
zrussell3 | 6:646d22295054 | 158 | int len = strlen(expr); |
zrussell3 | 6:646d22295054 | 159 | int num_of_dots = 0; |
zrussell3 | 6:646d22295054 | 160 | int i =0; |
zrussell3 | 6:646d22295054 | 161 | |
zrussell3 | 6:646d22295054 | 162 | for (int i=0; i<len; i++) { |
zrussell3 | 6:646d22295054 | 163 | switch(expr[i]) { |
zrussell3 | 6:646d22295054 | 164 | |
zrussell3 | 6:646d22295054 | 165 | // find digit, '.' |
zrussell3 | 6:646d22295054 | 166 | case '0' ... '9': |
zrussell3 | 6:646d22295054 | 167 | continue; |
zrussell3 | 6:646d22295054 | 168 | case '.': |
zrussell3 | 6:646d22295054 | 169 | num_of_dots++; |
zrussell3 | 6:646d22295054 | 170 | if (num_of_dots>1) |
zrussell3 | 6:646d22295054 | 171 | return -num_of_dots; // an error |
zrussell3 | 6:646d22295054 | 172 | continue; |
zrussell3 | 6:646d22295054 | 173 | |
zrussell3 | 6:646d22295054 | 174 | // legal end of match |
zrussell3 | 6:646d22295054 | 175 | case ' ' : |
zrussell3 | 6:646d22295054 | 176 | case '\t': |
zrussell3 | 6:646d22295054 | 177 | case '\n': |
zrussell3 | 6:646d22295054 | 178 | case '(' : |
zrussell3 | 6:646d22295054 | 179 | case ')' : |
zrussell3 | 6:646d22295054 | 180 | case '+' : |
zrussell3 | 6:646d22295054 | 181 | case '-' : |
zrussell3 | 6:646d22295054 | 182 | case '*' : |
zrussell3 | 6:646d22295054 | 183 | case '/' : |
zrussell3 | 6:646d22295054 | 184 | case '^' : |
zrussell3 | 6:646d22295054 | 185 | return i; |
zrussell3 | 6:646d22295054 | 186 | |
zrussell3 | 6:646d22295054 | 187 | // error end of match |
zrussell3 | 6:646d22295054 | 188 | default: |
zrussell3 | 6:646d22295054 | 189 | return -i; |
zrussell3 | 6:646d22295054 | 190 | } |
zrussell3 | 6:646d22295054 | 191 | } |
zrussell3 | 6:646d22295054 | 192 | return i; |
zrussell3 | 6:646d22295054 | 193 | } |
zrussell3 | 6:646d22295054 | 194 | |
zrussell3 | 6:646d22295054 | 195 | int isFunc(const char* expr) { |
zrussell3 | 6:646d22295054 | 196 | for (int i=0; i<strlen(expr); i++) { |
zrussell3 | 6:646d22295054 | 197 | switch(expr[i]) { |
zrussell3 | 6:646d22295054 | 198 | case 'a' ... 'z': |
zrussell3 | 6:646d22295054 | 199 | case 'A' ... 'Z': |
zrussell3 | 6:646d22295054 | 200 | case '_': |
zrussell3 | 6:646d22295054 | 201 | continue; |
zrussell3 | 6:646d22295054 | 202 | case '(': |
zrussell3 | 6:646d22295054 | 203 | return i; |
zrussell3 | 6:646d22295054 | 204 | default: |
zrussell3 | 6:646d22295054 | 205 | return i==0 ? -1 : -i; |
zrussell3 | 6:646d22295054 | 206 | } |
zrussell3 | 6:646d22295054 | 207 | } |
zrussell3 | 6:646d22295054 | 208 | return -1; |
zrussell3 | 6:646d22295054 | 209 | } |
zrussell3 | 6:646d22295054 | 210 | |
zrussell3 | 6:646d22295054 | 211 | int isVar(const char* expr) { |
zrussell3 | 6:646d22295054 | 212 | if (strlen(expr)==0) |
zrussell3 | 6:646d22295054 | 213 | return 0; |
zrussell3 | 6:646d22295054 | 214 | |
zrussell3 | 6:646d22295054 | 215 | for (int i=0; i<strlen(expr); i++) { |
zrussell3 | 6:646d22295054 | 216 | // match var name |
zrussell3 | 6:646d22295054 | 217 | switch(expr[i]) { |
zrussell3 | 6:646d22295054 | 218 | case 'a' ... 'z': |
zrussell3 | 6:646d22295054 | 219 | case 'A' ... 'Z': |
zrussell3 | 6:646d22295054 | 220 | case '_': |
zrussell3 | 6:646d22295054 | 221 | continue; |
zrussell3 | 6:646d22295054 | 222 | |
zrussell3 | 6:646d22295054 | 223 | // match terminating character |
zrussell3 | 6:646d22295054 | 224 | case ' ' : |
zrussell3 | 6:646d22295054 | 225 | case '\t': |
zrussell3 | 6:646d22295054 | 226 | case '\n': |
zrussell3 | 6:646d22295054 | 227 | case ')' : |
zrussell3 | 6:646d22295054 | 228 | case '+' : |
zrussell3 | 6:646d22295054 | 229 | case '-' : |
zrussell3 | 6:646d22295054 | 230 | case '*' : |
zrussell3 | 6:646d22295054 | 231 | case '/' : |
zrussell3 | 6:646d22295054 | 232 | case '^' : |
zrussell3 | 6:646d22295054 | 233 | return i; |
zrussell3 | 6:646d22295054 | 234 | default: |
zrussell3 | 6:646d22295054 | 235 | return i==0 ? -1 : -i; |
zrussell3 | 6:646d22295054 | 236 | } |
zrussell3 | 6:646d22295054 | 237 | } |
zrussell3 | 6:646d22295054 | 238 | return -1; |
zrussell3 | 6:646d22295054 | 239 | } |
zrussell3 | 6:646d22295054 | 240 | |
zrussell3 | 6:646d22295054 | 241 | // Add right side of OP |
zrussell3 | 6:646d22295054 | 242 | struct node* add_right(struct node* node, struct node* right){ |
zrussell3 | 6:646d22295054 | 243 | node->right = right; |
zrussell3 | 6:646d22295054 | 244 | right->parent = node; |
zrussell3 | 6:646d22295054 | 245 | return right; |
zrussell3 | 6:646d22295054 | 246 | } |
zrussell3 | 6:646d22295054 | 247 | |
zrussell3 | 6:646d22295054 | 248 | // Add right side of OP |
zrussell3 | 6:646d22295054 | 249 | struct node* add_left(struct node* node, struct node* left){ |
zrussell3 | 6:646d22295054 | 250 | node->left = left; |
zrussell3 | 6:646d22295054 | 251 | left->parent = node; |
zrussell3 | 6:646d22295054 | 252 | return left; |
zrussell3 | 6:646d22295054 | 253 | } |
zrussell3 | 6:646d22295054 | 254 | |
zrussell3 | 6:646d22295054 | 255 | // Add a Node |
zrussell3 | 6:646d22295054 | 256 | struct node* add_op(struct node* left, enum op_type op) { |
zrussell3 | 6:646d22295054 | 257 | struct node* binop = NULL; |
zrussell3 | 6:646d22295054 | 258 | struct node* parent = NULL; |
zrussell3 | 6:646d22295054 | 259 | |
zrussell3 | 6:646d22295054 | 260 | // no precedence ordering required |
zrussell3 | 6:646d22295054 | 261 | if (left->parent==NULL) { |
zrussell3 | 6:646d22295054 | 262 | return new_binop_node_no_right(op, left); |
zrussell3 | 6:646d22295054 | 263 | } |
zrussell3 | 6:646d22295054 | 264 | |
zrussell3 | 6:646d22295054 | 265 | // new operation is same or higher precedence, so append as child of branch |
zrussell3 | 6:646d22295054 | 266 | if (op >= left->parent->data.op) { |
zrussell3 | 6:646d22295054 | 267 | parent = left->parent; |
zrussell3 | 6:646d22295054 | 268 | binop = new_binop_node_no_right(op, left); |
zrussell3 | 6:646d22295054 | 269 | add_right(parent, binop); |
zrussell3 | 6:646d22295054 | 270 | return binop; |
zrussell3 | 6:646d22295054 | 271 | } |
zrussell3 | 6:646d22295054 | 272 | |
zrussell3 | 6:646d22295054 | 273 | // traverse up the tree until no more parents or parent operation is lower precedence |
zrussell3 | 6:646d22295054 | 274 | return add_op(left->parent, op); |
zrussell3 | 6:646d22295054 | 275 | } |
zrussell3 | 6:646d22295054 | 276 | |
zrussell3 | 6:646d22295054 | 277 | // scanner and parser |
zrussell3 | 6:646d22295054 | 278 | struct node* scanner(const char* es) { |
zrussell3 | 6:646d22295054 | 279 | char buff[200]; |
zrussell3 | 6:646d22295054 | 280 | int len = strlen(es); |
zrussell3 | 6:646d22295054 | 281 | struct node* left = NULL; |
zrussell3 | 6:646d22295054 | 282 | int lookahead = -1; // 0: fails, >0: success |
zrussell3 | 6:646d22295054 | 283 | |
zrussell3 | 6:646d22295054 | 284 | for (int i=0; i<len; i++) { |
zrussell3 | 6:646d22295054 | 285 | |
zrussell3 | 6:646d22295054 | 286 | switch(es[i]) { |
zrussell3 | 6:646d22295054 | 287 | // skip space |
zrussell3 | 6:646d22295054 | 288 | case ' ' : continue; // printf("[space]"); |
zrussell3 | 6:646d22295054 | 289 | case '\t': continue; // printf("[tab]"); |
zrussell3 | 6:646d22295054 | 290 | case '\n': continue; // printf("[newline]"); |
zrussell3 | 6:646d22295054 | 291 | |
zrussell3 | 6:646d22295054 | 292 | // find number |
zrussell3 | 6:646d22295054 | 293 | case '0' ... '9': |
zrussell3 | 6:646d22295054 | 294 | case '.': |
zrussell3 | 6:646d22295054 | 295 | lookahead = isNumber(&es[i+1]); |
zrussell3 | 6:646d22295054 | 296 | if (lookahead>=0) { |
zrussell3 | 6:646d22295054 | 297 | memcpy(buff, &es[i], lookahead+1); |
zrussell3 | 6:646d22295054 | 298 | buff[lookahead+1] = (char) 0; |
zrussell3 | 6:646d22295054 | 299 | i = i + lookahead; |
zrussell3 | 6:646d22295054 | 300 | // printf("token-number: '%s' (atof:%f)\n", buff,atof(buff)); |
zrussell3 | 6:646d22295054 | 301 | |
zrussell3 | 6:646d22295054 | 302 | if (left==NULL) { |
zrussell3 | 6:646d22295054 | 303 | left = new_number_node(atof(buff)); |
zrussell3 | 6:646d22295054 | 304 | } else if (left->type==NODE_BINOP) { |
zrussell3 | 6:646d22295054 | 305 | left = add_right(left, new_number_node(atof(buff))); |
zrussell3 | 6:646d22295054 | 306 | } else if (left->type==NODE_FUNC) { |
zrussell3 | 6:646d22295054 | 307 | left = add_left(left, new_number_node(atof(buff))); |
zrussell3 | 6:646d22295054 | 308 | left = left->parent; |
zrussell3 | 6:646d22295054 | 309 | } |
zrussell3 | 6:646d22295054 | 310 | } |
zrussell3 | 6:646d22295054 | 311 | continue; |
zrussell3 | 6:646d22295054 | 312 | |
zrussell3 | 6:646d22295054 | 313 | // operators |
zrussell3 | 6:646d22295054 | 314 | case '+' : |
zrussell3 | 6:646d22295054 | 315 | // printf("token-add: '%c'\n", es[i]); |
zrussell3 | 6:646d22295054 | 316 | left = add_op(left, OP_ADD); |
zrussell3 | 6:646d22295054 | 317 | continue; |
zrussell3 | 6:646d22295054 | 318 | case '-' : |
zrussell3 | 6:646d22295054 | 319 | // printf("token-sub: '%c'\n", es[i]); |
zrussell3 | 6:646d22295054 | 320 | left = add_op(left, OP_SUB); |
zrussell3 | 6:646d22295054 | 321 | continue; |
zrussell3 | 6:646d22295054 | 322 | case '*' : |
zrussell3 | 6:646d22295054 | 323 | // printf("token-mul: '%c'\n", es[i]); |
zrussell3 | 6:646d22295054 | 324 | left = add_op(left, OP_MUL); |
zrussell3 | 6:646d22295054 | 325 | continue; |
zrussell3 | 6:646d22295054 | 326 | case '/' : |
zrussell3 | 6:646d22295054 | 327 | // printf("token-div: '%c'\n", es[i]); |
zrussell3 | 6:646d22295054 | 328 | left = add_op(left, OP_DIV); |
zrussell3 | 6:646d22295054 | 329 | continue; |
zrussell3 | 6:646d22295054 | 330 | case '^' : |
zrussell3 | 6:646d22295054 | 331 | // printf("token-exp: '%c'\n", es[i]); |
zrussell3 | 6:646d22295054 | 332 | left = add_op(left, OP_EXP); |
zrussell3 | 6:646d22295054 | 333 | continue; |
zrussell3 | 6:646d22295054 | 334 | |
zrussell3 | 6:646d22295054 | 335 | case 'a' ... 'z': |
zrussell3 | 6:646d22295054 | 336 | case 'A' ... 'Z': |
zrussell3 | 6:646d22295054 | 337 | // find function |
zrussell3 | 6:646d22295054 | 338 | lookahead = isFunc(&es[i+1]); |
zrussell3 | 6:646d22295054 | 339 | if (lookahead>=0) { |
zrussell3 | 6:646d22295054 | 340 | memcpy(buff, &es[i], lookahead+1); |
zrussell3 | 6:646d22295054 | 341 | buff[lookahead+1] = (char) 0; |
zrussell3 | 6:646d22295054 | 342 | printf("token-func: '%s'\n", buff); |
zrussell3 | 6:646d22295054 | 343 | i = i + lookahead; |
zrussell3 | 6:646d22295054 | 344 | /* |
zrussell3 | 6:646d22295054 | 345 | if (left==NULL) { |
zrussell3 | 6:646d22295054 | 346 | left = new_func_node(buff); |
zrussell3 | 6:646d22295054 | 347 | } else if (left->type==NODE_BINOP) { |
zrussell3 | 6:646d22295054 | 348 | left = add_right(left, new_func_node(buff)); |
zrussell3 | 6:646d22295054 | 349 | } |
zrussell3 | 6:646d22295054 | 350 | */ continue; |
zrussell3 | 6:646d22295054 | 351 | } |
zrussell3 | 6:646d22295054 | 352 | |
zrussell3 | 6:646d22295054 | 353 | // find variable |
zrussell3 | 6:646d22295054 | 354 | lookahead = isVar(&es[i+1]); |
zrussell3 | 6:646d22295054 | 355 | if (lookahead>=0) { |
zrussell3 | 6:646d22295054 | 356 | memcpy(buff, &es[i], lookahead+1); |
zrussell3 | 6:646d22295054 | 357 | buff[lookahead+1] = (char) 0; |
zrussell3 | 6:646d22295054 | 358 | // printf("token-var: '%s'\n", buff); |
zrussell3 | 6:646d22295054 | 359 | i = i + lookahead; |
zrussell3 | 6:646d22295054 | 360 | |
zrussell3 | 6:646d22295054 | 361 | if (left==NULL) { |
zrussell3 | 6:646d22295054 | 362 | left = new_var_node(buff); |
zrussell3 | 6:646d22295054 | 363 | } else if (left->type==NODE_BINOP) { |
zrussell3 | 6:646d22295054 | 364 | left = add_right(left, new_var_node(buff)); |
zrussell3 | 6:646d22295054 | 365 | } |
zrussell3 | 6:646d22295054 | 366 | continue; |
zrussell3 | 6:646d22295054 | 367 | } |
zrussell3 | 6:646d22295054 | 368 | |
zrussell3 | 6:646d22295054 | 369 | // grouping |
zrussell3 | 6:646d22295054 | 370 | case '(' : |
zrussell3 | 6:646d22295054 | 371 | printf("token-l-paren: '%c'\n", es[i]); |
zrussell3 | 6:646d22295054 | 372 | continue; |
zrussell3 | 6:646d22295054 | 373 | case ')' : |
zrussell3 | 6:646d22295054 | 374 | printf("token-r-paren: '%c'\n", es[i]); |
zrussell3 | 6:646d22295054 | 375 | continue; |
zrussell3 | 6:646d22295054 | 376 | |
zrussell3 | 6:646d22295054 | 377 | |
zrussell3 | 6:646d22295054 | 378 | default: ; |
zrussell3 | 6:646d22295054 | 379 | } |
zrussell3 | 6:646d22295054 | 380 | } |
zrussell3 | 6:646d22295054 | 381 | |
zrussell3 | 6:646d22295054 | 382 | // find root |
zrussell3 | 6:646d22295054 | 383 | while (left->parent != NULL) { |
zrussell3 | 6:646d22295054 | 384 | left = left->parent; |
zrussell3 | 6:646d22295054 | 385 | } |
zrussell3 | 6:646d22295054 | 386 | return left; |
zrussell3 | 6:646d22295054 | 387 | } |
zrussell3 | 6:646d22295054 | 388 | |
zrussell3 | 6:646d22295054 | 389 | |
zrussell3 | 6:646d22295054 | 390 | |
zrussell3 | 6:646d22295054 | 391 | /* |
zrussell3 | 6:646d22295054 | 392 | static const char expr_str[] = "5*4 * 3 / 2 - 1 + 37\n"; |
zrussell3 | 6:646d22295054 | 393 | |
zrussell3 | 6:646d22295054 | 394 | // compile expression |
zrussell3 | 6:646d22295054 | 395 | struct node* expr = comp_expr(expr_str); |
zrussell3 | 6:646d22295054 | 396 | |
zrussell3 | 6:646d22295054 | 397 | // evaluate expression |
zrussell3 | 6:646d22295054 | 398 | eval_expr(expr, 1); |
zrussell3 | 6:646d22295054 | 399 | |
zrussell3 | 6:646d22295054 | 400 | // some output |
zrussell3 | 6:646d22295054 | 401 | printf("Expression: %s\n", expr_str); |
zrussell3 | 6:646d22295054 | 402 | x = 3.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 403 | x = 3.5; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 404 | x = 4.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 405 | |
zrussell3 | 6:646d22295054 | 406 | // example 2 |
zrussell3 | 6:646d22295054 | 407 | static const char str2[] = "5*4 * 3 / 2 - x + 37\n"; |
zrussell3 | 6:646d22295054 | 408 | expr = comp_expr(str2); |
zrussell3 | 6:646d22295054 | 409 | eval_expr(expr, 1); |
zrussell3 | 6:646d22295054 | 410 | |
zrussell3 | 6:646d22295054 | 411 | printf("Expression: %s\n", str2); |
zrussell3 | 6:646d22295054 | 412 | x = 1.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 413 | x = 3.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 414 | x = 3.5; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 415 | x = 4.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 416 | |
zrussell3 | 6:646d22295054 | 417 | |
zrussell3 | 6:646d22295054 | 418 | // example 3 |
zrussell3 | 6:646d22295054 | 419 | static const char str3[] = "5*4 * 3 / 2 - 1 + 37 + sin(x)\n"; |
zrussell3 | 6:646d22295054 | 420 | expr = comp_expr(str3); |
zrussell3 | 6:646d22295054 | 421 | eval_expr(expr, 1); |
zrussell3 | 6:646d22295054 | 422 | |
zrussell3 | 6:646d22295054 | 423 | printf("Expression: %s\n", str3); |
zrussell3 | 6:646d22295054 | 424 | x =-1.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 425 | x = 1.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 426 | x = 3.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 427 | x = 3.5; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 428 | x = 4.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 429 | |
zrussell3 | 6:646d22295054 | 430 | // example 4 |
zrussell3 | 6:646d22295054 | 431 | static const char str4[] = "5*4 * 3 / 2 - 1 + 37 + sin(x) + 2^3\n"; |
zrussell3 | 6:646d22295054 | 432 | expr = comp_expr(str4); |
zrussell3 | 6:646d22295054 | 433 | eval_expr(expr, 1); |
zrussell3 | 6:646d22295054 | 434 | |
zrussell3 | 6:646d22295054 | 435 | printf("Expression: %s\n", str4); |
zrussell3 | 6:646d22295054 | 436 | x = 1.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 437 | x = 5.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 438 | x = 7.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 439 | x = 9.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 440 | x =11.0; printf("Value[x=%2.3g]: %2.3g\n", x, eval_expr(expr, x)); |
zrussell3 | 6:646d22295054 | 441 | */ |
zrussell3 | 6:646d22295054 | 442 |