Solved

Evaluating expressions

Posted on 2001-07-19
8
406 Views
Last Modified: 2012-06-21
Hi,
I've just started develop some code coverage software
implementing branch and function coverage.

As of now all the conditional expressions I've replaced
some macro which evaluates the expression and replaces
it. Is it the right way or any other alternate for evaluating
expressions at run time b'cos the current method is getting
complicated for elseif's do..whiles???

Any site which gives such info would also be useful!
0
Comment
Question by:premadhas
8 Comments
 
LVL 30

Expert Comment

by:Axter
Comment Utility
Can you post some of your code?

You should stay away from using macro's for your evaluations.

Use const variables when posible.
0
 
LVL 2

Accepted Solution

by:
curri earned 200 total points
Comment Utility
Also, do you need to develop your own ? there are several free/open source solutions you could use (GNU has one, that integrates with gcc). And tons of tools you can buy.

Orlando
0
 

Author Comment

by:premadhas
Comment Utility
#define if(expr) if(expr) printf("FileName: %s\nLineNo: %d\n",__FILE__,__LINE__);if(expr)

#define while(expr)          for(i=0;(expr)&&(i<1);printf("FileName: %s\nLineNo: %d\n",__FILE__,__LINE__),i++);while(expr)

These are the sample macros for if() & while expressions...

Curri can you gimme the link for gcc's open source if you have
0
 
LVL 2

Expert Comment

by:curri
Comment Utility
The name of the program is gcov. Here is a link to some info about it (I'm sure you can find better info, this is just the first one that came out in google :)

http://www.delorie.com/gnu/docs/gcc/gcc_102.html

Orlando
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 14

Expert Comment

by:AlexVirochovsky
Comment Utility
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
Comment Utility
next is code:
file ee.h
/* Some of you may choose to define TYPE as a "float" instead... */

#define TYPE            double          /* Type of numbers to work with */



#define VARLEN          15              /* Max length of variable names */

#define MAXVARS         50              /* Max user-defined variables */

#define TOKLEN          30              /* Max token length */



#define VAR             1

#define DEL             2

#define NUM             3



typedef struct

{

   char name[VARLEN + 1];               /* Variable name */

   TYPE value;                          /* Variable value */

} VARIABLE;



typedef struct

{

   char* name;                          /* Function name */

   int   args;                          /* Number of arguments to expect */

   TYPE  (*func)();                     /* Pointer to function */

} FUNCTION;



/* The following macros are ASCII dependant, no EBCDIC here! */

#define iswhite(c)  (c == ' ' || c == '\t')

#define isnumer(c)  ((c >= '0' && c <= '9') || c == '.')

#define isalpha(c)  ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') \

                    || c == '_')

#define isdelim(c)  (c == '+' || c == '-' || c == '*' || c == '/' || c == '%' \

                    || c == '^' || c == '(' || c == ')' || c == ',' || c == '=')



/* Codes returned from the evaluator */

#define E_OK           0        /* Successful evaluation */

#define E_SYNTAX       1        /* Syntax error */

#define E_UNBALAN      2        /* Unbalanced parenthesis */

#define E_DIVZERO      3        /* Attempted division by zero */

#define E_UNKNOWN      4        /* Reference to unknown variable */

#define E_MAXVARS      5        /* Maximum variables exceeded */

#define E_BADFUNC      6        /* Unrecognised function */

#define E_NUMARGS      7        /* Wrong number of arguments to funtion */

#define E_NOARG        8        /* Missing an argument to a funtion */

#define E_EMPTY        9        /* Empty expression */



file ee.c

