#include "exprparser.h" #include "arithexpr.h" #include "relexpr.h" #include "logexpr.h" #include #include void check_token(const char* token, const char* should_be, int l) { if (token == (char*)0) { throw expression_error(l,"unexpected end of file"); } if (strcmp(token,should_be) != 0) { throw expression_error(l,"syntax error"); } } expression_error::expression_error(int l, char* s):line_number(l) { strcpy(error,s); } expression_parser::expression_parser(lexer* lex):L(lex) { } expression* expression_parser::read_one(istream& is,list& B) { const char* token = L->get_token(is); expression *ex = (expression*)0; if (strcmp(token,"(")==0) { // sub expression expression *e = read(is,B); // call resursivelly check_token(L->next_token(is),")",L->get_line_number()); ex = new sub_expression(e); } else if (strcmp(token,"-")==0) { // - expression; unary - expression *e = read_one(is,B); ex = new unary_minus(e); } else if (strcmp(token,"+")==0) { // + expression; unary + expression *e = read_one(is,B); ex = new unary_plus(e); } else if (strcmp(token,"!")==0) { // ! expression; unary ! expression *e = read_one(is,B); ex = new negation(e); } else if (strcmp(token,"sin")==0) { // sin(x) check_token(L->next_token(is),"(",L->get_line_number()); expression *arg = read(is,B); check_token(L->next_token(is),")",L->get_line_number()); ex = new sin_function(arg); } else if (strcmp(token,"cos")==0) { // cos(x) check_token(L->next_token(is),"(",L->get_line_number()); expression *arg = read(is,B); check_token(L->next_token(is),")",L->get_line_number()); ex = new cos_function(arg); } else if (strcmp(token,"tan")==0) { // tan(x) check_token(L->next_token(is),"(",L->get_line_number()); expression *arg = read(is,B); check_token(L->next_token(is),")",L->get_line_number()); ex = new tan_function(arg); } else if (token[0] >= '0' && token[0] <= '9') { // constant ex = new constant(atof(token)); } else { // SEE IF IT IS ANY OF THE VARIABLES list_iterator I = B.first(); int i=0; bool found = false; while(I.has_more_elements() && !found) { if (strcmp(*I,token) == 0) { ex = new variable(i); found = true; break; } I++; i++; } if (!found) { throw expression_error(L->get_line_number(),"unknown identifier"); } } return ex; } expression* expression_parser::read(istream& is, list& B) { expression * ex = read_one(is,B); // up to potential binary symbol const char* token; if ((token = L->next_token(is)) == (char*)0) return ex; // end of file // check for binary operators // the trick is to allocate them with the wrapper // "binary_operator_adaptor" if (strcmp(token,"+")==0) { // binary + return new binary_operator_adaptor(new binary_plus(ex,read(is,B))); } else if (strcmp(token,"-")==0) { // binary - return new binary_operator_adaptor(new binary_minus(ex,read(is,B))); } else if (strcmp(token,"/")==0) { // / return new binary_operator_adaptor(new division(ex,read(is,B))); } else if (strcmp(token,"*")==0) { // * return new binary_operator_adaptor(new multiplication(ex,read(is,B))); } else if (strcmp(token,"==")==0) { // == return new binary_operator_adaptor(new equal_expression(ex,read(is,B))); } else if (strcmp(token,"!=")==0) { // != return new binary_operator_adaptor( new not_equal_expression(ex,read(is,B))); } else if (strcmp(token,"<")==0) { // < return new binary_operator_adaptor(new less_expression(ex,read(is,B))); } else if (strcmp(token,"<=")==0) { // <= return new binary_operator_adaptor( new less_or_equal_expression(ex,read(is,B))); } else if (strcmp(token,">")==0) { // > return new binary_operator_adaptor( new greater_expression(ex,read(is,B))); } else if (strcmp(token,">=")==0) { // >= return new binary_operator_adaptor( new greater_or_equal_expression(ex,read(is,B))); } else if (strcmp(token,"&&")==0) { // && return new binary_operator_adaptor(new and_expression(ex,read(is,B))); } else if (strcmp(token,"||")==0) { // || return new binary_operator_adaptor(new or_expression(ex,read(is,B))); } else { L->putback(); // OTHERWISE IT IS NOT A BINARY EXPRESSION! } return ex; }