4.1. Expression Language

4.1.1. Basics

4.1.1.1. Supported values types

The language supports many value types. Values can be stored inside variables, used in expressions, passed to/returned by functions, ecc.

Some values have no literal rappresentation in the language. This means that you can create them (es: as a function return value), but you can not rappresent them as a sequence of character in the expression string).

Base values

Types Description Literal rappresentation Example
numbers intergers and floats values number literal 123
booleans true or false values boolean literal True , False
characters A single character string literal “c”, ‘c’
strings sequences of ascii or unicode characters. string literal (ascii characters only) “world”, ‘world’
bytes 8-bit values

Special values used when working with SNMP protocol.

Types Description Literal rappresentation Example
OIDs OID strings (1.3.6.1.2.1.1) OID literal 1.3.6.1.2.1.1.1

Special composite values

Types Description Literal rappresentation Example
arrays Sequence of other values
dictionaries Mapping objects

4.1.1.1.1. Language Literals

4.1.1.1.1.1. Strings

A string is a sequence of characters delimited by single quotes or double quotes:

  • ‘a’, ‘b’, ‘c’
  • “a”, “b”, “c”
  • “foo”, ‘bar’
  • “Hello world”

Character escaping

Few special characters can be inserted into a string by prepending the escape character *.

Escape sequence Character Description
\t   tab
\b   Back Space
\n   new line
\f   line feed
\r   Carriage Return
" double quote
' single quote
\ \ \ backslash

You can use escaped characters inside strings delimited by single (‘)or double quotes (“).

Examples

Input string Value
“Hello\nWorld” Hello World
“Hello ‘World’” Hello ‘World’
‘Hello “World”’ Hello “World”
‘Hello 'World' ‘ Hello ‘World’
“Hello "World"” Hello “World”
4.1.1.1.1.1.1. Disable string escaping

It is possible to disable string escaping by prepending the prefix r to any string.

r

r

Examples

Input string Value Description
“Hello\nWorld” Hello World  
“Hello\World” Hello\World  
“Hello"World” Hello”World  
r”Hello\nWorld” Hello\nWorld unescaped
r”Hello\nWorld” Hello\nWorld unescaped
r”Hello"nWorld” Hello"World unescaped
4.1.1.1.1.2. Numbers

Numbers can be expressed as:

Integer values

Sequence of decimal characters starting with a decimal.

Examples:

expression value
1 1
-1982 -1982

Floating point values

They follow the following sintax:

integer part . decimal part [ (e | E) ( - | + ) exponent ]

Examples:

expression value
1.0 1.0
3.14 3.14
4.0e+10 40000000000.0
1.0E-3 0.0001

Hexadecimals values

Sequence of hexadecimal characaters with the prefix 0x.

Examples:

expression value
0x1 1
0xff 255
0xFF 255
0x80000 32768

Octal values

Sequence of octal characters startring with 0.

Examples:

expression value
01 1
07 7
010 8
011 9
4.1.1.1.1.3. Booleans

Booleans values can be true or false. These values are represented by the constants: True or False.

Example:

Expression Value
True true
False false
4.1.1.1.1.4. OIDs

When speaking about SNMP, OIDs (or Object Identifiers) uniquely identify managed objects in a MIB hierarchy.

They are expressed with a sequence of at least three decimal strings separated by a dot “.”.

IMPORTANT: An OID are a special kind of literal and can be used only inside SNMP sub-expression. You can not use OID literals inside mathematical expressions or comparisons.

Examples:

Expression
1.2.3
1.3.6.1.2.1.1.1.18.241

4.1.1.1.2. Vectors

Vectors are sequence values. Functions and variables can be used to handle vectors and the sintax to access vector elements is:

*expression* [ *index* ]

Example:

"hello world"[0] --> 'h'

my_function_returns_a_vector()[1] --> second value of the returned vector

Note

Strings are vectors or characters.

4.1.1.1.3. Dictionaries

A dictionary is an hashtable, a mapping object that maps values to arbitrary objects.

Functions and variables can be used to handle vectors and the sintax to access vector elements is:

*expression* [ *key* ]

Example:

my_function_returns_a_dictionary()["key1"]  --> value for the key "key1"
my_function_returns_a_dictionary()[1]       --> value for the key 1

4.1.1.1.4. Variables

A variable is represented by a initial $ followed by a sequence of alphanumeric characters or _.

