Patterns are written in JME syntax, but there are extra operators available to specify what does or doesn’t match.
The pattern-matching algorithm uses a variety of techniques to match different kinds of expression.
Data elements such as numbers, strings, booleans are matched by comparison: a pattern consisting of a single data element matches only that exact element.
A pattern consisting of a function application function application
f(arguments...) matches any expression consisting of an application of exactly that function, and whose arguments, considered as a sequence, match the sequence of patterns
There are some special functions which match differently.
If the same group name is captured by more than one argument, then all the groups captured under that name are gathered into a list.
A pattern consisting of a sequence of terms joined by a binary operator, or a single term with a unary operator applied, is considered as a sequence. If a way of matching up the terms in the input expression with the terms in the pattern can be found, considering quantifiers and the properties of commutativity and associativity, then the expression matches the pattern. If the same group name is captured by more than one argument, then all the groups captured under that name are gathered into a sequence joined by the operator being matched.
A pattern consisting of a list matches any expression consisting of a single list, whose elements match the elements of the list in the pattern. Quantifiers allow you to write a pattern which matches lists with different numbers of terms.
Matches a number.
This only matches single number tokens, not expressions which would evaluate to a number, such as
-3(unary negation) or
This does not match unary negation, but does match negative numbers which have been substituted into an expression. To robustly match a positive or negative number, use
You can use the following annotations to restrict the kinds of numbers that are matched:
real- has no imaginary part.
complex- has a non-zero imaginary part.
imaginary- has a non-zero imaginary part and zero real part.
positive- real and strictly greater than 0.
nonnegative- real and greater than or equal to 0.
negative- real and less than 0.
integer- an integer.
decimal- written with at least one digit after the decimal place, or any real number with a fractional part.
rational- an integer, or the division of one integer by another. This doesn’t only match a single token - it’s equivalent to the pattern
integer:$n / integer:n`?.
Matches any variable name.
Match nothing. Use this as the right-hand side of a
*operation to force the pattern-matcher to match a sum or product, respectively, when the pattern would otherwise only contain one term, due to use of a quantifier.
($n `| $v)`+ + $zmatches a sum of any length consisting of numbers or variable names, such as
3 + x + 1 + 2 + y.
$n * (`*/ $n)matches either the product or the quotient of two numbers, such as
A `| B
x*x `| x^2matches two different ways of writing “x squared”.
A `& B
The expression must match both
? = ? `& m_uses(x)matches an equation which contains the variable
Match anything except
`! m_uses(x)matches any expression which does not use the variable
X `where C
The expression must match
X, and then the condition
Cis evaluated, with any names corresponding to groups captured in
Xsubstituted in. If the condition
true, the expression matches this pattern.
$n;x + $n;y `where x+y=5matches the sum of two numbers which add up to a total of 5.
macros `@ X
macrosis a dictionary of patterns. The macros are substituted into
Xto produce a new pattern, which the expression must match.
["x": a `| b] `@ ["trig": sin(x) `| cos(x) `| tan(x)] `@ trig*trig + trig*trigmatches
sin(a)*cos(b) + cos(a)*sin(b).
Capturing named groups¶
The capturing operator
; attaches to a part of a pattern, and captures the part of the input expression matching that pattern under the given name.
Capture the input expression in the group named
gif it matches the pattern
$n;acaptures a number as
a. For the expression
$n;a + $n;bcaptures two numbers
b. For the expression
(x-$?;root);termwhen matched against the expression
root = 2and
term = x-2.
X, and capture the value
vin the group named
You can use this to provide a default value for a value that’s missing or implied, for example a coefficient of \(-1\) in \(-x\).
(`+- $n);a * x `| x;a:1 `| -x;a:-1captures the coefficient of
a. When the expression is
a = -1.
Xonly if it’s identical to every other occurrence captured under the name
?;=t + ?;=tmatches two copies of the same thing, added together. It matches
1 + 1,
sin(x*pi) + sin(x*pi), but not
x+y. When the expression is
2x + 2x,
t = 2x.
Quantifiers are used to capture terms that may appear a variable number of times in a sequence.
Either one occurrence of
$n`? * xmatches
X `: Y
If the expression matches
X, match that, otherwise match as the default value
In a sequence, this acts the same as the
`?quantifier, additionally capturing the default value
Xdoes not appear in the sequence.
($n `: 1);coefficient * xmatches
5x, and captures
1when it’s omitted.
x^(? `: 1);pcaptures any power of
p=1when the power is omitted.
Any number of occurrences of
X, or none.
x * integer:$n`*matches the product of
xand any number of integers, such as
x*2*3, but not
[$n `*]matches a list containing any number of numbers, such as
At least one occurrence of
x * integer:$n`+matches the product of
xand at least one integer, such as
x*5*6, but not
The following functions change the way the matcher works.
- Allow other terms
- When matching an associative operation, allow the presence of terms which don’t match the pattern, as long as there are other terms which do satisfy the pattern.
This allows you to write patterns which pick out particular parts of sums and products, for example, while ignoring the rest.
This is equivalent to adding something like
+ ?`*to the end of every sum, and likewise for other associative operations.
- Use commutativity
When matching an associative operation, allow the terms to appear in any order. A sequence matches if an ordering of the terms which satisfies the pattern can be found.
For non-symmetric operators with converses, such as \(\lt\) and \(\leq\), also match the converse relation, reversing the order of the operands.
- Use associativity
For an associative operator \(\circ\), sequences of terms such as \(a \circ b \circ c\) will be considered together.
If this mode is not enabled, terms are not gathered into sequences before trying to match, so \((a \circ b) \circ c\) is not considered to be the same as \(a \circ (b \circ c)\).
- Gather as a list
For an associative operator, when the same name is captured by multiple terms, the resulting captured group for that name is a list whose elements are the captured subexpressions from each term.
If this mode is not enabled, the subexpressions from each term are joined together by the associative operator. This doesn’t always make sense, particularly if the group captures only portions of each term.
- Strict inverse
If this mode is not enabled, then
a-bis matched as if it’s
a/bis matched as if it’s
a*(1/b). This makes matching sums of terms that may have negative coefficients easier.
If this mode is enabled, then the behaviour described above is not used.
Match any item with the given data type.
Match a function whose name, as a string, matches the given pattern, and whose arguments, considered as a
list, match the given pattern.
m_func(?, [?,?])matches any function of two variables.
Match a binary or unary operator whose name, as a string, matches the given pattern, and whose operands, considered as a
list, match the given pattern.
Note that any properties of matched operators, such as commutativity or associativity, aren’t exploited with this matching method.
Match if the expression uses the variable with the given name as a free variable.
Match if a sub-expression matching the pattern
Xcan be found anywhere inside the input expression.
sin(pi/2) + cos(pi/2)but not