// // parser.cpp // // The purpose of this program is to convert an equation or expression in standard //algebraic form into Reversed Polish Notation RPN. Once in RPN, the expression is //evaluated and can be reevaluated many times. // // The software may freely be used. If you find any bugs, or have suggestions then email //me at: sdattalo@interstice.com // // More information about the program may be found on my web page: // // http://www.dattalo.com // // TSD 09JUL95 REV1 is Finally working // TSD 06APR96 Added some comments and documentation // Known problems // 1) There is no index out of range checks for any of the arrays. Probably should // encapsulate the indexing within a class. // 2) There is no protection against math errors like division by zero. // I added a 'signal()' routine to catch Floating Point Errors, but nothing but exiting // the program is done. // 3) The exponentiation operator '^' has the same priority as '*' and '/'. May not // be a problem. // 4) Undefined varaibles are not flagged as such. Consequently, when the parser first // encounters a variable that has not been defined, it defines the variable and // initializes it to zero. Definitely a 'C' no-no. //#include <assoc.h> //#include <dict.h> #include <iostream.h> #include <string.h> #include<ctype.h> #include<stdlib.h> #include<stdio.h> #include<math.h> #include<signal.h> #include "parser.h" #define LF 0x0a // Various trial cases. Note that some of these will cause floating point exceptions. //This is no bug with the program; it's simply because some of the variables have not //been defined. static char fpin[] = "1+sin(-cos(1-(-2)))-3"; //char *fpin = "ln(2*x*cos(w * t + phi) / ( 7.2e-3 - 3*sqrt(4 * a *(c + 9.1e+7)) ) )"; //char *fpin = "cosh(2*x*cos(w * t + phi) + 5 / (1 + sqrt(4.9)))"; //char *fpin = "((-2/7)+(5)*1)"; //char *fpin = "cos(1)+(2*3)-(4)"; //char *fpin = "6-(1-2)/3*4+5"; //char *fpin = "log10(PI^2)"; int lines = 0, _index = 0; char var[30],ch; /*------------------------------------------------------------*/ //db_error // // This function is a make-shift error printer. Given an error number, it will //initialize the global variable *str to point to some constant string that describes //the error. // void db_error(int err_no) { char *str; switch(err_no) { case 1: str = "Missing '{' after key word"; break; case 2: str = "Illegal keyword"; break; case 3: str = "Missing '}'"; break; case 4: str = "Parenthesis mismatch"; break; case 5: str = "Operator syntax"; break; case 6: str = "Misplaced ')'"; break; default: str = "Unknown"; } printf("\nERROR: %d Line # %d\n%s\n", err_no, lines, str); /*fclose(fpin);*/ exit(1); } /*-----------------------------------------------*/ //my_getc // // This routine returns the next non-white space character in the input stream. //Note that the global variable "index" keeps track of where we are in the stream. //2nd Note, The stream for now is a string. // int my_getc(char *fpin) { char ch; while ( isspace(ch =fpin[_index])) /* Remove any spaces */ _index++; if (ch) _index++; /* If not the end of line, advance index */ return(ch); } /*-----------------------------------------------*/ //my_ungetc // void my_ungetc(char c, char *fpin) { fpin[--_index] = c; } /*-----------------------------------------------*/ //comment // //Not used here. However, if you wish to parse a file with comments, then you can suit //this function to your needs. // int comment(char c) { if (c == '#') { while( (c = my_getc(fpin)) != '#' && c != 0) ; return c=='#'; } return(0); } /*-----------------------------------------------*/ //skipbl // //Skipbl is an abbreviation for skip blanks. This function is primarily used with //file inputs. void skipbl(void) { char ch; do if ((ch= my_getc(fpin))==LF) lines++; while(isspace(ch) || comment(ch)); my_ungetc(ch,fpin); } /*-----------------------------------------------*/ int is_letter( char c) { c &= 0x5f; /* convert lower case to upper case */ return( (c>='A') && (c<='Z') ); } /*-----------------------------------------------*/ // Note that braces and brackets are equivalent. Consequently, something like // (a+b] while looking stupid is o.k. int is_openparen( char c) { return( (c=='[') || (c=='(') ); } /*-----------------------------------------------*/ int is_closedparen( char c) { return( (c==']') || (c==')') ); } /*-----------------------------------------------*/ int is_number( char c) { return( ( (c>='0') && (c<='9') ) || (c=='.') ); } /*------------------------------------------------------------*/ //read_substring // // The purpose of this function is to read a string from fpin. A string //in this case is defined to be same as a legal C name, i.e. the first character //must be a letter, the remaining characters can be letters or numbers. // void read_substring(char *variable) { char ch; skipbl(); ch=my_getc(fpin); if(is_letter(ch)) // The First character must be a letter { *variable++=ch; do { ch = my_getc(fpin); *variable++ = ch; // The other characters can be alphanumeric } while(is_letter(ch)|| ( (ch>='0') && (ch<='9') ) ); } my_ungetc(ch,fpin); *--variable = 0; } /*------------------------------------------------------------*/ void add_variable(token *new_variable) { variable_list[number_of_variables++] = new_variable; } /*------------------------------------------------------------*/ // search_var_and_func // // This function will take the input string "function" and see if it exists in either //the function list or the variable list. If it is found in either one, then the pointer //to the list element is returned. Otherwise, a new variable is created and added to the //variable list. token * search_var_and_func(char *function) { int i; skipbl(); for(i=0; i<number_of_functions; ++i) { if(strcmp(function_list[i]->nameOf(), function) == 0) return(function_list[i]); } for(i=0; i<number_of_variables; ++i) if(strcmp(variable_list[i]->nameOf(), function) == 0) return(variable_list[i]); variable *t = new variable(function); add_variable(t ); return(t); } /*-----------------------------------------------*/ variable::variable(char * new_variable) { value = 0; length = strlen(new_variable); name_ptr = new char [length]; strcpy(name_ptr, new_variable); type = TT_operand; } /*-----------------------------------------------*/ FOP::FOP(char* string) { char *end_ptr; end_ptr = NULL; if(*string) { t = strtod(&string[_index], &end_ptr); _index += (strlen (&string[_index]) - strlen(end_ptr)); } else t=0.0; type = TT_operand; } /*-----------------------------------------------*/ class BOPL_plus : public BOPL { public: virtual void execute(void) { numeric_push(numeric_pop() + numeric_pop());} virtual char get_ASCII(void) const { return '+';} }; class BOPL_minus : public BOPL { public: virtual void execute(void) { numeric_push(-numeric_pop() + numeric_pop());} virtual char get_ASCII(void) const { return '-';} }; /*-----------------------------------------------*/ class BOPH_times : public BOPH { public: virtual void execute(void) { numeric_push(numeric_pop() * numeric_pop());} virtual char get_ASCII(void) const { return '*';} }; class BOPH_divide : public BOPH { public: virtual void execute(void) { double t=numeric_pop(); numeric_push(numeric_pop() /t );} virtual char get_ASCII(void) const { return '/';} }; class BOPH_exponentiate : public BOPH { public: virtual void execute(void) { double t=numeric_pop(); numeric_push(pow(numeric_pop(),t) );} virtual char get_ASCII(void) const { return '^';} }; /*-----------------------------------------------*/ class UOP_minus : public UOP { public: virtual void execute(void) { numeric_push(-numeric_pop());} virtual char get_ASCII(void) const { return '-';} }; /*-----------------------------------------------*/ // // Trig Functions // class function_cos : public function { public: virtual void execute(void) { numeric_push(cos(numeric_pop()));} virtual Pchar nameOf(void) const { return "cos";} }; class function_sin : public function { public: virtual void execute(void) { numeric_push(sin(numeric_pop()));} virtual Pchar nameOf(void) const { return "sin";} }; class function_tan : public function { public: virtual void execute(void) { numeric_push(tan(numeric_pop()));} virtual Pchar nameOf(void) const { return "tan";} }; class function_sec : public function { public: virtual void execute(void) { numeric_push(1/cos(numeric_pop()));} virtual Pchar nameOf(void) const { return "sec";} }; class function_csc : public function { public: virtual void execute(void) { numeric_push(1/sin(numeric_pop()));} virtual Pchar nameOf(void) const { return "csc";} }; class function_cot : public function { public: virtual void execute(void) { numeric_push(1/tan(numeric_pop()));} virtual Pchar nameOf(void) const { return "cot";} }; /*-----------------------------------------------*/ // // Inverse Trig Functions // class function_acos : public function { public: virtual void execute(void) { numeric_push(acos(numeric_pop()));} virtual Pchar nameOf(void) const { return "acos";} }; class function_asin : public function { public: virtual void execute(void) { numeric_push(asin(numeric_pop()));} virtual Pchar nameOf(void) const { return "asin";} }; class function_atan : public function { public: virtual void execute(void) { numeric_push(atan(numeric_pop()));} virtual Pchar nameOf(void) const { return "atan";} }; class function_asec : public function { public: virtual void execute(void) { numeric_push(acos(1/numeric_pop()));} virtual Pchar nameOf(void) const { return "asec";} }; class function_acsc : public function { public: virtual void execute(void) { numeric_push(asin(1/numeric_pop()));} virtual Pchar nameOf(void) const { return "acsc";} }; class function_acot : public function { public: virtual void execute(void) { numeric_push(3.141592653/2-atan(numeric_pop()));} virtual Pchar nameOf(void) const { return "acot";} }; /*-----------------------------------------------*/ class function_cosh : public function { public: virtual void execute(void) { numeric_push(cosh(numeric_pop()));} virtual Pchar nameOf(void) const { return "cosh";} }; class function_sinh : public function { public: virtual void execute(void) { numeric_push(sinh(numeric_pop()));} virtual Pchar nameOf(void) const { return "sinh";} }; class function_tanh : public function { public: virtual void execute(void) { numeric_push(tanh(numeric_pop()));} virtual Pchar nameOf(void) const { return "tanh";} }; class function_sech : public function { public: virtual void execute(void) { numeric_push(1/cosh(numeric_pop()));} virtual Pchar nameOf(void) const { return "sech";} }; class function_csch : public function { public: virtual void execute(void) { numeric_push(1/sinh(numeric_pop()));} virtual Pchar nameOf(void) const { return "csch";} }; class function_coth : public function { public: virtual void execute(void) { numeric_push(1/tanh(numeric_pop()));} virtual Pchar nameOf(void) const { return "coth";} }; class function_ln : public function { public: virtual void execute(void) { numeric_push(log(numeric_pop()));} virtual Pchar nameOf(void) const { return "ln";} }; class function_log : public function // Identical to "ln" { public: virtual void execute(void) { numeric_push(log(numeric_pop()));} virtual Pchar nameOf(void) const { return "log";} }; class function_log10 : public function { public: virtual void execute(void) { numeric_push(log10(numeric_pop()));} virtual Pchar nameOf(void) const { return "log10";} }; class function_exp : public function { public: virtual void execute(void) { numeric_push(exp(numeric_pop()));} virtual Pchar nameOf(void) const { return "exp";} }; class function_sqrt : public function { public: virtual void execute(void) { numeric_push(sqrt(numeric_pop()));} virtual Pchar nameOf(void) const { return "sqrt";} }; /*-----------------------------------------------*/ void tokenize(void) { int have_left_operand=0; int temp; do { ch = my_getc(fpin); switch(ch) { case '+': if(have_left_operand) the_array[token_index++] = new BOPL_plus(); break; case '-': if(have_left_operand) the_array[token_index++] = new BOPL_minus(); else the_array[token_index++] = new UOP_minus(); break; case '(': level++; have_left_operand=0; the_array[token_index++] = new open_parenthesis('('); break; case ')': level--; have_left_operand=1; the_array[token_index++] = new closed_parenthesis(ch); break; case '*': the_array[token_index++] = new BOPH_times(); break; case '/': the_array[token_index++] = new BOPH_divide(); break; case '^': the_array[token_index++] = new BOPH_exponentiate(); break; case '%': case '&': // the_array[token_index++] = new BOPH(ch); break; default: if(is_letter(ch)) { have_left_operand =1; my_ungetc(ch, fpin); read_substring(var); the_array[token_index++] = search_var_and_func(var); } if( is_number(ch)) { have_left_operand =1; my_ungetc(ch, fpin); the_array[token_index++] = new FOP(fpin); } } } while(ch); null_token *f = new null_token; the_array[token_index++] = f; } /*-----------------------------------------------*/ void push(int _index) { the_stack[stack_index++] = the_array[_index]; } /*-----------------------------------------------*/ PS_state parse(PS_state state) { do { state = the_array[t1++]->a_search(state); // state=search(state); } while( (state!=PS_search_end)&&(state!=PS_search_closed)); return(state); } void init_function_list(void) { number_of_functions = 0; function_list[number_of_functions++]= new function_cos(); function_list[number_of_functions++]= new function_sin(); function_list[number_of_functions++]= new function_tan(); function_list[number_of_functions++]= new function_sec(); function_list[number_of_functions++]= new function_csc(); function_list[number_of_functions++]= new function_cot(); function_list[number_of_functions++]= new function_acos(); function_list[number_of_functions++]= new function_asin(); function_list[number_of_functions++]= new function_atan(); function_list[number_of_functions++]= new function_asec(); function_list[number_of_functions++]= new function_acsc(); function_list[number_of_functions++]= new function_acot(); function_list[number_of_functions++]= new function_cosh(); function_list[number_of_functions++]= new function_sinh(); function_list[number_of_functions++]= new function_tanh(); function_list[number_of_functions++]= new function_sech(); function_list[number_of_functions++]= new function_csch(); function_list[number_of_functions++]= new function_coth(); function_list[number_of_functions++]= new function_exp(); function_list[number_of_functions++]= new function_ln(); function_list[number_of_functions++]= new function_log(); function_list[number_of_functions++]= new function_log10(); function_list[number_of_functions++]= new function_sqrt(); } /*-----------------------------------------------*/ void init_variable_list(void) { number_of_variables = 0; variable *v = new variable("ONE"); v->value = 1; variable_list[number_of_variables++] = v; v = new variable("ZERO"); v->value = 0; variable_list[number_of_variables++] = v; v = new variable("PI"); v->value = 3.141592653; variable_list[number_of_variables++] = v; } typedef void (*fptr)(int); void Catcher(int *reglist) { cout << "Floating Point Error"; exit(1); } /*-----------------------------------------------*/ void main(void) { int i; signal(SIGFPE, (fptr)Catcher ); //Define catcher for floating point errors. init_function_list(); //Initialize the user defineable function list init_variable_list(); // " " " variable list printf("\n%s\n", fpin); // tokenize(); if(level) db_error(4); for( i=0; i<token_index; i++) the_array[i]->printOn(); cout << "\nParsed Results\n"; t1=0; parse(PS_null); cout << '\n'; for(i=0; i<stack_index; i++) { the_stack[i]->printOn(); cout << ' '; } if(level) db_error(4); for(i=0; i<stack_index; i++) { the_stack[i]->execute(); } cout << '\n' << numeric_stack[0] << '\n'; }
file: /Techref/language/ccpp/parser_cpp.htm, 100KB, , updated: 2013/7/22 16:33, local time: 2024/12/21 08:33,
3.16.69.239:LOG IN
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://techref.massmind.org/techref/language/ccpp/parser_cpp.htm"> parser.cpp</A> |
Did you find what you needed? |
Welcome to massmind.org! |
Welcome to techref.massmind.org! |
.