  This file describes the ``expression'' context which is available
  in the ${} expando and the @, IF, and WHILE commands.

  As opposed to the ``text'' context, where everything is assumed to
  be text unless it is preceeded by a $, in the ``expression'' context
  everything is assumed to be a variable name unless it is surrounded
  by square brackets '[' and ']'.

  The '@' command is not really a command, but rather is an operator
  to the command parser to pass the entire line to the expression parser
  instead of passing the line through the command parser.  The result
  of any @ command is thrown away.

  The syntax of the expression context is modeled after the C++ syntax,
  and honors order of precedence as defined by C++.  A simple example
  is if you have ${A + 2}, if the ASSIGNed variable "A" has the
  value of '3', the result of the expando is '5'.

  Paranthesis can be used freely in expressions, so (A+2)*3 would give
  the value of (3+2)*3 == 15, whereas A+2*3 would give a value of 
  3+2*3 == 3+6 == 9, because multiplication comes before addition.

  All common operators from C are available (+, -, *, /, %), as well
  as the string concatenation operator (##) which treats both sides
  as strings and pastes them together: If A is 3 and B is 7, then
	A ## B is "37" but  A + B is "10"

  Bitwise operators are also available.  These include the '&' operator
  for bitwise AND, '|' for bitwise OR, '^' or bitwise XOR, and '~' for
  bitwise NOT.  (ones complement)

  So if A is 12 and B is 11,
		A & B is 8,	A | B is 15, 	A ^ B is 7.

  Assignment to variables can be done using the '=' operator.  If you
  have the expression "C = A + B", then C would be assigned the value
  of 10 (using the values of A and B from the above paragraph).  It is
  very useful to use the '@' command for assignment, to do something
  like this:

	@ C = A + B

  The '=' operator always returns the value assigned, so you can extend
  assignments leftward as in:

	@ D = C = A + B

  Which would assign the same value (10) to both C and D.  It is useful
  to use the ${} expression if you want to do an assignment but also have
  the value available for inclusion in a command, as in the following:

	echo The value of C is now ${C = A + B}

  which would set C to 10 and display "The value of C is now 10".

  Also available are the full range of "shorthand" assignment operators.
  These include +=, -=, *=, /=, %=, #=, &=, ^=, and |=.

  Also, the prefix and postfix increment and decrement operators are
  also available, so the following forms are equivilant.
		@ a = a + 1		@ b = b - 1
		@ a += 1		@ b -= 1
		@ a++			@ --b

  Also available is the tertiary operator, which allows you to have a
  three part if/then/else expression:  A full explanation of the tertiary
  operator is beyond the scope of this help file, but the syntax is such:

	(expression) ? (value1) : (value2)

  is equal to value1 if the expression is nonzero (or nonnull)
  and is equal to value2 if the expression is zero or null.


  Comparison operations also exist. These return 1 if the comparison is
  valid (true) and 0 if it is invalid (false). The comparison operations
  available are:

    == (equal to)
    >  (greater than)
    >= (greater than or equal to)
    <  (less than)
    <= (less than or equal to)
    != (not equal to)

  Thus, the following expressions would result in the following results:
   ( recall A = 3 and B = 7 )

	A == B			FALSE	0
	A == 3			TRUE	1
	A > 3			FALSE	0
	A >= 3			TRUE	1
	A != 3			TRUE	1

  These expressions can be combined with || (OR), && (AND) and ^^ (XOR).
  So (A == 3) || (B==3) would be TRUE, and (A == 2) && (B == 7) would be
  FALSE. You can also negate expressions with ! (NOT), so !(A == 3) would
  be FALSE. These boolean expressions are used primarily in IF and WHILE.

  A string expression is considered to be true if it is non empty. So
  if E has the value "word", then E || ( A > 3) is true, because E has
  a non empty value, and !E is false.


  Functions can also appear in expressions. The arguments to functions
  are evaluated as normal $ type expressions. Thus the following alias:

    alias test echo ${ MID(3 2 $0) + 5) }

  is executed with /test 123456, would give  34 (Two digits from position 3
  in $0) + 5, giving 39. If the function returns another function name, that
  function name can be called with another set of brackets. Thus if you have
  the following set of aliases:

    alias fptr
    {
        if ( [$0] )
            { @ function_return = func1 }
            { @ function_return = func2 }
    }
    alias func1 @ function_return = this is $0
    alias func2 @ function_return = that is $0
    alias check echo ${ fptr($0)($1) }

  then /check 0 1 would print "that is 1", and /check 1 0 would print
  "this is 0".

  Array expressions can also be used in this way. For example:

    assign A.1.1 One One was a racehorse
    assign A.1.2 Two Two was one too
    assign A.2.1 One One won one race
    assign A.2.2 Two Two won one too
    alias rhyme echo ${ A[$0][$1] }

  would cause /rhyme 2 1 to print "One One won one race".

  Function and array expressions can be combined to give a form
  of pointer arithmetic like that seen in C. If a function
  RhymeNum exists as follows:

    alias RhymeNum @ function_return = [A]
  and rhyme is changed to:
    alias rhyme echo ${ RhymeNum()[$0][$1] }

  /rhyme 2 1 still prints "One One won one race". This is because
  RhymeNum returns A, and the expression then becomes A[$0][$1].
  The $0 is expanded to 2, so it becomes A.2[$1], and the $1 is
  expanded to 1, so it becomes A.2.1, which is then substituted as
  a variable for "One One won one race". The reverse is also possible.
  For example, a robot might have the following:

     alias thing.0 @ function_return = laughs his silly head off
     alias thing.1 @ function_return = growls menacingly
     alias thing.2 @ function_return = smiles like a crocodile
     alias thing.3 @ function_return = wails uncontrollably
     alias something SAY WereBot ${ thing[$RANDOM(4)]() }

  Will cause WereBot to say that it's laughing itself silly, growling
  menacingly, smiling like a crocodile or wailing uncontrollably.
  Assuming RANDOM(4) results in a value of 2, This expands to
  thing.2(), which is then considered to be a function and substituted
  to "smiles like a crocodile", the end result being that WereBot will
  say "WereBot smiles like a crocodile".

  Finally, there are occasions when you need to get back to the $
  substitution level. This can be done by enclosing text to be used at
  this level in [..]. For example, [A] substitutes to a literal 'A', 
  whereas A on its own substitutes to 3, and [$0] is needed to get
  argument 0, because 0 on its own is taken to be the number 0.
  Example:

    alias something SAY WereBot ${ [$0][$RANDOM(4)]() }

  will case /something thing to first expand [$0] to thing, giving
  thing[$RANDOM(4)](), and if $RANDOM(4) returns 1, this becomes
  thing.1(), which expands to "growls menacingly", and causes
  WereBot to say "WereBot growls menacingly".


  The following is the parse tree for expressions such as those
  **** NOTE -- VERY IMPORTANT! **** This is the parse tree for EPIC
  clients, and is NOT the same as the one for the regular 
  client!  The regular ircII client uses its own operator precedence
  table, whereas the EPIC client conforms to the C++ operator order.

	NU_POIX = varexp++		|
		  varexp--		|
		  VAR_EXPR   
	NU_EXPR = NU_ASSN
        NU_ASSN = varexp = NU_ASSN	|
		  varexp += NU_ASSN	|
		  varexp -= NU_ASSN	|
		  varexp *= NU_ASSN	|
		  varexp /= NU_ASSN	|
		  varexp %= NU_ASSN	|
		  varexp &= NU_ASSN	|
		  varexp ^= NU_ASSN	|
		  varexp |= NU_ASSN	|
		  varexp #= NU_ASSN	|
		  NU_TERT
	NU_TERT = NU_COMP ? NU_COMP : NU_COMP |
		  NU_CONJ
	NU_CONJ = NU_CONJ && NU_CONJ	|
		  NU_CONJ || NU_CONJ	|
		  NU_CONJ ^^ NU_CONJ	|
		  NU_BITW
	NU_BITW = NU_COMP & NU_COMP	|
		  NU_COMP | NU_COMP	|
		  NU_COMP ^ NU_COMP	|
		  NU_COMP
	NU_COMP = NU_COMP == NU_COMP	|
		  NU_COMP != NU_COMP	|
		  NU_COMP >  NU_COMP	|
		  NU_COMP >= NU_COMP	|
		  NU_COMP <  NU_COMP	|
		  NU_COMP <= NU_COMP	|
		  NU_ADD
	NU_ADD  = NU_ADD + NU_ADD	|
		  NU_ADD - NU_ADD	|
		  NU_ADD ## NU_ADD	|
		  NU_MULT
	NU_MULT = NU_MULT * NU_MULT	|
		  NU_MULT / NU_MULT	|
		  NU_MULT % NU_MULT	|
		  NU_UNIT
	NU_UNIT = token NUX_MODIF	|
		 unaryop token		|
		( NU_EXPR )		|
		[ expression ] NUX_MODIF |
		NU_PRIX
	NU_PRIX = ++varexp		|
		  --varexp

	NUX_MODIF = ( expression ) NUX_MODIF |
		    [ expression ] NUX_MODIF

	unaryop = ! |
		  ~

Special cases:
  If a (...) or {...} construct is quoted with \(...\) or \{...\}
  then variable expansion will take place on the first available
  parse run.  However, after parsed, the \'s are eaten. e.g.
    alias bonk echo ($0)        will return "($*)" regardless of
  the argument to the alias.  No expansion takes place.  However, in
    alias bonk echo \($0\)
  expansion takes place as the special meaning of the () is taken
  away by \.  This will return "(arguments to bonk)".
