Unary minus in the greenhouse parser

here is my parser using the bypass algorithm it works well as expected, except in one situation when I use the unary minus, as in -2 * 3, it does not work (I think it should not be, because I do not found nothing in the algorithm to handle this) is there an easy way I can fix this? (this is a simple parser that I need () + - * / ^) Regards Pedram

#include <cctype> #include <iostream> #include <cstring> #include <cstdlib> #include <cmath> using namespace std; int olaviat (char c) { /************* **Operator precedence *************/ switch(c) { case '-' : case '+' : return 1 ; case '*' : case '/' : return 2 ; case '^' : return 3 ; default : return 0 ; } } double eval(char *exp) { /************* **Convert to reverse polish *************/ char n [50] , o[50] ; static int nl = 0 , ol = 0 ; while (*exp) { while(isspace(*exp)) *exp++ ; if(*exp == '(') { o[ol++] = *exp++ ; } else if (*exp == ')'){ while(o[--ol]!='('){ n[nl++] = o[ol]; n[nl++] = ' '; } *exp++; } else if (isdigit(*exp)) { while (isdigit(*exp)) { n[nl++] = *exp++ ; } n[nl++] = ' ' ; } else if (strchr("+-*/^",*exp)){ if(olaviat(*exp) > olaviat(o[ol-1])) { o[ol++] = *exp++ ; } else { if(olaviat(*exp) == olaviat(o[ol-1]) && olaviat(*exp)== 3) { o[ol++] = *exp++ ; }else{ n[nl++] = o[ol-1] ; n[nl++] = ' ' ; o[--ol] = '\0' ; } } } } for (int k = ol-1 ; k >= 0 ; k --){ n[nl++] = o[k]; n[nl++] = ' ' ; } /*******************************/ cout << "Reverse Polish" << endl ; for (int i = 0 ; i < nl-1 ; i++){ cout << n[i] ; } cout << endl ; //n[nl+1] = '\0' ; /******************************* **Calculate Result *******************************/ double temp[50]; char *e ; ol = 0; int nol = 0 ; e=n ; int digitcount = 0; while (*e) { while (isspace(*e)) *e++; if (isdigit(*e)) { while (isdigit(*e)) { o[ol++] =*e++ ; digitcount++ ; } temp[nol++] = atof(o) ; for (int i = 0 ; i < digitcount ; i++) o[i]='\0' ; ol=0; digitcount = 0 ; } else if (strchr("+-*/^",*e)){ // char opr ; double tempAns = 0; switch (*e) { case '+' : tempAns = temp[nol-2] + temp [nol-1] ; break ; case '-' : tempAns = temp [nol-2] - temp [nol-1] ; break; case '*' : tempAns = temp [nol-2] * temp [nol-1] ; break; case '/' : tempAns = temp[nol-2] / temp[nol-1]; break ; case '^' : tempAns = pow(temp[nol-2],temp [nol-1]); break ; default : cout << "\n Unknown error" ; continue; } *e++ ; nol--; temp[nol-1] = tempAns ; temp[nol] = NULL ; } else { break ; } } double ans = temp[0]; return ans ; } int main() { char exp[100]; char c; start : cin.get (exp , 99); cout << "\n\tANS= " << eval(exp) ; cout << endl ; system("PAUSE"); return 0; } 
+7
source share
2 answers

The above option is correct, but it will be very cumbersome and buggy. Consider the case 2*-(1+2)^-(2+5*-(2+4)) . As you can see, you need to consider many things. Also, when you find "* - (" for example, you know that you replace it with * (0 - (....), which will be encoded in a cumbersome recursive function. The best solution is much simpler. Consider cases where the operator " - ", and it is preceded by another operator or preceded by a left bracket or when it is the first character of input (these cases mean that it is a unary minus, not binary). In this case, you change it to another character, say" u "( this was my case) and make its priority the same as "^".

In addition, processing it as part of a literal number has its catch. Imagine a case like -2 ^ 4. In Wolfram Alpha, you get -16, not 16.

And consider using stacks. They will make your life easier.

Let me explain what I meant. Note that you are provided with input:

2 / - 7 + (- 9 * 8) * 2 ^ - 9 - 5

Having made the replacement that I proposed, it will look like this:

2 / u 7 + (u 9 * 8) * 2 ^ u 9 - 5

Your operator priority switch should now be changed to:

 switch(c) { case '-' : case '+' : return 1 ; case '*' : case '/' : return 2 ; case '^' : case 'u': //note the 'u' operator we added return 3 ; default : return 0 ; } 

And, of course, you need to make changes in support of this unary operator.

+6
source

One option is to put 0 in front if the first character is '-'. You should do this when - after (.

More beggars either implement a unary minus operator, or consider it as part of the literal of a number.

+1
source

All Articles