📄 parser.c
字号:
/* CASE 7: Bad string, give up */ if (PARSE_DEBUG) printf("parse_gen_expr: syntax error [string = \"%s\"] (LINE %d)\n", string, line_count); free_tree_expr(tree_expr); return NULL; }} /* Inserts expressions into tree according to operator precedence. If root is null, a new tree is created, with gen_expr as only element */tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t **root) { tree_expr_t * new_root; /* Sanity check */ if (infix_op == NULL) return NULL; /* The root is null, so make this operator the new root */ if (*root == NULL) { new_root = new_tree_expr(infix_op, NULL, NULL, NULL); *root = new_root; return new_root; } /* The root node is not an infix function, so we make this infix operator the new root */ if ((*root)->infix_op == NULL) { new_root = new_tree_expr(infix_op, NULL, *root, NULL); (*root) = new_root; return new_root; } /* The root is an infix function. If the precedence of the item to be inserted is greater than the root's precedence, then make gen_expr the root */ if (infix_op->precedence > (*root)->infix_op->precedence) { new_root = new_tree_expr(infix_op, NULL, *root, NULL); (*root) = new_root; return new_root; } /* If control flow reaches here, use a recursive helper with the knowledge that the root is higher precedence than the item to be inserted */ insert_infix_rec(infix_op, *root); return *root; }tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root) { tree_expr_t * new_root; /* If someone foolishly passes a null pointer to insert, return the original tree */ if (gen_expr == NULL) { return *root; } /* If the root is null, generate a new expression tree, using the passed expression as the root element */ if (*root == NULL) { new_root = new_tree_expr(NULL, gen_expr, NULL, NULL); *root = new_root; return new_root; } /* Otherwise. the new element definitely will not replace the current root. Use a recursive helper function to do insertion */ insert_gen_rec(gen_expr, *root); return *root;}/* A recursive helper function to insert general expression elements into the operator tree */int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root) { /* Trivial Case: root is null */ if (root == NULL) { ////if (PARSE_DEBUG) printf("insert_gen_rec: root is null, returning failure\n"); return FAILURE; } /* The current node's left pointer is null, and this current node is an infix operator, so insert the general expression at the left pointer */ if ((root->left == NULL) && (root->infix_op != NULL)) { root->left = new_tree_expr(NULL, gen_expr, NULL, NULL); return SUCCESS; } /* The current node's right pointer is null, and this current node is an infix operator, so insert the general expression at the right pointer */ if ((root->right == NULL) && (root->infix_op != NULL)) { root->right = new_tree_expr(NULL, gen_expr, NULL, NULL); return SUCCESS; } /* Otherwise recurse down to the left. If this succeeds then return. If it fails, try recursing down to the right */ if (insert_gen_rec(gen_expr, root->left) == FAILURE) return insert_gen_rec(gen_expr, root->right); /* Impossible for control flow to reach here, but in the world of C programming, who knows... */ //if (PARSE_DEBUG) printf("insert_gen_rec: should never reach here!\n"); return FAILURE; } /* A recursive helper function to insert infix arguments by operator precedence */int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root) { /* Shouldn't happen, implies a parse error */ if (root == NULL) return FAILURE; /* Also shouldn't happen, also implies a (different) parse error */ if (root->infix_op == NULL) return FAILURE; /* Left tree is empty, attach this operator to it. I don't think this will ever happen */ if (root->left == NULL) { root->left = new_tree_expr(infix_op, NULL, root->left, NULL); return SUCCESS; } /* Right tree is empty, attach this operator to it */ if (root->right == NULL) { root->right = new_tree_expr(infix_op, NULL, root->right, NULL); return SUCCESS; } /* The left element can now be ignored, since there is no way for this operator to use those expressions */ /* If the right element is not an infix operator, then insert the expression here, attaching the old right branch to the left of the new expression */ if (root->right->infix_op == NULL) { root->right = new_tree_expr(infix_op, NULL, root->right, NULL); return SUCCESS; } /* Traverse deeper if the inserting operator precedence is less than the the root's right operator precedence */ if (infix_op->precedence < root->right->infix_op->precedence) return insert_infix_rec(infix_op, root->right); /* Otherwise, insert the operator here */ root->right = new_tree_expr(infix_op, NULL, root->right, NULL); return SUCCESS;}/* Parses an infix operator */gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset) { gen_expr_t * gen_expr; switch (token) { /* All the infix operators */ case tPlus: //if (PARSE_DEBUG) printf("parse_infix_op: found addition operator (LINE %d)\n", line_count); return parse_gen_expr(fs, insert_infix_op(infix_add, &tree_expr), preset); case tMinus: //if (PARSE_DEBUG) printf("parse_infix_op: found subtraction operator (LINE %d)\n", line_count); return parse_gen_expr(fs, insert_infix_op(infix_minus, &tree_expr), preset); case tMult: //if (PARSE_DEBUG) printf("parse_infix_op: found multiplication operator (LINE %d)\n", line_count); return parse_gen_expr(fs, insert_infix_op(infix_mult, &tree_expr), preset); case tDiv: //if (PARSE_DEBUG) printf("parse_infix_op: found division operator (LINE %d)\n", line_count); return parse_gen_expr(fs, insert_infix_op(infix_div, &tree_expr), preset); case tMod: //if (PARSE_DEBUG) printf("parse_infix_op: found modulo operator (LINE %d)\n", line_count); return parse_gen_expr(fs, insert_infix_op(infix_mod, &tree_expr), preset); case tOr: //if (PARSE_DEBUG) printf("parse_infix_op: found bitwise or operator (LINE %d)\n", line_count); return parse_gen_expr(fs, insert_infix_op(infix_or, &tree_expr), preset); case tAnd: //if (PARSE_DEBUG) printf("parse_infix_op: found bitwise and operator (LINE %d)\n", line_count); return parse_gen_expr(fs, insert_infix_op(infix_and, &tree_expr), preset); case tPositive: //if (PARSE_DEBUG) printf("parse_infix_op: found positive operator (LINE %d)\n", line_count); return parse_gen_expr(fs, insert_infix_op(infix_positive, &tree_expr), preset); case tNegative: //if (PARSE_DEBUG) printf("parse_infix_op: found negative operator (LINE %d)\n", line_count); return parse_gen_expr(fs, insert_infix_op(infix_negative, &tree_expr), preset); case tEOL: case tEOF: case tSemiColon: case tRPr: case tComma: //if (PARSE_DEBUG) printf("parse_infix_op: terminal found (LINE %d)\n", line_count); gen_expr = new_gen_expr(TREE_T, (void*)tree_expr); return gen_expr; default: //if (PARSE_DEBUG) printf("parse_infix_op: operator or terminal expected, but not found (LINE %d)\n", line_count); free_tree_expr(tree_expr); return NULL; } /* Will never happen */ return NULL; }/* Parses an integer, checks for +/- prefix */int parse_int(FILE * fs, int * int_ptr) {char string[MAX_TOKEN_SIZE]; token_t token; int sign; char * end_ptr = " "; token = parseToken(fs, string); switch (token) { case tMinus: sign = -1; token = parseToken(fs, string); break; case tPlus: sign = 1; token = parseToken(fs, string); break; default: sign = 1; break; } if (string[0] == 0) return PARSE_ERROR; /* Convert the string to an integer. *end_ptr should end up pointing to null terminator of 'string' if the conversion was successful. */ // printf("STRING: \"%s\"\n", string); (*int_ptr) = sign*strtol(string, &end_ptr, 10); /* If end pointer is a return character or null terminator, all is well */ if ((*end_ptr == '\r') || (*end_ptr == '\0')) return SUCCESS; return PARSE_ERROR; }/* Parses a floating point number */int string_to_float(char * string, double * float_ptr) { char ** error_ptr; if (*string == 0) return PARSE_ERROR; error_ptr = malloc(sizeof(char**)); (*float_ptr) = strtod(string, error_ptr); /* These imply a succesful parse of the string */ if ((**error_ptr == '\0') || (**error_ptr == '\r')) { free(error_ptr); return SUCCESS; } (*float_ptr) = 0; free(error_ptr); return PARSE_ERROR; }/* Parses a floating point number */int parse_float(FILE * fs, double * float_ptr) { char string[MAX_TOKEN_SIZE]; char ** error_ptr; token_t token; int sign; error_ptr = malloc(sizeof(char**)); token = parseToken(fs, string); switch (token) { case tMinus: sign = -1; token = parseToken(fs, string); break; case tPlus: sign = 1; token = parseToken(fs, string); break; default: sign = 1; } if (string[0] == 0) { free(error_ptr); return PARSE_ERROR; } (*float_ptr) = sign*strtod(string, error_ptr); /* No conversion was performed */ if ((**error_ptr == '\0') || (**error_ptr == '\r')) { free(error_ptr); return SUCCESS; } //if (PARSE_DEBUG) printf("parse_float: double conversion failed for string \"%s\"\n", string); (*float_ptr) = 0; free(error_ptr); return PARSE_ERROR; }/* Parses a per frame equation. That is, interprets a stream of data as a per frame equation */per_frame_eqn_t * parse_per_frame_eqn(FILE * fs, int index, struct PRESET_T * preset) { char string[MAX_TOKEN_SIZE]; param_t * param; per_frame_eqn_t * per_frame_eqn; gen_expr_t * gen_expr; if (parseToken(fs, string) != tEq) { //if (PARSE_DEBUG) printf("parse_per_frame_eqn: no equal sign after string \"%s\" (LINE %d)\n", string, line_count); return NULL; } /* Find the parameter associated with the string, create one if necessary */ if ((param = find_param(string, preset, P_CREATE)) == NULL) { return NULL; } /* Make sure parameter is writable */ if (param->flags & P_FLAG_READONLY) { //if (PARSE_DEBUG) printf("parse_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count); return NULL; } /* Parse right side of equation as an expression */ if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) { //if (PARSE_DEBUG) printf("parse_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count); return NULL; } //if (PARSE_DEBUG) printf("parse_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count); /* Create a new per frame equation */ if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) { //if (PARSE_DEBUG) printf("parse_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n"); free_gen_expr(gen_expr); return NULL; } //if (PARSE_DEBUG) printf("parse_per_frame_eqn: per_frame eqn parsed succesfully\n"); return per_frame_eqn;}/* Parses an 'implicit' per frame equation. That is, interprets a stream of data as a per frame equation without a prefix */per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset) { param_t * param; per_frame_eqn_t * per_frame_eqn; gen_expr_t * gen_expr; if (fs == NULL) return NULL; if (param_string == NULL) return NULL; if (preset == NULL) return NULL; //rintf("param string: %s\n", param_string); /* Find the parameter associated with the string, create one if necessary */ if ((param = find_param(param_string, preset, P_CREATE)) == NULL) { return NULL; } //printf("parse_implicit_per_frame_eqn: param is %s\n", param->name); /* Make sure parameter is writable */ if (param->flags & P_FLAG_READONLY) { //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count); return NULL; } /* Parse right side of equation as an expression */ if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) { //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count); return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -