Function evaluation

Submitted by javelin on Sat, 2002-11-30 18:27

The expression parser is responsible for evaluating functions (as well as doing other kinds of parsing). It's recursive in design, which means that during evaluation, the parser often calls itself to evaluate subportions of an expression.

For example, here's how [add(1,sub(3,2))]foo is evaluated:

[add(1,sub(3,2))]foo

The parser starts with the first character. 
It's a [, which causes the parser to recurse,
and turns on mandatory function evaluation --
the next thing we expect to see is a function.
The next evaluation will terminate when it reaches a ].

  add(1,sub(3,2))]foo

  The level-2 parser starts with the first character
  ('a') and keeps reading until it comes to a special
  character, the '(', which marks the end of a 
  function's name. It looks to see if 'add' is a valid
  function, which it is, and now recurses to parse the
  first argument. The next evaluation will terminate 
  when it reaches a comma, which is the argument separator.

    1,sub(3,2))]foo

    The level-3 parser starts with the first character
    ('1') and keeps reading until it comes to a special
    character, the comma, which is the terminator it was
    expecting. Because no other special characters have
    been reached, it returns what it's got so far ('1')
    as a literal.

  The level-2 parser recurses again to evaluate the
  second argument to add():

    sub(3,2))]foo

    The level-3 parser starts with the first character
    ('s') and keeps reading until it comes to a special
    character, the '('. It checks that 'sub' is a 
    function, and recurses to parse its first argument.

      3,2))]foo

      The level-4 parser returns the literal '3'

    The level-3 parser recurses again to evaluate the
    second argument to sub():

      2))]foo

      The level-4 parser returns the literal '2'. It
      returns because it hits a ')', which denotes the
      end of an argument list.

    ))]foo

    The level-3 parser now calls the internal sub() 
    function, with arguments '3' and '2'. That function
    returns '1', and this parser level returns with that
    value.

  )]foo

  The level-2 parser now reads an ')', which terminates
  the argument list to add(). It calls the internal add()
  function, with arguments '1' and '1'. That function 
  returns '2'.

]foo

The top-level parser now expects to see a ']', marking the
end of its recursion for mandatory function evaluation.
It gets one, and the overall result of the recursive
parsing was '2'.

foo

The top-level parser continutes to work its way through 
the characters. No more special characters are encountered,
so 'foo' is copied into the return buffer. The top-level
parser returns '2foo', and parsing is done.

A player set DEBUG and evaluating the expression above would see very similar output, though DEBUG, for brevity, does not show evaluations at the level of literals:

think [add(1,sub(3,2))]foo

#7! [add(1,sub(3,2))]foo :
#7! add(1,sub(3,2)) :
#7! sub(3,2) => 1
#7! add(1,sub(3,2)) => 2
#7! [add(1,sub(3,2))]foo => 2foo
2foo