Previous: general-information Up: ../slides.html Next: about-variables
The parsing package supports input of keywords, switches, integer
numbers, floating-point numbers, quoted and unquoted text strings, file
names, and special tokens (such as comma). It is desirable to permit
arbitrary arithmetic expressions whereever numeric values are expected,
and in order to support this with minimal runtime overhead, the
convention is adopted that a right parenthesis met where a number is
expected will cause input to be collected up to and including a
matching left parenthesis, and that parenthesized string will then be
passed to a powerful expression parser for evaluation.
The expression parser supports a complete FORTRAN 77 numeric and
Boolean (LOGICAL) expression grammar, with extensions from the Ada, C,
Pascal, and Reduce languages. In addition, it supports vector
expressions and named variables. Variable names begin with a letter
optionally followed by one or more letters, digits, underscores, or
dots. There is no variable name length restriction, and letter case is
NOT significant. Names are looked up first in the built-in function
name table, and if not found there, then in the variable name table.
Thus, all function names are effectively reserved words, and attempts
to assign values to them or use them as scalar variables will result in
an error return.
This reservation of some names is required because size and type
declarations of variables are not required; when an unknown name is
encountered, it is automatically entered into the symbol table with a
flag marking it as undefined. Immediate symbol table installation is
necessary because this parser requires no lookahead at all, and the use
of a variable on the left-hand side of an assignment cannot be
recognized until possibly many more tokens have been parsed (e.g.
"V(very_long_subscript_expression) = value"). Thus, variables come
into existence when they are assigned values, and disappear only when
the symbol table is reinitialized.
Operators are applied according to assigned precedences, with those of
highest precedence being applied first. For example, since multiply
(*) has higher precedence than plus (+), the expression (A + B*C) is
evaluated as ((A) + (B*C)), NOT as ((A + B)*C). Unless otherwise
noted, operators are left associative, meaning that in a sequence of
operators of identical precedence, they are applied in order from left
to right; thus (A*B*C*D) is GUARANTEED to be evaluated as
(((A*B)*C)*D). Parentheses can always be used to force evaluation of
subexpressions first, and are recommended for clarity; operator
precedences are not the same in all programming languages, and subtle
errors can creep in if one is not careful. The operator precedences
are as follows:
Level 0 (lowest precedence):
Unsigned_Named_Literal,
Unsigned_Subscripted_Named_Literal,
Unsigned_Integer_Literal,
Unsigned_Floating_Literal
Level 1: (right associative)
Assign_Op = = (lhs becomes rhs)
| += (lhs becomes lhs + rhs)
| -= (lhs becomes lhs - rhs)
| *= (lhs becomes lhs * rhs)
| /= (lhs becomes lhs / rhs)
Level 2:
Equiv_Op = .EQV.
| .NEQV.
Level 3:
Disjunctive_Op = .OR.
| .XOR.
Level 4:
Conjunctive_Op = .AND.
Level 5:
NOT_Op = .NOT.
Level 6:
Rel_Op = == (equal)
| .EQ. (equal)
| <> (not equal)
| # (not equal)
| .NE. (not equal)
| < (less than)
| .LT. (less than)
| > (greater than)
| .GT. (greater than)
| >= (greater than or equal)
| .GE. (greater than or equal)
| <= (less than or equal)
| .LE. (less than or equal)
Level 7:
Add_Op = + (including unary +)
| - (including unary -)
Level 8:
Mul_Op = *
| /
| >> (binary integer logical shift
right)
| << (binary integer logical shift
left)
Level 9: (right associative)
Exp_Op = **
Level 10: Function_Op = ABS | ACOS | ACOSH | AINT | ANINT
| ASIN | ASINH | ATAN | ATAN2 | ATANH
| BINOM | CASE | CEIL | COS | COSD
| COSH | COTAN | COTAND | CROSS | DIM
| DOT | ENORM | ERF | ERFC | EXP
| FLOAT | FLOOR | GAMMA | IF | IFIX
| INORM | INT | LGAMMA | LOG | LOG10
| LOG2 | MAX | MIN | MOD | NINT
| PROD | REAL | ROUND | SIGN | SIN
| SIND | SINH | SIZE | SQRT | SUM
| SWITCH | TAN | TAND | TANH | TRUNC
| VEC
Note that assignment is not a statement, but instead is a legal
expression whose value is that of the right-hand side. Thus 3 + (A =
5) sets A to 5 and evalutes to 8. Assigning a scalar or vector to a
variable creates it and defines its size; subsequent assignment can
change the size. Vector elements are represented in the usual way
"name(subscriptexpression)", where the subscript expression ranges in
value from 1 up to the number of elements in the vector.
Integer division truncates toward 0, for example:
+11/5 = +2 -11/5 = -2
MOD is defined for integer division by the relations
MOD(A,B) = A - (A/B)*B
Note that A MOD B has the sign of A. Some examples are
MOD( 13, 5) = 3
MOD(-13, 5) = -3
MOD( 13,-5) = 3
MOD(-13,-5) = -3
The function operators are the same as the real-arithmetic generic
functions in FORTRAN 77, with these additions:
ACOSH(x) Inverse hyperbolic cosine of x
ASINH(x) Inverse hyperbolic sine of x
ATANH(x) Inverse hyperbolic tangent of x
BINOM(n,m) Binomial coefficient, n!/((n-m)!m!)
CASE(n,e1,e2,...,ek,edefault)
e1 if n = 1, e2 if n = 2, ..., ek if n = k, and for all
other values of n, edefault.
CEIL(x) Smallest integer not less than x
COSD(x) Cosine for angle x in degrees
COTAN(x) Cotangent for angle x in radians
COTAND(x) Cotangent for angle x in degrees
CROSS(v1,v2) Right-handed cross product of 3-element vectors v1 and
v2
DOT(v1,v2) Dot product of vectors v1 and v2
ENORM(e1,e2,...,en)
Euclidean norm of n-vector (n > 0), equivalent to
SQRT(e1**2 + e2**2 + ... + en**2), but without
possibility of destructive overflow or underflow
ERF(x) Error function
ERFC(x) Complementary error function (1 - ERF(x))
FLOOR(x) Largest integer not greater than x
GAMMA(x) Gamma function
IF(b,ethen,eelse)
Ethen if b is TRUE, and otherwise, eelse.
INORM(e1,e2,...,en)
Infinity norm of n-vector (n > 0), equivalent to
MAX(ABS(e1),ABS(e2),..., ABS(en))
LGAMMA(x) Natural logarithm of absolute value of gamma function
LOG2(x) Logarithm of x to base 2
PROD(e1,e2,...,en)
Product of arguments, e1*e2*...*en.
ROUND(x) Nearest INTEGER to x, and rounding for half integral
values is away from zero
SIND(x) Sine for angle x in degrees
SIZE(v) Number of elements in vector v
SUM(e1,e2,...,en)
Sum of arguments, e1+e2+...+en
SWITCH(b1,e1,b2,e2,...,bk,ek,edefault)
Ej, where bj is the first b which is TRUE, and edefault
if none of the b's are TRUE.
TAND(x) Tangent for angle x in degrees
TRUNC(x) Same as FLOOR and INT
VEC(e1,e2,...,en)
Vector of the concatenation of the elements e1, e2, ...,
en. Equivalent to [e1,e2,..., en]
Scalar values are treated as vectors of one element. Vectors may be
generated by a value list in square brackets (e.g.
[1,cosd(60),sqrt(27)]), or by a special function VEC (e.g.
VEC(1,cosd(60),sqrt(27))). The latter will be useful primarily for
those machines whose character sets lack square brackets. A vector
whose components are themselves vectors is not a matrix, but simply a
vector formed by the concatenation of elements in its components.
Thus, [[1,2],[3,4]] is equivalent to [1,2,3,4].
With the few exceptions noted below, functions operating on vectors
apply component-wise, returning a vector of the same size. Thus,
SQRT[3,4,5] is equivalent to [SQRT(3),SQRT(4),SQRT(5)].
Binary operators and functions (ATAN2, BINOM, and MOD) apply
component-wise as well, with the rule that if the two vector arguments
have differing numbers of elements, the shorter one is implicitly
extended by its last element. This choice means that no special action
need be taken for scalar-vector multiplication; thus, [1,2,3]*10
evaluates to [10,20,30].
The functions ENORM, INORM, MAX, MIN, PROD, SIZE and SUM permit a
variable number of arguments (1 or more), and ALWAYS return a scalar
result. If the arguments are vectors, they are simply expanded into
their components. MAX([1,2],[-7,3]) therefore evaluates to 3. Note
that ENORM([1,2],[-7,3]) does not return a vector of 2 Euclidean norm
values, but a single value which is the norm of the vector [1,2,-7,3].
To get the former result, one would write [ENORM([1,2]),ENORM([-7,3])].
The function DOT requires exactly two vector arguments, and returns the
dot product of the two as a scalar value. ENORM(V) is equivalent to
SQRT(DOT(V,V)), but is not subject to destructive overflow or underflow
which may occur in the latter form. Similarly, INORM(V) is equivalent
to MAX(ABS(V)).
The function CROSS requires exactly two vector arguments, each of which
MUST have 3 elements, and returns a 3-element vector which is the
right-handed cross product of the two vectors. It is the only function
for which a size requirement applies to its argument vectors.
CASE, IF, and SWITCH are treated specially. The selector values
(argument 1 for CASE and IF, arguments 1, 3, 5, ... for SWITCH) use
only the first component of their possibly vector values, and return
the selected argument as a vector result. For example,
CASE(2,[1],[-2,2],[3,-3,3],0) returns the vector [-2,2].