EVEXPR Evaluating Algebraic Expressions in SPP Programs dct 17 April 1985 1. Introduction EVEXPR is a function which takes an algebraic expression as input, evaluates the expression, and returns the value of the expression as the function value. The input expression (a character string) is parsed and reduced to a single value. The operands to the expression may be either constants or identifiers (foreign strings). If an identifier is encountered the user supplied get operand procedure is called to return the value of the operand. Operands are described by the operand structure, and operands are passed about by a pointer to such a structure. The value of the expression is returned as the function value and is a pointer to an operand structure. Operands of different datatypes may be mixed in an expression with the usual automatic type coercion rules. All SPP datatypes are supported plus the string datatype. All SPP operators and intrinsic functions are recognized. 2. Procedures op = evexpr (expr, locpr(getop), locpr(ufcn)) getop (identifier, op) ufcn (fcn, args, nargs, op) where evexpr The main entry point. expr A character string, the expression to be evaluated. getop A user supplied procedure which returns the value of a nonconstant operand given the NAME of the operand (a character string) as input. If locpr(getop) is NULL only constant operands are permitted in the expression. ufcn A user supplied procedure which returns the value of a user defined function given the name of the function as the first argument (a string). If locpr(ufcn) is NULL only the standard functions are permitted. fcn Name of the function to be evaluated. args Array of pointers to operands (the arguments to the function). nargs Number of arguments to function. op A pointer to an operand structure A a simple example, consider the following statement which evaluates a constant expression and prints the value on the standard output. include pointer o, evexpr() o = evexpr ("sin(.5)**2 + cos(.5)**2)", NULL, NULL) switch (O_TYPE(o)) { case TY_INT: call printf ("result = %d\n") call pargi (O_VALI(o)) case TY_REAL: call printf ("result = %g\n") call pargr (O_VALR(o)) case TY_CHAR: call printf ("result = %s\n") call pargstr (O_VALC(o)) } If a syntax error occurs while parsing the expression EVEXPR will take the error action "syntax error". The NULL arguments could be replaced by the LOCPR addresses of get operand and/or user function procedures if required by the application. 3. Lexical Form The lexical form of the input expression is the same as that of SPP and the CL for all numeric, character, and string constants and operators. Any other sequence of characters is considered an identifier and will be passed to the user supplied get operand function to be turned into an operand. 4. Syntax Parsing and evaluating of the input expression is carried out by an SPP/Yacc parser. The grammar recognized by the parser is given below. expr : CONST # numeric or string constant | IDENT # external operand (getop) | '-' expr %prec UMINUS | expr '+' expr | expr '-' expr | expr '*' expr | expr '/' expr | expr '**' expr | expr '//' expr | '!' expr | expr '<' expr | expr '<=' expr | expr '>' expr | expr '>=' expr | expr '==' expr | expr '!=' expr | expr '&&' expr | expr '||' expr | IDENT '(' arglist ')' # function call | '?' expr ':' expr # conditional expression | '(' expr ')' ; arglist : # Empty. | arglist ',' expr ; 2. Data Structures The operand structure (size 3 su) is used to represent all operands in expressions and on the parser stack. Operands are passed to and from the outside world by means of a pointer to an operand structure. The caller is responsible for string storage of string operands passed to EVEXPR. EVEXPR manages string storage for temporary string operands created during expression evaluation, as well as storage for the final string value if the expression is string valued. In the latter case the value string should be used before EVEXPR is again called. struct operand { int type # operand datatype union { bool v_b # boolean value int v_i # integer value real v_r # real value char *v_s # string value } v } SPP equivalent () O_TYPE(o) # operand datatype O_VALB(o) # boolean value O_VALI(o) # integer value (or string ptr) O_VALR(o) # real value O_VALC(o) # string value