Reference
The grammar is small on purpose: you write what you would write on paper, and the parser reads it. This page is the whole of it - the operators, the 163 callable functions, and the half-dozen places where it does something other than what you expect.
Everything below is what the parser actually does, checked against the source rather than remembered.
Four of these have caught every person who has used the library, including its author. They are listed first for that reason.
^ is exclusive or, not exponentiation. x ^ 2
quietly returns x xor 2, which is a perfectly good number and
almost never the one you meant.
Write x ** 2, or spell it x degree 2.
// takes a root: 8 // 3 is 2. There are no comments
inside a formula, so nothing is being ignored.
A true comparison returns -1, false returns 0 -
the Pascal convention for a boolean stored as a number. So
(3 > 2) + 1 is 0, not 2.
Use AsBoolean if you want a Pascal Boolean back.
Sin, sin and SIN are one built-in, and a
variable registered as Rate also answers to rate and
RATE. Since case does not tell two names apart, registering a
second rate beside an existing Rate is refused
rather than shadowing it.
Higher binds tighter. The two that matter: power and root bind tighter than
multiplication, so 2 * 3 ** 2 is 18, and comparison binds
loosest, so a + b > c compares the sum.
| Operator | Means | Binds |
|---|---|---|
+ - * / | the usual four | normal |
** | power - 2 ** 10 is 1024 | higher |
// | root - 8 // 3 is 2 | higher |
degree | power again, spelled out | higher |
div mod | integer quotient and remainder | normal |
! | logical not, written before the value | lower |
= <> > < >= <= | comparison - answers -1 or 0 | lower |
and or xor not | logic | lower |
& | ~ bxor | bitwise and, or, not, xor | lower |
shl shr | bit shifts | normal |
A formula can hold integers of every width, single, double, and extended floats, booleans, strings, dates, and pointers. You never declare any of it - ask for the type you want and the conversion happens on the way out.
| Call | Formula | Answer |
|---|---|---|
AsInteger | 2 ** 10 | 1024 |
AsDouble | pi / 6 | 0.5235988 |
AsExtended | sqrt(2) | 1.4142136 |
AsBoolean | 3 > 2 | True |
AsString | 2 + 2 | '4' |
A formula is not limited to arithmetic. if is lazy - only the
branch that is taken gets evaluated, so if(x <> 0, 1 / x, 0) is
safe. Loops carry their own counter, and exit ends the whole
script with a value.
| Written | Does |
|---|---|
if(cond, then, else) | evaluates one branch, never both |
while(cond, body) | repeats while the condition holds |
repeat(body, cond) | runs the body, then tests |
for(name, from, to, body) | counted loop with its own variable |
exit(value) | ends the script there and then |
tryexcept(body, fallback) | the fallback answers if the body raises |
new(name, value) get set | variables that live inside the script |
parse("2 + 3") compiles a formula while the outer formula is
running. deriv("x ** 2", "x") differentiates symbolically and
returns the derivative - not a numeric approximation of it.
Grouped by what they are for. Every name is registered at startup and can be replaced or extended with your own.
The parser answers to 249 names in all. Besides the 163
functions below, 62 of them are constants (pi,
true, the month and weekday names, maxint64,
kilobyte), 15 are service entries that drive the parser
itself (new, get, set,
execute, parse, script), and 9 are
operators written as words (and, or,
div, mod, shl). All these counts
come from a probe built against the sources of this release, not from
memory.
sqr sqrt int round roundto trunc abs frac ln lg log log2 log10 lnxp1 exp intpower ldexp ceil floor poly factorial deriv sign iszero samevalue ensurerange comparevalue equalsvalue
sin cos tan cotan sec csc arcsin arccos arctan arccotan arcsec arccsc sinh cosh tanh cotanh sech csch arcsinh arccosh arctanh arccotanh arcsech arccsch arctan2 hypot
radtodeg radtograd radtocycle degtorad degtograd degtocycle gradtorad gradtodeg gradtocycle cycletorad cycletodeg cycletograd
mean sum sumint sumofsquares minvalue maxvalue stddev popnstddev variance popnvariance totalvariance norm
date time datetime year month day hour minute second dayofweek encodedate encodetime encodedatetime yearsbetween monthsbetween daysbetween hoursbetween minutesbetween secondsbetween millisecondsbetween weeksbetween weekoftheyear dayofthemonth dayoftheyear comparedate comparetime comparedatetime samedate sametime samedatetime ...
random randg randomrange randomfrom
strtoint strtointdef strtofloat strtofloatdef strtodate strtotime strtodatetime
if ifthen while repeat for exit tryexcept tryfinally
program Extend; {$APPTYPE CONSOLE} uses ParseTypes, ValueTypes, ValueUtils, Parser; type TPricing = class function Discount(const Header: PScriptHeader; const AFunction: PFunction; const AType: PType; const PA: TParameterArray): TValue; end; function TPricing.Discount(const Header: PScriptHeader; const AFunction: PFunction; const AType: PType; const PA: TParameterArray): TValue; begin Result := MakeDouble(GetDouble(PA[0].Value) * (1 - GetDouble(PA[1].Value) / 100)); end; var P: TMathParser; Pricing: TPricing; Handle: TFunctionHandle; Rate: Double; begin P := TMathParser.Create(nil); Pricing := TPricing.Create; try P.AddFunction('discount', Handle, fkMethod, MakeFunctionMethod(Pricing.Discount, 2, pkValue), False); P.AddVariable('rate', Rate); Rate := 20; Writeln(P.AsDouble('discount(1000, rate)'):0:2); finally Pricing.Free; P.Free; end; end.