/*************************************************************************

**                                                                       **

** EE.C         Expression Evaluator                                     **

**                                                                       **

** AUTHOR:      Mark Morley                                              **

** COPYRIGHT:   (c) 1992 by Mark Morley                                  **

** DATE:        December 1991                                            **

** HISTORY:     Jan 1992 - Made it squash all command line arguments     **

**                         into one big long string.                     **

**                       - It now can set/get VMS symbols as if they     **

**                         were variables.                               **

**                       - Changed max variable name length from 5 to 15 **

**              Jun 1992 - Updated comments and docs                     **

**                                                                       **

** You are free to incorporate this code into your own works, even if it **

** is a commercial application.  However, you may not charge anyone else **

** for the use of this code!  If you intend to distribute your code,     **

** I'd appreciate it if you left this message intact.  I'd like to       **

** receive credit wherever it is appropriate.  Thanks!                   **

**                                                                       **

** I don't promise that this code does what you think it does...         **

**                                                                       **

** Please mail any bug reports/fixes/enhancments to me at:               **

**      morley@camosun.bc.ca                                             **

** or                                                                    **

**      Mark Morley                                                      **

**      3889 Mildred Street                                              **

**      Victoria, BC  Canada                                             **

**      V8Z 7G1                                                          **

**      (604) 479-7861                                                   **

**                                                                       **

 *************************************************************************/



/* #define VAX */             /* Uncomment this line if you're using VMS */



#include <stdlib.h>

#include <math.h>

#include <setjmp.h>



#ifdef VAX

#include <ssdef.h>

#include <descrip.h>

#endif



#include "ee.h"



#define ERR(n) {ERROR=n; ERPOS=expression-ERANC-1; strcpy(ERTOK,token); longjmp(jb,1);}



/* These defines only happen if the values are not already defined!  You may

   want to add more precision here, if your machine supports it. */

#ifndef M_PI

#define M_PI    3.14159265358979323846

#endif

#ifndef M_E

#define M_E     2.71828182845904523536

#endif





/*************************************************************************

**                                                                       **

** PROTOTYPES FOR CUSTOM MATH FUNCTIONS                                  **

**                                                                       **

 *************************************************************************/



double deg( double x );

double rad( double x );





/*************************************************************************

**                                                                       **

** VARIABLE DECLARATIONS                                                 **

**                                                                       **

 *************************************************************************/



int   ERROR;                 /* The error number */

char  ERTOK[TOKLEN + 1];     /* The token that generated the error */

int   ERPOS;                 /* The offset from the start of the expression */

char* ERANC;                 /* Used to calculate ERPOS */



/*

   Add any "constants" here...  These are "read-only" values that are

   provided as a convienence to the user.  Their values can not be

   permanently changed.  The first field is the variable name, the second

   is its value.

*/

VARIABLE Consts[] =

{

   /* name, value */

   { "pi",      M_PI },

   { "e",       M_E },



   { 0 }

};



/*

   Add any math functions that you wish to recognise here...  The first

   field is the name of the function as it would appear in an expression.

   The second field tells how many arguments to expect.  The third is

   a pointer to the actual function to use.

*/

FUNCTION Funcs[] =

{

   /* name, funtion to call */

   { "sin",     1,    sin },

   { "cos",     1,    cos },

   { "tan",     1,    tan },

   { "asin",    1,    asin },

   { "acos",    1,    acos },

   { "atan",    1,    atan },

   { "sinh",    1,    sinh },

   { "cosh",    1,    cosh },

   { "tanh",    1,    tanh },

   { "exp",     1,    exp },

   { "log",     1,    log },

   { "log10",   1,    log10 },

   { "sqrt",    1,    sqrt },

   { "floor",   1,    floor },

   { "ceil",    1,    ceil },

   { "abs",     1,    fabs },

   { "hypot",   2,    hypot },



   { "deg",     1,    deg },

   { "rad",     1,    rad },



   { 0 }

};



VARIABLE        Vars[MAXVARS];       /* Array for user-defined variables */

unsigned char*  expression;          /* Pointer to the user's expression */

unsigned char   token[TOKLEN + 1];   /* Holds the current token */

int             type;                /* Type of the current token */

jmp_buf         jb;                  /* jmp_buf for errors */





/*************************************************************************

**                                                                       **

** Some custom math functions...   Note that they must be prototyped     **

** above (if your compiler requires it)                                  **

**                                                                       **

** deg( x )             Converts x radians to degrees.                   **

** rad( x )             Converts x degrees to radians.                   **

**                                                                       **

 *************************************************************************/



