The |
This document describes the syntax of the
Identifiers are formed using letters, digits and the special characters _ and ?. Identifiers must start with a letter or _. Identifiers match the [a-zA-Z_]+[a-zA-Z0-9_?]*. Examples of identifiers are x, y2, my_var and test?.
Some special predefined constants are:
Notice that streams can be used with the operators << as in C++:
mmout << 3 << "\n";
In addition to identifiers,
Strings can be braced into double quotes " ... ". Inside such a string a double quote must be blackslashed. In order to avoid blackslashing one can use the stronger string delimiters /" ... "/.
s1 := "This is a string";
s2 := "Print \"foo\"";
s2 := /"Print "foo"/;
A floating literal is a sequence of digits with a decimal point inside and an optional exponent. It matches the regular expression [-]?[0-9]+[.][0-9]+[[eE][-]?[0-9]+]?. Some examples:
z := 0.0;
w := -3.14159;
x := 1.11e2007
Note that 0. is not permited, one must write 0.0.
Here we list the operators in increasing priority order, together with their internal names:
DEFINE "==",
ASSIGN ":=",
DEFINE_MACRO “==>”,
ASSIGN_MACRO “:=>”,
PLUS_ASSIGN "+=",
MINUS_ASSIGN "-=",
TIMES_ASSIGN "*=",
OVER_ASSIGN "/="
LEFT_FLUX "<<", LEFT_FLUX_VAR "<<*", LEFT_FLUX_STR "<<%", RIGHT_FLUX ">>"
IMPLIES "=>", EQUIVALENT "<=>"
SEQOR "or", OR "\/", XOR "xor"
SEQAND "and", AND "/\"
EQUAL "=", LESS "<", LEQ "<=", GREATER ">", GEQ ">=", NOT_EQUAL "!=", NOT_LESS "!<", NOT_LEQ "!<=", NOT_GREATER "!>", NOT_GEQ "!>="
INTO "->", MAPSTO ":->"
RANGE "::", RANGEEQ ".."
PLUS "+", MINUS "-" (binary), OPLUS "@+", OMINUS "@-"
TIMES "*", OVER "/", OTIMES "@*", OOVER "@/", DIV "div", MOD "mod", COMPOSE "@"
NOT "!" (infix unitary), MINUS "-" (infix unitary), OMINUS "@-" (infix unitary),
INC "++" (infix unitary), DEC "–" (infix unitary), SIZE "#" (infix unitary)
POWER "^"
INC "++" (postfix unitary), DEC "–" (postfix unitary), NOT "!" (postfix unitary), QUOTE "'" (postfix unitary), BACKQUOTE “‘” (postfix unitary),
TILDA “~” (postifix unitary), ACCESS “.”
a..b means the range [a,b], while a::b stands for the half open range [a,b).
Tuples are written inside (...). Elements are separated by ,. Row-tuples rows are separated by ;.
Lists are written inside [...].
v := (1, 2, 3);
x := ("a", 3, (7, 0.4));
M := (1, 2; 3, 4; 5, 6);
l := [2, 3, 5, 7, 11];
Automatic constructions are possible through the | resp. || notation:
v := ( i^2 | i in 1..3 );
l := [ i * j | i in 1..3, j in 1..4 ];
m := matrix (i*j | i in 1..5 || j in 1..5)
The default type of lists used in the interpreter is List(Generic).
Tables allow to store the association between keys of one type to values of another type. They are defined by providing a default value. In the following exemple, the default value is 1:
t := table(1);
The definition of specific values is done as follows:
t[1] := -3;
t[34] := 2;
The default type of tables used in the interpreter is Table(Generic,Generic).
Any function definition can be preceded by quantifiers forall(...) or exists(...).
A function definition is done as follows:
name (arg1: type1, arg2: type2, ...): returned_type == ...
lambda (arg1: type1, arg2: type2,
...): returned_type do ...
Notice that any of the type specifications can be omitted, in which case the type is assumed to be Generic. Expression macros can be defined by using macro instead of lambda.
When function or macro have only one argument, () can be omited.
square x ==> x^2; // macro for squaring
discr (a, b, c) == b^2 - 4*a*c;
forall (R)
gcd (p: Polynomial(R), q: Polynomial(R)):
Polynomial(R) == {...}
A function or a macro foo is called in the usual way: foo(arg1, arg2,...).
If foo is unitary then () can be omited, but note that foo a b c is equivalent to foo(a(b(c))). Function call is always by value.
Instructions are separated with ;.
x := 1;
y := 3;
z := x*y;
The construction is as follows: if condition then block1 else block2.
condition is any expression that evaluates to a boolean. block1 and block2 are either one instruction or a block of instructions braced into {...}. The else part is optional.
if true then 1;
if a = b then 1 else 2;
if i = 0 then { x := 1; y := 2} else { z := 3; mmerr
<< "error" }
Loops are constructed as follows: [for E1] [while E2] [until E3] [step E4] do block.
Here [...] means that the expression is optional. block is an instruction or a sequence of instruction delimited by {...}. break exits the loop, and continue goes to the next step of the loop.
do mmout << "no end "; // This loop
has no end
for i in 1..3 do mmout << i << "
";
i := 0; while i < 0 do { mmout << i <<
" "; i := i + 1 }
Comments starting with // extend to the end of the physical line. Such a comment may appear at the start of a line or following whitespace or code, but not within a string literal. Multi-line comments must be braced into /{ ... }/ and can be nested.
x := 1; // Assign 1 to x.
y := 2;
/{ This
is multi-line
comment about y.
}/
The Mathemagix grammar is specified in the file mmx-parser.ypp of the basix module.