/* Copyright 2015-2022 Ian Jauslin Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "symbolic_parser.h" #include #include #include "tree.h" #include "definitions.cpp" #include "array.h" #include "istring.h" #include "fields.h" #include "polynomial.h" #define SP_NULL_MODE 0 #define SP_FUNCTION_MODE 1 // parse a symbolic expression from a char_array int parse_symbolic_expression(Char_Array str, Fields_Table fields, Variables variables, Polynomial* polynomial){ Tree symbol_tree; char_array_to_symbol_tree(str, &symbol_tree); resolve_symbol_tree(symbol_tree, fields, variables, polynomial); free_Tree(symbol_tree); return(0); } // from char* int parse_symbolic_expression_str(char* str, Fields_Table fields, Variables variables, Polynomial* polynomial){ Char_Array char_array; str_to_char_array(str,&char_array); parse_symbolic_expression(char_array, fields, variables, polynomial); free_Char_Array(char_array); return(0); } // compute the symbol tree from a string int char_array_to_symbol_tree(Char_Array str, Tree* symbol_tree){ // buffer char* buffer=calloc(str.length+1,sizeof(char)); char* buffer_ptr=buffer; Tree child; int match; Char_Array nodestr; Char_Array label; Char_Array str_clean; int mode; int comment=0; int j; int gotanode=0; // allocate memory init_Tree(symbol_tree,SYMBOL_TREE_SIZE, SYMBOL_TREE_LABEL_SIZE); // remove comments, ' ' and '\n' init_Char_Array(&str_clean,str.length); for(j=0;j>), got %s\n",char_array_to_str_noinit(&str)); exit(-1); } else{ // set label str_to_char_array(buffer,&label); tree_set_label(label,symbol_tree); free_Char_Array(label); } } break; // function case '%': if(j>0){ fprintf(stderr,"syntax error: functions must occupy an entire node (e.g. <%%exp<...>>), got %s\n",char_array_to_str_noinit(&str)); exit(-1); } mode=SP_FUNCTION_MODE; break; // product case '*': if(gotanode==0){ fprintf(stderr,"syntax error: '*' is not preceded by a node in %s\n",char_array_to_str_noinit(&str)); exit(-1); } if(j>=str_clean.length-1){ fprintf(stderr,"syntax error: '*' cannot be at the end of an expression, got %s\n",char_array_to_str_noinit(&str)); exit(-1); } // set label init_Char_Array(&label,1); char_array_append('*',&label); tree_set_label(label,symbol_tree); free_Char_Array(label); // next child char_array_substring(str_clean,j+1,str_clean.length-1,&nodestr); // parse subexpression char_array_to_symbol_tree(nodestr, &child); free_Char_Array(nodestr); // append next child tree_append_child_noinit(child, symbol_tree); // make it stop j=str_clean.length-1; break; // sum case '+': if(gotanode==0){ fprintf(stderr,"syntax error: '+' is not preceded by a node in %s\n",char_array_to_str_noinit(&str)); exit(-1); } if(j>=str_clean.length-1){ fprintf(stderr,"syntax error: '+' cannot be at the end of an expression, got %s\n",char_array_to_str_noinit(&str)); exit(-1); } // set label init_Char_Array(&label,1); char_array_append('+',&label); tree_set_label(label,symbol_tree); free_Char_Array(label); // next child char_array_substring(str_clean,j+1,str_clean.length-1,&nodestr); // parse subexpression char_array_to_symbol_tree(nodestr, &child); free_Char_Array(nodestr); // append next child tree_append_child_noinit(child, symbol_tree); // make it stop j=str_clean.length-1; break; default: if(mode!=SP_NULL_MODE){ // write to buffer buffer_ptr=str_addchar(buffer_ptr,str_clean.str[j]); } break; } } free_Char_Array(str_clean); free(buffer); return(0); } // from char* int str_to_symbol_tree(char* str, Tree* symbol_tree){ Char_Array char_array; str_to_char_array(str,&char_array); char_array_to_symbol_tree(char_array,symbol_tree); free_Char_Array(char_array); return(0); } // find matching '<' and '>' int matching_bracket(Char_Array str, int start){ int bracket_count=0; int i; for(i=start;i'){ bracket_count--; if(bracket_count==0){ return(i); } } } // if the function has not returned, then no matching bracket return(-1); } // resolve a symbol tree to its corresponding polynomial int resolve_symbol_tree(Tree symbol_tree, Fields_Table fields, Variables variables, Polynomial* output){ Polynomial poly; Tree variable_tree; // trivial tree if(symbol_tree.length==0){ // variable if(symbol_tree.root_label.length>0 && symbol_tree.root_label.str[0]=='$'){ variables_find_var(symbol_tree.root_label, variables, &variable_tree); resolve_symbol_tree(variable_tree, fields, variables, output); free_Tree(variable_tree); } //polynomial else{ Char_Array_to_Polynomial(symbol_tree.root_label, output); } } // exp else if (char_array_cmp_str(symbol_tree.root_label,"exp")==1){ if(symbol_tree.length!=1){ fprintf(stderr,"syntax error: exp must have 1 argument\n"); exit(-1); } resolve_symbol_tree(symbol_tree.children[0], fields, variables, &poly); polynomial_exponential(poly, output, fields); free_Polynomial(poly); } // log else if (char_array_cmp_str(symbol_tree.root_label,"log_1")==1){ if(symbol_tree.length!=1){ fprintf(stderr,"syntax error: log_1 must have 1 argument\n"); exit(-1); } resolve_symbol_tree(symbol_tree.children[0], fields, variables, &poly); polynomial_logarithm(poly, output, fields); free_Polynomial(poly); } // product else if (char_array_cmp_str(symbol_tree.root_label,"*")==1){ if(symbol_tree.length!=2){ fprintf(stderr,"syntax error: '*' must have 2 arguments\n"); exit(-1); } resolve_symbol_tree(symbol_tree.children[0], fields, variables, output); resolve_symbol_tree(symbol_tree.children[1], fields, variables, &poly); polynomial_prod_chain(poly, output, fields); free_Polynomial(poly); } // sum else if (char_array_cmp_str(symbol_tree.root_label,"+")==1){ if(symbol_tree.length!=2){ fprintf(stderr,"syntax error: '+' must have 2 arguments\n"); exit(-1); } resolve_symbol_tree(symbol_tree.children[0], fields, variables, output); resolve_symbol_tree(symbol_tree.children[1], fields, variables, &poly); polynomial_add_chain_noinit(poly, output, fields); } else{ fprintf(stderr,"syntax error: unrecognized operation '%s'\n",char_array_to_str_noinit(&(symbol_tree.root_label))); exit(-1); } return(0); }