double

deg( double x )

{

   return( x * 180.0 / M_PI );

}



double

rad( double x )

{

   return( x * M_PI / 180.0 );

}





/*************************************************************************

**                                                                       **

** GetSymbol( char* s )                                                  **

**                                                                       **

** This routine obtains a value from the program's environment.          **

** This works for DOS and VMS (and other OS's???)

**                                                                       **

 ************************************************************************/



GetSymbol( char* s, TYPE* v )

{

   char* e;



   e = getenv( s );

   if( !e )

      return( 0 );

   *v = atof( e );

   return( 1 );

}





/*************************************************************************

**                                                                       **

** SetSymbol( char* s, char* v )                                         **

**                                                                       **

** This VMS specific routine sets (or updates) a VMS symbol to a given   **

** value                                                                 **

**                                                                       **

 *************************************************************************/



#ifdef VAX

SetSymbol( char* s, char* v )

{

   struct dsc$descriptor_s sym;

   struct dsc$descriptor_s val;

   long                    typ = 1;



   sym.dsc$w_length = strlen( s );

   sym.dsc$a_pointer = s;

   sym.dsc$b_class = DSC$K_CLASS_S;

   sym.dsc$b_dtype = DSC$K_DTYPE_T;

   val.dsc$w_length = strlen( v );

   val.dsc$a_pointer = v;

   val.dsc$b_class = DSC$K_CLASS_S;

   val.dsc$b_dtype = DSC$K_DTYPE_T;

   return( LIB$SET_SYMBOL( &sym, &val, &typ ) );

}

#endif





/*************************************************************************

**                                                                       **

** strlwr( char* s )   Internal use only                                 **

**                                                                       **

** This routine converts a string to lowercase.  I know many compilers   **

** offer their own routine, but my VMS compiler didn't so...             **

** Again, this one is ASCII specific!                                    **

**                                                                       **

 *************************************************************************/



static

strlwr( char* s )

{

   while( *s )

   {

      if( *s >= 'A' && *s <= 'Z' )

         *s += 32;

      s++;

   }

}





/*************************************************************************

**                                                                       **

** ClearAllVars()                                                        **

**                                                                       **

** Erases all user-defined variables from memory. Note that constants    **

** can not be erased or modified in any way by the user.                 **

**                                                                       **

** Returns nothing.                                                      **

**                                                                       **

 *************************************************************************/



ClearAllVars()

{

   int i;



   for( i = 0; i < MAXVARS; i++ )

   {

      *Vars[i].name = 0;

      Vars[i].value = 0;

   }

}





/*************************************************************************

**                                                                       **

** ClearVar( char* name )                                                **

**                                                                       **

** Erases the user-defined variable that is called NAME from memory.     **

** Note that constants are not affected.                                 **

**                                                                       **

** Returns 1 if the variable was found and erased, or 0 if it didn't     **

** exist.                                                                **

**                                                                       **

 *************************************************************************/



ClearVar( char* name )

{

   int i;



   for( i = 0; i < MAXVARS; i++ )

      if( *Vars[i].name && ! strcmp( name, Vars[i].name ) )

      {

         *Vars[i].name = 0;

         Vars[i].value = 0;

         return( 1 );

      }

   return( 0 );

}





/*************************************************************************

**                                                                       **

** GetValue( char* name, TYPE* value )                                   **

**                                                                       **

** Looks up the specified variable (or constant) known as NAME and       **

** returns its contents in VALUE.                                        **

**                                                                       **

** First the user-defined variables are searched, then the constants are **

** searched.                                                             **

**                                                                       **

** Returns 1 if the value was found, or 0 if it wasn't.                  **

**                                                                       **

 *************************************************************************/



GetValue( char* name, TYPE* value )

