It is possible to attach a condition to a syntax rule. For example, the rules
foo ( # ) := ifoo(#1) :: integer(#1) foo ( # ) := gfoo(#1)
will parse `foo(3)' as `ifoo(3)', but will parse
`foo(3.5)' and `foo(x)' as calls to gfoo
. Any
number of conditions may be attached; all must be true for the
rule to succeed. A condition is "true" if it evaluates to a
nonzero number. See section Logical Operations, for a list of Calc
functions like integer
that perform logical tests.
The exact sequence of events is as follows: When Calc tries a rule, it first matches the pattern as usual. It then substitutes `#1', `#2', etc., in the conditions, if any. Next, the conditions are simplified and evaluated in order from left to right, as if by the a s algebra command (see section Simplifying Formulas). Each result is true if it is a nonzero number, or an expression that can be proven to be nonzero (see section Declarations). If the results of all conditions are true, the expression (such as `ifoo(#1)') has its `#'s substituted, and that is the result of the parse. If the result of any condition is false, Calc goes on to try the next rule in the syntax table.
Syntax rules also support let
conditions, which operate in
exactly the same way as they do in algebraic rewrite rules.
See section Other Features of Rewrite Rules, for details. A let
condition is always true, but as a side effect it defines a
variable which can be used in later conditions, and also in the
expression after the `:=' sign:
foo ( # ) := hifoo(x) :: let(x := #1 + 0.5) :: dnumint(x)
The dnumint
function tests if a value is numerically an
integer, i.e., either a true integer or an integer-valued float.
This rule will parse foo
with a half-integer argument,
like `foo(3.5)', to a call like `hifoo(4.)'.
The lefthand side of a syntax rule let
must be a simple
variable, not the arbitrary pattern that is allowed in rewrite
rules.
The matches
function is also treated specially in syntax
rule conditions (again, in the same way as in rewrite rules).
See section Matching Commands. If the matching pattern contains
meta-variables, then those meta-variables may be used in later
conditions and in the result expression. The arguments to
matches
are not evaluated in this situation.
sum ( # , # ) := sum(#1,a,b,c) :: matches(#2, a=[b..c])
This is another way to implement the Maple mode sum
notation.
In this approach, we allow `#2' to equal the whole expression
`i=1..10'. Then, we use matches
to break it apart into
its components. If the expression turns out not to match the pattern,
the syntax rule will fail. Note that Z S always uses Calc's
normal language mode for editing expressions in syntax rules, so we
must use regular Calc notation for the interval `[b..c]' that
will correspond to the Maple mode interval `1..10'.