previous contents next
Previous: Network Attributes and Attribute Lists Next: Element Selectors and Iterators


In Enif, most functionalities which access network data are not implemented by accessing network attributes directly, as is the case in EMME/2. Rather, wherever possible, the available functionalities (such as selecting subnetworks, plotting or listing network related data) are based on expressions.

In general, an expression is made up of an arbitrary combination of operands, operators and calls to intrinsic functions, using syntax rules compatible with those used by the expressions in EMME/2. In practice, however, an expression is often as simple as a single constant value (e.g. ``1'') or an attribute name (e.g. ``volau'').

In contrast to EMME/2, where expressions are limited to handle exclusively numerical values, Enif expressions support both numerical and string values. A strict distinction is made between numerical and string values. Each operator has well defined operand types and each intrinsic function requires its arguments to be of the specified types. Special intrinsic functions can be used to convert strings to numbers and vice versa, should this become necessary.

Each operand of an expression must correspond to one of the following:

Table 2: Operators in expressions
Operator: Description: Operand and result types:
|| or .or. logical OR num||num  $\rightarrow$ num
&& or .and. logical AND num&&num  $\rightarrow$ num
.xor. logical XOR num.xor.num  $\rightarrow$ num
!= or .ne. not equal num!=num  $\rightarrow$ num
< or .lt. less than num<num  $\rightarrow$ num
<= or .le. less than or equal num<=num  $\rightarrow$ num
== or .eq. equal num==num  $\rightarrow$ num
>= or .ge. greater or equal num>=num  $\rightarrow$ num
> or .gt. greater than num>num  $\rightarrow$ num
!= lexically not equal str!=str  $\rightarrow$ num
< lexically less than str<str  $\rightarrow$ num
<= lexically less than or equal str<=str  $\rightarrow$ num
== lexically equal str==str  $\rightarrow$ num
> lexically greater than str>str  $\rightarrow$ num
>= lexically greater or equal str>=str  $\rightarrow$ num
~ string matched by regular expression str~str  $\rightarrow$ num
!~ string not matched by regular expression str!~str  $\rightarrow$ num
& bitwise AND num&num  $\rightarrow$ num
+ add num+num  $\rightarrow$ num
+ string concatenation str+str  $\rightarrow$ str
- subtract num-num  $\rightarrow$ num
.addle. add if less or equal to zero num.addle.num  $\rightarrow$ num
.max. maximum num.max.num  $\rightarrow$ num
.min. minimum num.min.num  $\rightarrow$ num
.psum. add and truncate when negative num.psum.num  $\rightarrow$ num
| bitwise OR num|num  $\rightarrow$ num
* multiply num*num  $\rightarrow$ num
.mod. modulo num.mod.num  $\rightarrow$ num
/ divide num/num  $\rightarrow$ num
^ or ** power num^num  $\rightarrow$ num

A list of all available operators is shown in Table 2, grouped in the order of increasing operator precedence. It also shows the required operand types for each operator, as well as the type of the result of the operation. All operators are binary operators, with the exception of the ``+'' and ``-'' operators; these can be used as unary operators at the beginning of subexpressions.