{

   int i;



   /* First check for an environment variable reference... */

   if( *name == '_' )

      return( GetSymbol( name + 1, value ) );



   /* Now check the user-defined variables. */

   for( i = 0; i < MAXVARS; i++ )

      if( *Vars[i].name && ! strcmp( name, Vars[i].name ) )

      {

         *value = Vars[i].value;

         return( 1 );

      }



   /* Now check the programmer-defined constants. */

   for( i = 0; *Consts[i].name; i++ )

      if( *Consts[i].name && ! strcmp( name, Consts[i].name ) )

      {

         *value = Consts[i].value;

         return( 1 );

      }

   return( 0 );

}





/*************************************************************************

**                                                                       **

** SetValue( char* name, TYPE* value )                                   **

**                                                                       **

** First, it erases any user-defined variable that is called NAME.  Then **

** it creates a new variable called NAME and gives it the value VALUE.   **

**                                                                       **

** Returns 1 if the value was added, or 0 if there was no more room.     **

**                                                                       **

 *************************************************************************/



SetValue( char* name, TYPE* value )

{

   char b[30];

   int  i;



#ifdef VAX

   if( *name == '_' )

   {

      sprintf( b, "%g", *value );

      if( SetSymbol( name + 1, b ) != SS$_NORMAL )

         return( 0 );

      return( 1 );

   }

#endif

   ClearVar( name );

   for( i = 0; i < MAXVARS; i++ )

      if( ! *Vars[i].name )

      {

         strcpy( Vars[i].name, name );

         Vars[i].name[VARLEN] = 0;

         Vars[i].value = *value;

         return( 1 );

      }

   return( 0 );

}





/*************************************************************************

**                                                                       **

** Parse()   Internal use only                                           **

**                                                                       **

** This function is used to grab the next token from the expression that **

** is being evaluated.                                                   **

**                                                                       **

 *************************************************************************/



static

Parse()

{

   char* t;



   type = 0;

   t = token;

   while( iswhite( *expression ) )

      expression++;

   if( isdelim( *expression ) )

   {

      type = DEL;

      *t++ = *expression++;

   }

   else if( isnumer( *expression ) )

   {

      type = NUM;

      while( isnumer( *expression ) )

         *t++ = *expression++;

   }

   else if( isalpha( *expression ) )

   {

      type = VAR;

      while( isalpha( *expression ) )

        *t++ = *expression++;

      token[VARLEN] = 0;

   }

   else if( *expression )

   {

      *t++ = *expression++;

      *t = 0;

      ERR( E_SYNTAX );

   }

   *t = 0;

   while( iswhite( *expression ) )

      expression++;

}





/*************************************************************************

**                                                                       **

** Level1( TYPE* r )   Internal use only                                 **

**                                                                       **

** This function handles any variable assignment operations.             **

** It returns a value of 1 if it is a top-level assignment operation,    **

** otherwise it returns 0                                                **

**                                                                       **

 *************************************************************************/



static

Level1( TYPE* r )

{

   char t[VARLEN + 1];



   if( type == VAR )

      if( *expression == '=' )

      {

         strcpy( t, token );

         Parse();

         Parse();

         if( !*token )

         {

            ClearVar( t );

            return(1);

         }

         Level2( r );

         if( ! SetValue( t, r ) )

            ERR( E_MAXVARS );

         return( 1 );

      }

   Level2( r );

   return( 0 );

}





/*************************************************************************

**                                                                       **

** Level2( TYPE* r )   Internal use only                                 **

**                                                                       **

** This function handles any addition and subtraction operations.        **

**                                                                       **

 *************************************************************************/



static

Level2( TYPE* r )

{

   TYPE t = 0;

   char o;



   Level3( r );

   while( (o = *token) == '+' || o == '-' )

   {

      Parse();

      Level3( &t );

      if( o == '+' )

         *r = *r + t;

      else if( o == '-' )

         *r = *r - t;

   }

}





/*************************************************************************

**                                                                       **

** Level3( TYPE* r )   Internal use only                                 **

**                                                                       **

** This function handles any multiplication, division, or modulo.        **

**                                                                       **

 *************************************************************************/



