Language reference

This document describes the syntax and semantics of the custom language used in ransack.

Basic data types

Number

Numbers can be represented as integers, floating-point values, or in scientific notation.

Examples: 27, -15, 3.14, 2e25, 2.15e-17

String

A sequence of characters enclosed in single or double quotes.

Examples: "hello", 'world'

Datetime

Combination of date and time, optionally joined by T.

  • Date: YYYY-MM-DD

  • Time: HH:MM:SS[.fraction][Z|(+|-)HH:MM]

If the time component is omitted, it defaults to midnight.

Examples: 2025-04-11T14:30:00, 2025-04-11 14:30:00Z, 2025-04-11, 2025-04-11T14:30:00+07:00

Timedelta

Represents a time interval. An optional number of days (d or D) may precede the required time component (HH:MM:SS).

Examples: 1D12:00:00, 23:59:59

IPv4 & IPv6

Supports individual addresses, ranges, and CIDR notation.

Examples: 192.168.1.1, 192.168.1.1-192.168.1.100, 192.168.1.0/24 2001:db8::1, 2001:db8::1-2001:db8::ff, 2001:db8::/64

Warning

IP addresses in quotation marks (e.g., "192.168.0.1") are recognized as strings. That is, they are no longer recognized as IP addresses!

Variables

Alphanumeric with optional dots, underscores, or hyphens.

Examples: Source.IP4, .Description

Context

The parser accepts an optional context dictionary at initialization, allowing users to define static variables that can be referenced in queries.

Context variables:

  • Are separate from input data.

  • Take precedence over similarly named data variables.

  • Allow for reusable query logic.

To resolve ambiguity, a prefixing convention is used:

  • Variables prefixed with a dot (e.g., .foo) are explicitly taken from the input data.

  • Variables without a prefix (e.g., foo) are looked up in the context if available.

Example:

ctx = {"threshold": 100}
parser = Parser(context=ctx)
parser.parse("threshold > .load")  # Context variable vs data variable

Functions

Functions use parentheses and comma-separated arguments.

For the full list and documentation of available functions, see ransack.function module.

Functions return either a basic data type or a collection.

Examples: len(Source.IP4), now()

Collections

List

Comma-separated values in square brackets.

Examples: [1, 2, 3.0], [192.168.0.1, 192.168.0.0/24]

Range

Defines an inclusive sequence of numbers, datetimes, or IP addresses.

Examples: 1..1024, 1.0 .. 0, 2025-01-01 .. 2025-12-31

Operators

Arithmetic operators

Operator

Operand Types

Result Type

Description

+

Number + Number

Number

Standard numeric addition

Datetime + Timedelta

Datetime

Adds duration to datetime

Timedelta + Timedelta

Timedelta

Adds two time intervals

-

Number - Number

Number

Standard numeric subtraction

Datetime - Timedelta

Datetime

Subtracts duration from datetime

Timedelta - Timedelta

Timedelta

Subtracts two time intervals

Datetime - Datetime

Timedelta

Time difference between two datetimes

*

Timedelta * Number

Timedelta

Scales a time interval

Number * Number

Number

Standard numeric multiplication

/

Timedelta / Timedelta

Number

Ratio of two time intervals

Number / Number

Number

Standard numeric division

%

Timedelta % Timedelta

Timedelta

Remainder of timedelta division

Number % Number

Number

Standard numeric modulo

  • Basic data type vs. collection: Operation is applied element-wise.

  • Collection vs. collection: Disallowed.

Comparison operators

  • = : Loose equality

  • == : Strict equality

  • > / >= : Greater than / Greater than or equal

  • < / <= : Less than / Less than or equal

Comparisons are valid for numbers, datetimes, timedeltas, and IP addresses.

Collections: True if any element satisfies the comparison.

Comparing two collections is treated as: “Does any element in the left collection match any element in the right collection?”

Warning

The == operator now represents strong equality, in contrast to the older behavior where it also matched elements within collections.

To support collection-aware comparisons, a new = operator has been introduced. This operator returns True if any element in the collection satisfies the comparison — mirroring the behavior of >, >=, <, and <=.

For example:

1 == [1, 2]     # False
1 = [1, 2]      # True

This change promotes consistency across all comparison operators, but be aware that it may lead to different results if you previously relied on == for implicit collection matching.

Special operators

in operator

Tests membership. Returns true if the left-hand element exists in the right-hand side (collection or IP/CIDR range). Recurses into nested collections.

contains operator

String containment check.

Example: "abcdef" contains "abc"True

Warning

"abc" in ["abcdef", "cccabcddd"]False

?? operator

Existence/default fallback operator.

  • Unary: var?? — checks if a variable exists.

  • Binary: var ?? default — returns default if var is not found.

Examples: Description??, foo ?? "default", Source.Port??[]

. (Concatenation)

Used to concatenate strings or merge lists.

Examples: 'abc'.'def' , [1, 2, 3] . [4, 5, 6]

.. (Range)

Defines a range between two values (inclusive).

Examples: 1 .. 13, 1..Source.Port, 192.168.0.1..192.168.0.255

Logical operators

  • and / && : Logical AND

  • or / || : Logical OR

  • not / ! : Logical NOT

Return a boolean.

Evaluation order (precedence)

From highest to lowest:

  1. Parentheses ()

  2. Unary minus -

  3. Existence ??

  4. Multiplicative: *, /, %

  5. Additive: +, -

  6. Concatenation / Range: ., ..

  7. Comparison: =, ==, >, <, >=, <=, in, contains

  8. Logical NOT: !, not

  9. Logical AND: &&, and

  10. Logical OR: ||, or

Examples

(3 + 4) * 2
"tcp" in Source.Proto??[]
not (Format == "IDEA0")
Source.IP4 = 192.168.0.1 or Source.IP4 in 10.0.0.0/8