.. _expr-language-basics: ******************* Expression Language ******************* .. contents:: Contenuti ====== Basics ====== 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 | - | - | +-------------+--------------------------------------------+-------------------------+-----------------------------+ ----------------- Language Literals ----------------- .. _language-strings-and-escaping: ^^^^^^^ 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" | +----------------------+----------------------+ """"""""""""""""""""""" 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 | +--------------------+------------------+--------------+ ^^^^^^^ 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* | +------------+--------+ ^^^^^^^^ 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* | +------------+------------+ ^^^^ 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 | +--------------------------+ -------------------------- 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. -------------------------- 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 --------- 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 --------- Functions --------- Functions are represented by a sequence of alphanumeric characters or **_**. Examples: * power * round * sqrt * substr ----------- Expressions ----------- ^^^^^^^^^ 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 | +--------------------------+---------------+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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*. ^^^^^^^^^^^^^ 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** .. _agent-snmp-sub-expressions: -------------------- 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** ^^^^^^^^^^^^^^^^^^^ 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: * 1.3.6.1.2.1.1.1.0@ * 1.3.6.1.2.1.1.1.0@"mason" * 1.3.6.1.2.1.1.1.0@$node+"1" * 1.3.6.1.2.1.1.1.0@"mason":161 * 1.3.6.1.2.1.1.1.0@$node:$port * 1.3.6.1.2.1.1.1.0:"public"@"mason":161 * 1.3.6.1.2.1.2.(0+2)."1.1.1":$community@$node:($port+0) ^^^^^^^^^^^^^^^ 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. ==================== Special statements ==================== TRY/CATCH statement --------------------- This statement is useful when you need to detect and handle special errors/exceptions execution cases. Read the section :ref:`agent-exception-handling` 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. 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#)