
<rule> := ( <nterm> <arrow> ( {<nterm> | <wildcard>}+ ) <equation_list> )

<nterm> := grammar symbol, e.g. <NP>, etc.

<wildcard> := %

<arrow> := <==

<equation_list> := ( <equation>+ )

<equation> := ( <path> <op> <path> ) |

              ( *or* <equation_list>+ ) |

              ( *eor* <equation_list>+ ) |

              ( <path> <= <code> ) |

              ( <path> = *DEFINED* ) |

              ( <path> = *UNDEFINED* ) |


<path> := <register> | ( <register> <slotname>+ )

<op> := = | =c | >

<register> := X0 | X1 | ... | Xn

<slotname> := SYMBOL denoting f-structure slot name

<code> := executable code fragment, including <path> references which
          should be resolved to processable object references before
          the code is executed at run-time.


NOTES
=====

When a rule is tried, each of the X1...Xn registers is filled with a
reference to the f-structure which corresponds to the relevant
non-terminal in the right-hand side of the grammar rule. X0 is filled
with a (new) empty f-structure. (Question: do we need to *copy* the
X1...Xn structures?)

=  : unify first path with second path, even if first path is undefined

=c : unify first path with second path, only if first path is defined

>  : push the second path value onto the first path value as a MULT

<= : evaluate code fragment on the right-hand side, and assign the 
     resulting f-structure to the left-hand side path. Fail if doesn't
     return a valid f-structure.

     We should consider whether to normalize the call structure of all
     code fragments. For example, if the rule has X0...Xn the function
     should take n references to f-structures as its argument, and return
     an f-structure (or, tweak the X0 f-structure and return a bool).

Suppose x0 and x1 are nouns with multiple concepts, some of which are +
and some of which are -. How does

	((x0 concept mass) = (x1 concept mass))

unify?
