CS 3723
 Programming Languages 
   Evaluate  Arithmetic  
Expressions (C version)  


Evaluate Arithmetic Expressions as doubles: The program below processes arithmetic expressions made up of single-digit operands. Everything is treated as a double. Using synthesis (that is, using returns from functions to pass information up the parse tree), values are propagated up the tree from the operands at leaves to the root, where the final value is printed.

The C code below is a modification of "our" standard parser. The changes are highlighted in red.

/* eval.c: evaluate arith expr as double
  P ---> E '$'
  E ---> T { ( '+' | '-' ) T }
  T ---> S { ( '*' | '/' ) S }
  S ---> F '^' S | F
  F ---> '(' E ')' | digit
 */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>  /* for pow */
char next;
double E(void);
double T(void);
double S(void);
double F(void);
void error(void);
void scan(void);
double evaluate(double arg1, char op,
         double arg2);

int main() {
   double res;
   scan();
   res = E();
   if (next != '$') error();
   else 
      printf("Result is: %.16f\n", res);
}

double E(void) {
   char save;
   double res, arg1, arg2;
   res = T();
   while (next == '+' || next == '-') {
      save = next;
      arg1 = res;
      scan();
      arg2 = T();
      res = evaluate(arg1, save, arg2);
   }
   return res;
}

double T(void) {
   char save;
   double res, arg1, arg2;
   res = S();
   while (next == '*' || next == '/') {
      save = next;
      arg1 = res;
      scan();
      arg2 = S();
      res = evaluate(arg1, save, arg2);
   }
   return res;
}
double S(void) {
   char save;
   double res, arg1, arg2;
   res = F();
   if (next == '^') {
      save = next;
      arg1 = res;
      scan();
      arg2 = S();
      res = evaluate(arg1, save, arg2);
   }
   return res;
}

double F(void) {
   char save;
   double res;
   if (isdigit(next)) {
      save = next;
      scan();
      return (double)(save - '0');
   }
   else if (next == '(') {
      scan();
      res = E();
      if (next == ')') scan();
      else error();
      return res;
   }
   else {
      error();
      return 0;
   }
}

void scan(void) {
   while (isspace(next = getchar()))
      ;
}

void error(void)
{
   printf("\n*** ERROR ***\n");
   exit(1);
}

double evaluate(double arg1, char op,
      double arg2) {
   switch (op) {
   case '+': return arg1 + arg2;
   case '-': return arg1 - arg2;
   case '*': return arg1 * arg2;
   case '/': return arg1 / arg2;
   case '^': return pow(arg1, arg2);
   default: error(); return 0;
   }
}

% cc -o eval -lm eval.c

% eval
2+3*4$
Result is: 14.00000

3*4+5$
Result is: 17.00000

(2+3)*4$
Result is: 20.00000

(3*(2+4)/(5+1))-2$
Result is: 1.00000

(5+3)^(2+1)^2$
Result is: 134217728.00000

2+3*4^5*6+7$
Result is: 18441.00000

2 + (3*(4^5)*6) + 7$
Result is: 18441.00000

((3^2-4*1*2)^(1/2)-3)/(2*1)$
Result is: -1.00000

((2-3)^((4+1)*5)/6-(2-4)*7)-8$
Result is: 5.83333

3^4^2$
Result is: 43046721.00000

3^(4^2)$ 
Result is: 43046721.00000

(3^4)^2$
Result is: 6561.00000

9 - 5 - 3 $
Result is: 1.00000

8/3/5$
Result is: 0.53333

8/(3/5)$
Result is: 13.33333
1+1/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1
/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1
/(2+1/(2+1/(2+1/(2+1/(2+1/(2  
  ))))))))))))))))))))$
Result is: 1.4142135623730949
(sqrt(2) = 1.414213562373095048801688724209...)

2+1/(1+1/(2+1/(1+1/(1+1/(4+1/(1+1/(1+1
/(6+1/(1+1/(1+1/(8+1/(1+1/(1+1/(2*5+1
/(1+1/(1+1/(2*6+1/(1+1/(1+1/(2*7+1 
))))))))))))))))))))$
Result is: 2.7182818284590455
(Note:e =  2.718281828459045235260287471352...)

3+1/(7+1/(5*3+1/(1+1/((4*(9*8+1))  ))))$
Result is: 3.1415926530119025

3+1/(7+1/(5*3+1/(1+1/((4*(9*8+1))+1/(1+1
/(1+1/(1+1/(2+1/(1+1/(3+1/(1+1/(2*7+1/(2+1)
))))))))))))$
Result is: 3.1415926535897931
(Note:pi = 3.141592653589793238462643383279...)


1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1
/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1
/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1
/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1
/(1+1/(1+1/(1+1/(1+1
)))))))))))))))))))))))))))))))))))$
Result: 1.6180339887498940
(Note:  1.618033988749894848204586834365 ...
   = (0.5)*(1 + sqrt(5))) = Golden Ratio
        
4/(1+1/( 3     +( 2   * 2)/
       ( 5     +( 3   * 3)/
       ( 7     +( 4   * 4)/
       ( 9     +( 5   * 5)/
       ((9+2)  +( 6   * 6)/
       ((9+4)  +( 7   * 7)/
       ((9+6)  +( 8   * 8)/
       ((9+8)  +( 9   * 9)  ))))  )))))$
Result is:    3.1415897324224455

4/(1+1/( 3     +( 2   * 2)/
       ( 5     +( 3   * 3)/
       ( 7     +( 4   * 4)/
       ( 9     +( 5   * 5)/
       ((9+2)  +( 6   * 6)/
       ((9+4)  +( 7   * 7)/
       ((9+6)  +( 8   * 8)/
       ((9+8)  +( 9   * 9)/
       ((6*3+1)+((9+1)*(9+1))/
       ((6*3+3)+((9+2)*(9+2))/
       ((6*3+5)+((9+3)*(9+3))/
       ((6*3+7)+((9+4)*(9+4))/
       ((6*3+9)+((9+5)*(9+5))/
       ((9*3+2)+((9+6)*(9+6))/
       ((9*3+4)+((9+7)*(9+7))/
       ((9*3+6)+((9+8)*(9+8))/
       ((9*3+8)+((9+9)*(9+9))/
       ((7*5+2)+((6*3+1)*(6*3+1))/
       ((7*5+4)+((6*3+2)*(6*3+2))/
       ((7*5+6)+((6*3+3)*(6*3+3))/
       ((7*5+8)+((6*3+4)*(6*3+4)))) 
         ))))) ))))) ))))) )))))$
Result is: 3.1415926535897936
(Note:pi = 3.141592653589793238462643383279...)


Revision date: 2014-01-01. (Please use ISO 8601, the International Standard.)