Every variable has a value. The value can be a string, a number, a boolean, ecc.

Examples:

  • $foo
  • $BAR
  • $_
  • $foo_Bar

4.1.1.1.5. Functions

Functions are represented by a sequence of alphanumeric characters or _.

Examples:

  • power
  • round
  • sqrt
  • substr

4.1.1.1.6. Expressions

4.1.1.1.6.1. Operators

The language supports the following operators:

Arithmetical

Operator Meaning
a + b sum
a - b subtraction
a / b division
a % b module division
a * b multiplication
+a positive
-a negative

Comparison

Operator Meaning
a == b , a eq b  
a != b  
a =~ b a matches regular expression represented by b
a < b  
a <= b  
a > b  
a >= b  

BIT operators

Operator Meaning
a & b bit and
a | b bit or
a ^ b bit xor
~a one’s complement

Logical operators

Operator Meaning
a && b , a and b and
a || b , a or b or
!a , not a not
4.1.1.1.6.2. Operators precedence

Operators listed in descening precedence.

Operators Description
(), [] Call operator and range operator
+,-,~,!,not unary operator ( +10, -30, !b, not b)
||, or  
&&, and  

 
^  
&  
==, !=, ~= , eq  
<, <=, >, >=  
*  
*, /, %  
+, -  

Warning

binary logical operators (|, &&, and, or) and binary bit operators (&, |, ^) are not short-circuited.

4.1.1.1.6.3. Function call

This is the syntax for function call:

function name ( [ param , param , …. ] [, name = param , name = param ] )

You can specify simple parameters, also called positional parameters, and named parameters.

All named parameters can be specified in any order, but must appear after any other positional parameter.

Not all functions support named parameters. Read functions’ documentation for more details.

Examples:

myfunction1()

myfunction2( 10 )

myfunction2( "Hello", 'World', 42 )

myfunction3( "Hello", 'World', 42 , timeout=10, shorttries=(3+2))

myfunction4(timeout=10)

myfunction5(probesize=1472, "localhost")  **WRONG PARAMETERS SEQUENCE**

4.1.1.1.7. SNMP Sub-expressions

An SNMP sub-expression, or simply SNMP expression, is a special syntax element of the language.

It is used to reference (and retrieve) the value of a managed object (OID) in the MIB hierarchy.

There are two kind of SNMP expressions and they reppresent two kind of values:

  • Current SNMP value
  • Old SNMP value
4.1.1.1.7.1. Current snmp values

These expressions reppresent the current value of an OID. When the SNMP expression is evaluated the value is read from the network throw SNMP protocol.

The syntax is:

OID subexpr [ : snmp community subexpr ] @ [ node name subexpr [ : snmp subexpr ] ]

Where:

OID subexpr is an expression returning the desired OID. It must have the following sintax:

*OID literal* [ **.** *expression>* [ **.** .... ] ]

Where expression can be any expression representing string or number.

snmp community subexprrr: expression returning the SNMP community name.

node name subexprrr: expression returning the node name.

snmp subexpr: expression returning the used SNMP port number.

If snmp community subexpr, node name subexpr or snmp subexpr are missing, the default value is taken from the execution context.

The execution context is a set of variables created when the expression evaluation starts. This is a SANET related topic and will be explained later in this document.

parameter context’s variable name
snmp community subexpr $community
node name subexpr $node
snmp subexpr $snmpport

Examples:

4.1.1.1.7.2. Old snmp values

The syntax is:

OID subexpr [ : snmp community subexpr ] # [ node name subexpr [ : snmp subexpr ] ]

These sub-expressions represent the previous value of a managed object inside a MIB.

The term previous value means the value read throw SNMP the last time the expression containing the SNMP sub-expression was evaluated.

This is a SANET related topic and will be explained later in this document.

4.1.2. Special statements

4.1.2.1. TRY/CATCH statement

This statement is useful when you need to detect and handle special errors/exceptions execution cases.

Read the section Gestione delle eccezioni nei controlli for more details about known and unknown exceptions types.

The syntax is:

try expression1 catch exception name1 ( expression2 )

When an exception of the specified type expression name1 is raised, the returned value is the value for expression2.

Examples:

try 1 + 1                    catch ValueError (666)                  ->  2

try 1.3.6.1.2.1.1.1.0@       catch ValueError (666)                  -> Linux debiantest 3.2.0-3-486 #1 Thu Jun 28 08:08:24 UTC 2012 i686

