Table of Contents

Operators

Expressions can be combined using operators, each with a specific precedence priority. The precedence rules determine the order in which operations are performed in an expression. Below is a list of operator precedence in descending order:

  1. Primary
  2. Factorial
  3. Percent
  4. Exponential
  5. Unary
  6. Multiplicative
  7. Additive
  8. Relational
  9. Logical

Handling of null values

In some cases, null values can appear in expressions. If the TreatNullAsZero flag in ExpressionOptions is set, nulls are converted to zeros for all operations except for comparison and matchiing; for the latter operations, null takes place in comparison/matching. If TreatNullAsZero is not set and null is found in one of the values, null is immediately returned without evaluating the expression.

Primary

Primary are the first thing to be evaluated. They are direct values or a list of them.

Values

Values include literals that are used in expressions.

Examples:

42
"hello"
true

Lists

Lists are used to group expressions.

Examples:

2 * (3 + 2)
"foo" in ("foo", "bar", 5) 
secret_operation("my_db", 2) // Function arguments are actually a list!

Indexed Access to Lists and Strings

If an expression evaluates to a list or a string, an element or a range of elements of this list or string can be accessed using an index operator, where the index or the range may also be an expression or expressions. The C# "from end" syntax using a caret (^) is also supported. Any boundary of the range may be omitted.

Examples:

(1; 2; 3)[1] // produces 2
'abcd'[1] // produces 'b'
(1; 2; 3)[1..2] // produces 2
(1; 2; 3)[0..2] // produces (1; 2)
'abcd'[1..3] // produces "bc"
'abcd'[^2..^1] // produces "bc"
'abcd'[..^1] // produces "abc"
'abcd'[2..] // produces "cd"
'abcd'[..] // produces "abcd"

If an expression is a parameter (variable) that contains a list or a string, it is possible to update one of its elements using the index operator with an integer index (it is not possible to update the range at the moment):

a := "abcd"; a[0] := "X" // single-character strings work like chars in this type of assignment
a := (1; 2; 3); a[1] := 'Y' // this is possible as our lists are lists of objects

Factorial

Factorial ('!') is a special post-operator that is applicable to a value or expression that evaluates to an integer value. The resulting expression is binary, and the number of exclamation marks determines the type of factorial (standard, double, triple etc.).

  • !: standard factorial
  • !!: double factorial
  • !!!: triple factorial
  • !....!: some multifactorial

Example:

(1+2)!
20!!!

Percent

Percent is a post-operator that alters the way the operand is interpreted. A percent value is marked with a % character placed after a numeric value or expression.

Percent calculations must be enabled via the AdvancedOptions property of the ExpressionBase class. When percent calculations are enabled, the % character is used for them, and mod is used for modulo division.

Example:

(1+2)%
5% + 2%
100 * 5%
200 + 10%
200 - 5%

If the result of an operation is percent, an instance of Percent is returned as a result of the expression evaluation.

Exponential

Exponential operators perform exponentiation.

Example:

2 ** 2
2 ^ 3

When Unicode Characters are enabled for operations using the UseUnicodeCharsForOperations flag in ExpressionOptions, the following operations are also supported:

  • (U+2291): Exponentiation

Unary

Unary operators operate on a single operand.

Examples:

not true
!(1 != 2)

When Unicode Characters are enabled for operations using the UseUnicodeCharsForOperations flag in ExpressionOptions, the following operations are also supported:

  • ¬ (U+00AC) : Logical NOT
  • (U+221A) : Square root
  • (U+221B) : Cube root
  • (U+221C) : Fourth root

Examples:

√4
∜(4*4)

Multiplicative

Multiplicative operators perform multiplication, division, and modulus operations.

  • * : Multiplication
  • / : Division
  • // : Integer Division (Python-like - division may be performed on floating-point operands, and the result is truncated)
  • \\ : Integer Division (Basic-like - floating-point operands are truncated first)
  • div : Integer Division (Basic-like - floating-point operands are truncated first)
  • % : Modulus (when percent calculation is disabled)
  • mod : Modulus (when percent calculation is enabled in AdvancedExpressionOptions)

If floating-point values are passed to the modulus operation, they are truncated before the operation.

When Unicode Characters are enabled for operations using the UseUnicodeCharsForOperations flag in ExpressionOptions, the following operations are also supported:

  • × (U+00D7) : Multiplication
  • (U+2219): Multiplication
  • : : Division
  • ÷ (U+00F7) : Division

When assignments are enabled using the UseAssignments flag in ExpressionOptions, the following operations are also supported:

  • *= : Multiplication with assignment of the result to the left operand
  • /= : Division with assignment of the result to the left operand

When Unicode characters are enabled, they can also be used for multiplication with assignment and division with assignment.

Example:

1 * 2 % 3

The non-AOT version of NCalc can perform multiplication, division, and modulus operations on any types which have these operations defined (overloaded). This includes non-numeric types. The AOT version can handle only numbers (including BigInteger and BigDecimal) and multiplication and division of TimeSpan values by numbers.

Additive

Additive operators perform addition and subtraction.

  • + : Addition
  • - : Subtraction

Example:

1 + 2 - 3

