Previous: general-information Up: ../slides.html Next: about-variables


ABOUT-EXPRESSIONS


 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].