Table 3: Intrinsic functions in expressions
Function: Description: Argument and result types:
abs() absolute value abs(num) $\rightarrow$ num
Atan() arc tangent (degrees) Atan(num) $\rightarrow$ num
atan() arc tangent (radians) atan(num) $\rightarrow$ num
Atan2() arc tangent (degrees) Atan2(num,num) $\rightarrow$ num
atan2() arc tangent (radians) atan2(num,num) $\rightarrow$ num
ceil() ceiling function ceil(num) $\rightarrow$ num
Cos() cosine function (degrees) Cos(num) $\rightarrow$ num
cos() cosine function (radians) cos(num) $\rightarrow$ num
erf() Gaussian error function erf(num) $\rightarrow$ num
exp() exponential function exp(num) $\rightarrow$ num
floor() floor function floor(num) $\rightarrow$ num
get() return corresponding stack value get(num) $\rightarrow$ num
if() if-then-else on string values if(num,str,str) $\rightarrow$ str
if() if-then-else on numerical values if(num,num,num) $\rightarrow$ num
index() index of first substring index(str,str) $\rightarrow$ num
int() truncate to integer int(num) $\rightarrow$ num
justify() left/right justify string justify(str,num) $\rightarrow$ str
left() left substring left(str,num) $\rightarrow$ str
length() string length length(str) $\rightarrow$ num
lgam() logarithm of absolute gamma function lgam(num) $\rightarrow$ num
ln() natural logarithm ln(num) $\rightarrow$ num
log10() base-10 logarithm log10(num) $\rightarrow$ num
lookup() text lookup lookup(num,str,str,...) $\rightarrow$ str
lookup() numeric lookup lookup(num,num,num,...) $\rightarrow$ num
lower() convert string to lower case lower(str) $\rightarrow$ str
match() string matching match(str,str) $\rightarrow$ num
max() maximum max(num,num,num,...) $\rightarrow$ num
min() minimum min(num,num,num,...) $\rightarrow$ num
nint() round to nearest integer nint(num) $\rightarrow$ num
not() logical NOT not(num) $\rightarrow$ num
number() convert string to number number(str) $\rightarrow$ num
put() put argument on stack put(num) $\rightarrow$ num
puti() define stack index for next put() puti(num) $\rightarrow$ num
rand() random value between 0 and argument rand(num) $\rightarrow$ num
right() right substring right(str,num) $\rightarrow$ str
sign() sign function sign(num) $\rightarrow$ num
Sin() sine function (degrees) Sin(num) $\rightarrow$ num
sin() sine function (radians) sin(num) $\rightarrow$ num
sqrt() square root sqrt(num) $\rightarrow$ num
string() convert number to string string(num) $\rightarrow$ str
string() convert number to string with decimals string(num,num) $\rightarrow$ str
upper() convert string to upper case upper(str) $\rightarrow$ str
which() which among string arguments which(str,str,str,...) $\rightarrow$ num
which() which among numerical arguments which(num,num,num,...) $\rightarrow$ num

Note that all logical and comparison operators return 0 for FALSE and 1 for TRUE. Operands of logical operators are assumed TRUE for all non-zero values, FALSE for zero values.

The available intrinsic functions are shown in Table 3. Note that some functions allow for a variable number of arguments. For technical reasons, the number of arguments for these functions is currently limited to a maximum of 30. Two noteworthy functions of this type are the lookup() and the which() functions. The function lookup( i, v1, v2, v3,...) takes an index i as first argument and returns vi, the i-th of the following values. The function which( v, v1, v2, v3,...) takes a value v as first argument and compares it with the following values vi. It returns the index i of the first match v = vi found, or 0 otherwise.

In addition to operands and operators, an expression may also contain comments enclosed in brackets, e.g. ``[auto network without connectors] isAuto && not(isConnector)''. This is useful to explain the meaning of an expression to those users who are not (yet) Enif experts.

Depending on the context, an expression may allow only a numerical result or also accepts a string result. But even expressions which are limited to numerical results may include string valued subexpressions.

In certain contexts it is possible to specify an expression returning more than a single value. This is done by simply specifying several subexpressions, separated by commas. The maximum allowed number of expressions is given by the particular context. E.g. the expression
volau-volad, volad
provides two values, the auto volumes minus the additional volumes as first value and the additional volumes as second value.

A special case is the empty expression, i.e. an expression with no operands at all. Empty expression will always return a zero value as result.

While the expressions in Enif are much more powerful than those in EMME/2, they remain essentially compatible with EMME/2 expressions. All attributes, operators and intrinsic functions which are available in EMME/2 are also available in Enif.

Expressions are always stored as normal strings, which also implies that they can easily be saved to files and read back when needed. However, when expressions are actually used to provide values, their string representation is automatically compiled into an efficient internal RPN token list. Special cases, such as empty expressions, constants or expressions consisting of a single attribute are recognized as such, so that they can be handled with less overhead. These features allow for a very efficient evaluation of the same expression for large numbers of network elements.

Since the user can enter and modify expressions at any time, it may happen that he or she enters an invalid expression. For this reason, expressions entered or modified interactively by the user are compiled immediately after the return key is pressed. If the expression is found to be invalid, the background of the expression field becomes red (or to be more precise: changes to a special color which is configurable in the user preferences) and the cursor is moved to the place in the expression where the error was detected. If this is not enough to reveal the cause of the error to the user, he can also check on the diagnostic window, where he will find a detailed description of the error.

previous contents next
Previous: Network Attributes and Attribute Lists Next: Element Selectors and Iterators

Enif - Toward a New Interface for EMME/2, Heinz Spiess, October 2000