When Advanced Value Formats and Operations are used and time operations are enabled, it is possible to add a time value (Timespan) to a date or another time value. Also, it is possible to subtract a time value from another time value or a time value from a date or a date from a date.

When assignments are enabled using the UseAssignments flag in ExpressionOptions, the following operations are also supported:

  • += : Addition with assignment of the result to the left operand
  • -= : Subtraction with assignment of the result to the left operand

The non-AOT version of NCalc can perform addition and subtraction operations on any types which have these operations defined (overloaded). This includes non-numeric types. The AOT version can handle numbers (including BigInteger and BigDecimal), dates and times (where the operations make sense), char variables and addition of strings.

Relational

Relational operators compare two values and return a boolean result.

Equality and Inequality Operators

These operators compare two values to check equality or inequality.

  • =, == : Equal to
  • !=, <> : Not equal to

Examples:

42 == 42            // true
"hello" == "world"  // false
10 != 5             // true
"apple" != "apple"  // false

When Unicode Characters are enabled for operations using the UseUnicodeCharsForOperations flag in ExpressionOptions, the following operations are also supported:

  • (U+2260) : Not equal to

Comparison Operators

These operators compare two values to determine their relative order.

  • < : Less than
  • <= : Less than or equal to
  • > : Greater than
  • >= : Greater than or equal to

Examples:

3 < 5          // true
10 <= 10       // true
7 > 3          // true
8 >= 12        // false

When Unicode Characters are enabled for operations using the UseUnicodeCharsForOperations flag in ExpressionOptions, the following operations are also supported:

  • (U+2264) : Less than or equal to
  • (U+2265) : Greater than or equal to

When an attempt is made to compare the values that are not compatible (e.g., a string and a number), the outcome depends on whether the CompareIncompatibleTypes flag is set in ExpressionOptions. If it is set, false is returned; otherwise, an exception is thrown.

IN and NOT IN

The IN and NOT IN operators check whether a value is present or absent within a specified collection or string.

  • IN : Returns true if the left operand is found in the right operand (which can be a collection or string).
  • NOT IN : Returns true if the left operand is not found in the right operand.

When Unicode Characters are enabled for operations using the UseUnicodeCharsForOperations flag in ExpressionOptions, the following operations are also supported:

  • (U+2208) : Returns true if the left operand is found in the right operand (which can be a collection or string).
  • (U+2209) : Returns true if the left operand is not found in the right operand.

The right operand must be either a string or a collection (IEnumerable).

Examples:

'Insert' IN ('Insert', 'Update')          // True
42 NOT IN (1, 2, 3)                       // True
'Sergio' IN 'Sergio is at Argentina'      // True
'Mozart' NOT IN ('Chopin', 'Beethoven')   // True
945 IN (202, 303, 945)                    // True
945 ∈ (202, 303, 945)                     // True

LIKE and NOT LIKE

The LIKE and NOT LIKE operators compare a string against a pattern.

  • LIKE : Checks if the string matches the specified pattern.
  • NOT LIKE : Checks if the string does not match the specified pattern.

Default matching uses RegEx and is used unless an application handles the MatchString event of Expression or AsyncExpression and returns the result of matching. This event is fired before the default matching, allowing applications to override the default matching mechanism.

With default matching, patterns can include:

  • % to match any sequence of characters.
  • _ to match any single character.

Examples:

'HelloWorld' LIKE 'Hello%'     // True
'Test123' NOT LIKE 'Test__'    // False
'2024-08-28' LIKE '2024-08-__' // True
'abc' LIKE 'a%'                // True

Logical

Logical operators perform logical comparisons between expressions.

  • or, || : Logical OR
  • and, && : Logical AND
  • xor : Logical XOR

Examples:

true or false and true    // Evaluates to true
(1 == 1) || false        // Evaluates to true

Note: The and operator has higher priority than the or or xor operator. Hence, in the example above, false and true is evaluated first.

When Unicode Characters are enabled for operations using the UseUnicodeCharsForOperations flag in ExpressionOptions, the following operators are also supported:

  • (U+2228) : Logical OR
  • (U+2229) : Logical AND
  • (U+2295) : Logical XOR
  • (U+22BB) : Logical XOR

Bitwise

Bitwise operators perform bitwise operations on integers.

  • << : Left shift
  • >> : Right shift

By default, when the SkipLogicalAndBitwiseOpChars flag is not set in ExpressionOptions, the following operator symbols are used:

  • | : Bitwise OR
  • & : Bitwise AND
  • ^ : Bitwise XOR

Example:

2 >> 3

When the SkipLogicalAndBitwiseOpChars flag is set in ExpressionOptions, the following operators are used:

  • BIT_OR : Bitwise OR
  • BIT_AND : Bitwise AND
  • BIT_XOR : Bitwise XOR

When assignments are enabled using the UseAssignments flag in ExpressionOptions, the following operations are also supported (regardless of the SkipLogicalAndBitwiseOpChars flag):

  • &= : Bitwise AND with assignment of the result to the left operand
  • |= : Bitwise OR with assignment of the result to the left operand
  • ^= : Bitwise XOR with assignment of the result to the left operand