1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
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 <evexpr.h>
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 (<evexpr.h>)
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
|