try 1/0                      catch ZeroDivisionError (666)           -> 666

try 1/0                      catch TimeoutException (666)            -> *EXCEPTION* -> *UNCHECKABLE*

try 1.3.6.1.2.1.1.1.2.3.4.5@ catch UndefinedSnmpValueException (666) -> 666

try 1.3.6.1.2.1.1.1.2.3.4.5@ catch TimeoutException (666)            -> *EXCEPTION* -> *UNCHECKABLE*

Danger

This statement will catch every exception:
try ..... catch Exception ( ... )

You SHOULD NEVE USE this statement, UNLESS YOU ARE REALLY SURE your expressions never raise dangerous exceptions.

You can omit the expression2 part:

try expression1 catch exception name1 ( )

Executes expression1 and returns the calculated value.

When an exception of the specified type expression name1 is raised, the returned value is a string with the exception description.

Examples:

try 1 + 1                    catch ValueError ()                  ->  2

try 1.3.6.1.2.1.1.1.0@       catch ValueError ()                  -> Linux debiantest 3.2.0-3-486 #1 Thu Jun 28 08:08:24 UTC 2012 i686

try 1/0                      catch ZeroDivisionError ()           -> ZeroDivisionError:division 1 / 0.0division 1 / 0.0
try 1/0                      catch TimeoutException ()            -> *EXCEPTION* -> *UNCHECKABLE*

try 1.3.6.1.2.1.1.1.2.3.4.5@ catch UndefinedSnmpValueException () -> 666
try 1.3.6.1.2.1.1.1.2.3.4.5@ catch TimeoutException ()            -> UndefinedSnmpValueException:Current variable 1.3.6.1.2.1.1.1.2.3.4.5:public@localhost:161 can't be read or is not present (GET)

Danger

This statement will catch every exception:

try ..... catch Exception ()

You SHOULD NEVE USE this statement, UNLESS YOU ARE REALLY SURE your expressions never raise dangerous exceptions.

You can omit the exception name:

try expression1 catch ( expression2 )

Executes expression1 and returns the calculated value.

When any exception is raised, the returned value is the value calculated by expression2.

Warning

any exception raised by expression2 is not catched.

Examples:

try 1 + 1                    catch (666)    ->  2

try 1.3.6.1.2.1.1.1.0@       catch (666)    -> Linux debiantest 3.2.0-3-486 #1 Thu Jun 28 08:08:24 UTC 2012 i686

try 1/0                      catch (666)    -> 666

try 1.3.6.1.2.1.1.1.2.3.4.5@ catch (666)    -> 666

Danger

You SHOULD NEVE USE this statement, UNLESS YOU ARE REALLY SURE your expressions never raise dangerous exceptions.

You can omit both exception name and secondary expression:

try expression1 catch ( )

Executes expression1 and returns the calculated value.

When any exception is raised, the returned value is a string with the exception’s description.

Example:

try 1 + 1                    catch ()    ->  2

try 1.3.6.1.2.1.1.1.0@       catch ()    -> Linux debiantest 3.2.0-3-486 #1 Thu Jun 28 08:08:24 UTC 2012 i686

try 1/0                      catch ()    -> ZeroDivisionError:division 1 / 0.0division 1 / 0.0

try 1.3.6.1.2.1.1.1.2.3.4.5@ catch ()    -> UndefinedSnmpValueException:Current variable 1.3.6.1.2.1.1.1.2.3.4.5:public@localhost:161 can't be read or is not present (GET)

Danger

You SHOULD NEVE USE this statement, UNLESS YOU ARE REALLY SURE your expressions never raise dangerous exceptions.

4.1.2.2. IF statement

The syntax is:

if expression1 then expression2 else expression3

The statement calculate the value for the expression1. If the computed value is true, expression2 is calculated, otherwise expressione3.

Example:

if 1 + 1 >= 2                            then "Hello"             else "Goodbye"

if try 1.3.6.1.2.1.1.1.10@ catch (False) then  1.3.6.1.2.1.1.1.0@ else "Goodbye"

Attention

this statement is dangerous when used with Old snmp values. If you do not write your statement properly, some SNMP variables could never be fetched.

if 1 + 1 >= 2 then 1.3.6.1.2.1.1.2.3.4.0# else (1.3.6.1.2.1.1.2.3.4.0@ - 1.3.6.1.2.1.1.2.3.4.0#)