static

Level3( TYPE* r )

{

   TYPE t;

   char o;



   Level4( r );

   while( (o = *token) == '*' || o == '/' || o == '%' )

   {

      Parse();

      Level4( &t );

      if( o == '*' )

         *r = *r * t;

      else if( o == '/' )

      {

         if( t == 0 )

            ERR( E_DIVZERO );

         *r = *r / t;

      }

      else if( o == '%' )

      {

         if( t == 0 )

            ERR( E_DIVZERO );

         *r = fmod( *r, t );

      }

   }

}





/*************************************************************************

**                                                                       **

** Level4( TYPE* r )   Internal use only                                 **

**                                                                       **

** This function handles any "to the power of" operations.               **

**                                                                       **

 *************************************************************************/



static

Level4( TYPE* r )

{

   TYPE t;



   Level5( r );

   if( *token == '^' )

   {

      Parse();

      Level5( &t );

      *r = pow( *r, t );

   }

}





/*************************************************************************

**                                                                       **

** Level5( TYPE* r )   Internal use only                                 **

**                                                                       **

** This function handles any unary + or - signs.                         **

**                                                                       **

 *************************************************************************/



static

Level5( TYPE* r )

{

   char o = 0;



   if( *token == '+' || *token == '-' )

   {

      o = *token;

      Parse();

   }

   Level6( r );

   if( o == '-' )

      *r = -*r;

}





/*************************************************************************

**                                                                       **

** Level6( TYPE* r )   Internal use only                                 **

**                                                                       **

** This function handles any literal numbers, variables, or functions.   **

**                                                                       **

 *************************************************************************/



static

Level6( TYPE* r )

{

   int  i;

   int  n;

   TYPE a[3];



   if( *token == '(' )

   {

      Parse();

      if( *token == ')' )

         ERR( E_NOARG );

      Level1( r );

      if( *token != ')' )

         ERR( E_UNBALAN );

      Parse();

   }

   else

   {

      if( type == NUM )

      {

         *r = (TYPE) atof( token );

         Parse();

      }

      else if( type == VAR )

      {

         if( *expression == '(' )

         {

            for( i = 0; *Funcs[i].name; i++ )

               if( ! strcmp( token, Funcs[i].name ) )

               {

                  Parse();

                  n = 0;

                  do

                  {

                     Parse();

                     if( *token == ')' || *token == ',' )

                        ERR( E_NOARG );

                     a[n] = 0;

                     Level1( &a[n] );

                     n++;

                  } while( n < 4 && *token == ',' );

                  Parse();

                  if( n != Funcs[i].args )

                  {

                     strcpy( token, Funcs[i].name );

                     ERR( E_NUMARGS );

                  }

                  *r = Funcs[i].func( a[0], a[1], a[2] );

                  return;

               }

               if( ! *Funcs[i].name )

                  ERR( E_BADFUNC );

            }

            else if( ! GetValue( token, r ) )

               ERR( E_UNKNOWN );

         Parse();

      }

      else

         ERR( E_SYNTAX );

   }

}





/*************************************************************************

**                                                                       **

** Evaluate( char* e, TYPE* result, int* a )                             **

**                                                                       **

** This function is called to evaluate the expression E and return the   **

** answer in RESULT.  If the expression was a top-level assignment, a    **

** value of 1 will be returned in A, otherwise it will contain 0.        **

**                                                                       **

** Returns E_OK if the expression is valid, or an error code.            **

**                                                                       **

 *************************************************************************/



Evaluate( char* e, TYPE* result, int* a )

{

   if( setjmp( jb ) )

      return( ERROR );

   expression = e;

   ERANC = e;

   strlwr( expression );

   *result = 0;

   Parse();

   if( ! *token )

      ERR( E_EMPTY );

   *a = Level1( result );

   return( E_OK );

}





/*************************************************************************

**                                                                       **

** What follows is a main() routine that evaluates the command line      **

** arguments one at a time, and displays the results of each expression. **

** Without arguments, it becomes an interactive calculator.              **

**                                                                       **

 *************************************************************************/



