Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Expressions

Expressions in Structured Text combine variables, literals, operators, and function calls to produce values. This chapter covers operator precedence, grouping with parentheses, and using function calls within expressions.

Operator Precedence

Operators are listed from highest to lowest precedence. Operators on the same row have equal precedence and are evaluated left-to-right.

PrecedenceOperator(s)Description
1 (highest)**Exponentiation
2- (unary), NOTNegation, bitwise/logical NOT
3*, /, MODMultiplication, division, modulo
4+, -Addition, subtraction
5<, >, <=, >=Relational comparisons
6=, <>Equality, inequality
7AND, &Logical/bitwise AND
8XORLogical/bitwise XOR
9 (lowest)ORLogical/bitwise OR

When in doubt, use parentheses to make intent explicit.

Arithmetic Operators

Standard arithmetic works on numeric types (ANY_NUM):

VAR
  a, b, result : INT;
END_VAR

a := 10;
b := 3;

result := a + b;    // 13
result := a - b;    // 7
result := a * b;    // 30
result := a / b;    // 3 (integer division)
result := a MOD b;  // 1

Exponentiation

The ** operator raises the left operand to the power of the right operand:

VAR
  x : REAL;
END_VAR

x := 2.0 ** 10.0;   // 1024.0
x := 3.0 ** 0.5;    // square root of 3

Unary Negation

VAR
  speed : REAL := 50.0;
  reverse_speed : REAL;
END_VAR

reverse_speed := -speed;  // -50.0

Comparison Operators

Comparisons return BOOL:

VAR
  temp    : REAL := 85.0;
  too_hot : BOOL;
  in_range: BOOL;
END_VAR

too_hot  := temp > 100.0;
in_range := (temp >= 60.0) AND (temp <= 100.0);

The full set:

OperatorMeaning
=Equal to
<>Not equal to
<Less than
>Greater than
<=Less than or equal
>=Greater than or equal

Note that = is the equality comparison operator, not assignment. Assignment uses :=.

Logical and Bitwise Operators

AND, OR, XOR, and NOT operate on BOOL values (logical) or bit-string types (bitwise), depending on the operand types:

VAR
  a, b   : BOOL;
  result : BOOL;
END_VAR

result := a AND b;
result := a OR b;
result := a XOR b;
result := NOT a;

The & symbol is an alternative for AND:

result := a & b;  // same as a AND b

Bitwise example

VAR
  flags  : WORD := 16#FF00;
  mask   : WORD := 16#0F0F;
  masked : WORD;
END_VAR

masked := flags AND mask;  // 16#0F00

Parentheses

Parentheses override the default precedence:

VAR
  a : INT := 2;
  b : INT := 3;
  c : INT := 4;
  r : INT;
END_VAR

r := a + b * c;     // 14  (multiplication first)
r := (a + b) * c;   // 20  (addition first)

A practical example – checking a sensor range with debounce:

VAR
  pressure     : REAL;
  pump_active  : BOOL;
  override     : BOOL;
  should_run   : BOOL;
END_VAR

should_run := (pressure < 50.0 OR override) AND NOT pump_active;

Without parentheses this expression would bind differently due to AND having higher precedence than OR. Always parenthesize mixed AND/OR expressions.

Function Calls in Expressions

Functions that return a value can be used directly inside expressions:

FUNCTION ABS_REAL : REAL
  VAR_INPUT
    x : REAL;
  END_VAR
  IF x < 0.0 THEN
    ABS_REAL := -x;
  ELSE
    ABS_REAL := x;
  END_IF;
END_FUNCTION

PROGRAM Main
  VAR
    error    : REAL := -3.5;
    clamped  : REAL;
  END_VAR

  // Function call as part of a larger expression
  clamped := ABS_REAL(x := error) * 2.0 + 1.0;
  // result: 8.0
END_PROGRAM

Nested function calls are also valid:

VAR
  angle : REAL;
  dist  : REAL;
END_VAR

dist := SQRT(SIN(angle) ** 2.0 + COS(angle) ** 2.0);
// Always 1.0, but demonstrates nesting

Precedence in Practice

Consider a PID error calculation:

VAR
  setpoint     : REAL := 100.0;
  measured     : REAL := 95.0;
  deadband     : REAL := 2.0;
  error        : REAL;
  needs_action : BOOL;
END_VAR

error := setpoint - measured;
needs_action := error > deadband OR error < -deadband;

Because > and < bind tighter than OR, this evaluates as:

(error > deadband) OR (error < -deadband)

which is the intended behavior. Still, explicit parentheses make the intent clearer for anyone reading the code.

Common Pitfalls

Confusing = and :=. The single = is comparison, not assignment. Writing x = 5 in an IF condition compares; writing x := 5 assigns.

Integer division truncates. 7 / 2 yields 3, not 3.5. Use REAL operands for fractional results: 7.0 / 2.0 yields 3.5.

MOD with negative operands. The sign of the result follows the dividend: -7 MOD 3 yields -1.

NOT precedence. NOT a AND b means (NOT a) AND b, not NOT (a AND b). Parenthesize when in doubt.