ELAM has the following syntactic elements:
Expression | Explanation |
1 | a simple literal number |
1+2 | simple operation using two literals |
2*a | simple operation using a literal and a variable |
1+2*3 | two operations with precedence (* is evaluated before +) |
(1+2)*3 | two operations with precedence changed through parentheses |
a=3+4 | operation with the result assigned to a variable |
b=a=3+4 | operation with the result assigned to two variables |
The default library knows numeric literals:
Example | Composition | Description |
123 | starts with 1..9, contains any number of 0..9 | decimal integer value |
012 | starts with 0, contains 0..7 | octal integer value |
0x12 | starts with 0x, contains 0..9 and a..f/A..F | hexadecimal integer value |
1.8, .8, 1. 1e34 | starts with digit or dot, contains digits, optionally a dot and/or "e" and more digits | floating point value |
If the string library is loaded you can also formulate strings enclosed in "..." or '...'.
Constants are variables that have been marked as immutable, they can be of any type.
Unary operators precede an expression and change it, returning the result. For example the unary "-" operator in the default library negates its numeric argument (e.g. if "a" is 12, then "-a" returns -12).
Binary operators operate on two expressions, one to the left and one to the right of the operator.
If operators follow each other (e.g. "a != -b") then the operators must be separated by spaces.
Parentheses group operations and may alter the order in which they are executed. Parentheses are evaluated before any other operation.
The default library has the following precedence order:
Operator Class | Operators | Precedence Value |
Parentheses | (parentheses), functions(...) | 1000 |
All Unary Operators | ~, !, -, + | 100 |
Maximum usable Precedence | 99 | |
Multiplicative | *, /, % | 90 |
Additive | +, - | 80 |
Shift | <<, >> | 70 |
compare | <, >, ==, !=, <=, >= | 60 |
bitwise AND | & | 50 |
bitwise XOR | ^ | 45 |
bitwise OR | | | 40 |
logical AND | && | 30 |
logical XOR | ^^ | 25 |
logical OR | || | 20 |
Lowest usable Precedence | 1 | |
assignments | =, +=, -=, ... | 0 |
This means for example that in "a=9+1+2*(3-1)" these operations are executed in this order:
For example: in "2*(3-1*5)/4" the expression "3-1*5" inside the parentheses is resolved before the remaining multiplication and division around it are executed. While calculating the content of the parentheses the normal precedence applies, so the multiplication is executed before the subtraction.
In other words: if ELAM encounters an operator that equals its notion of the assignment operator (normally "="), then it is always interpreted as assignment - even if another operator with the same name exists. If ELAM encounters an operator that contains the assignment syntax (normally: one that ends in "="), then it first checks whether there is a more specific operator (above, e.g. "==") and uses it if found, if there is none, then it checks whether this could be a compound operation (e.g. "+=", which first adds and then assigns the result back to the left argument).
Assignment syntax can be changed by changing the character class for the assignment operator.
The default library knows the following functions:
Function | Description |
int(value) | converts value to integer, rounding towards zero |
float(value) | converts value to a floating point number |
string(value) | converts value to string |
concat(v1,v2,...) | concatenates strings |
The "whitespace" class contains any character that can be ignored. Whitespaces can be used to separate tokens and to adjust expressions for readability. In the default library these are the normal space, the tab chars (\t, \v), and line endings (\n, \r).
The "operators" character class contains all characters that make up operators, in the default library these are "~!@#$%^&*-+=:<>?/". Operator class characters can be used to formulate unary and binary operators. This class also contains the assignment operator.
The "names" character class contains all characters that make up variable and function names. In the default library these are English letters (a-z and A-Z), digits (0-9), and underscores (_).
The "operators" and "names" classes must not overlap. While parsing the engine will recognize if the next character in a line is a different class (e.g. "a+b" is equivalent to "a + b"), but inside a class spaces have to be used to separate tokens (e.g. "+-" is different from "+ -").
The class of "literals" is comprised of rules that define what a literal looks like. Literals have a start character (which may overlap with the "names" class), a rule how to recognize the end of the literal and a routine to convert it to an actual value. The characters making up a literal can come from any class, although it is recommended to not use any operator characters. The start characters of literals may overlap, in this case they have a built-in precendence in which they are tried out. For example the class of integer numbers in the default library start with digits (0-9) and may contain digits and an optional "x" in second position (as in 0x12), any non-digit ends the literal.
The "special" characters are those with a specific built-in meaning to the parser. In the default library those are:
Characters | Description | Rules |
Parentheses "(", ")" | change the order of evaluation by grouping the inner operations to be performed before the outer operations, or by enclosing the arguments of a function | the two parentheses characters must differ and must not match any other class |
Comma "," | separates the arguments of a function | single character that must not be contained in any other class |
Equals "=" | denotes assignments, the character itself cannot be overridden as operator, combinations with other operators can be overridden | one or two characters: prefix and postfix, they must differ, they both must be part of the operator class |
Any other character falls in the "noise" class and produces a parser error.