#include <stdio.h>



char* ErrMsgs[] =

{

   "Syntax error",

   "Unbalanced parenthesis",

   "Division by zero",

   "Unknown variable",

   "Maximum variables exceeded",

   "Unrecognised funtion",

   "Wrong number of arguments to funtion",

   "Missing an argument",

   "Empty expression"

};



main( int argc, char* argv[] )

{

   TYPE  result;

   int   i;

   int   ec;

   int   a;

   char  line[1024];

   char* v;



   ClearAllVars();

   /* If we have command line arguments then we evaluate them and exit. */

   if( argc > 1 )

   {

      /* Concatenate all arguments into one string. */

      strcpy( line, argv[1] );

      for( i = 2; i < argc; i++ )

         strcat( line, argv[i] );



      /* Call the evaluator. */

      if( (ec = Evaluate( line, &result, &a )) == E_OK )

      {

         /* If we didn't assign a variable, then print the result. */

         if( ! a )

            printf( "%g\n", result );

      }

      else if( ec != E_EMPTY )

      {

         /* Display error info.  In this example, an E_EMPTY error is ignored. */

         printf( "ERROR: %s - %s", ErrMsgs[ERROR - 1], ERTOK );

         printf( "\n%s", ERANC );

         printf( "\n%*s^\n", ERPOS, "" );

      }

      return;

   }



   /* There were no command line arguments, so lets go interactive. */

   printf( "\nEE - Equation Evaluator" );

   printf( "\nBy Mark Morley  December 1991" );

   printf( "\nEnter EXIT to quit.\n" );

   printf( "\nEE> " );



   /* Input one line at a time from the user.  Note that it uses stdin, so on

      DOS or UNIX you could pipe a list of expressions into it... */

   for( gets( line ); !feof( stdin ); gets( line ) )

   {

      strlwr( line );



      /* Did the user ask to exit? */

      if( ! strcmp( line, "exit" ) )

         return;



      /* Did the user ask to see the variables in memory? */

      else if( ! strcmp( line, "vars" ) )

      {

         for( i = 0; i < MAXVARS; i++ )

            if( *Vars[i].name )

               printf( "%s = %g\n", Vars[i].name, Vars[i].value );

      }



      /* Did the user ask to see the constants in memory? */

      else if( ! strcmp( line, "cons" ) )

      {

         for( i = 0; *Consts[i].name; i++ )

            printf( "%s = %g\n", Consts[i].name, Consts[i].value );

      }



      /* Did the user ask to clear all variables? */

      else if( ! strcmp( line, "clr" ) )

         ClearAllVars();



      /* If none of the above, then we attempt to evaluate the user's input. */

      else

      {

         /* Call the evaluator. */

         if( (ec = Evaluate( line, &result, &a )) == E_OK )

         {

            /* Only display the result if it was not an assignment. */

            if( ! a )

               printf( "%g\n", result );

         }

         else if( ec != E_EMPTY )

         {

            /* Display error information.  E_EMPTY is ignored. */

            printf( "ERROR: %s - %s", ErrMsgs[ERROR - 1], ERTOK );

            printf( "\n%s", ERANC );

            printf( "\n%*s^\n", ERPOS, "" );

         }

      }

      printf( "EE> " );

   }

}



0
 
LVL 11

Expert Comment

by:griessh
Comment Utility
Dear premadhas

I think you forgot this question. I will ask Community Support to close it unless you finalize it within 7 days. You can always request to keep this question open. But remember, experts can only help you if you provide feedback to their questions.
Unless there is objection or further activity,  I will suggest to accept

     "curri"

comment(s) as an answer.

If you think your question was not answered at all, you can post a request in Community support (please include this link) to refund your points. The link to the Community Support area is: http://www.experts-exchange.com/commspt/

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
======
Werner
0
 
LVL 6

Expert Comment

by:Mindphaser
Comment Utility
Force accepted

** Mindphaser - Community Support Moderator **
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now