Skip to content

Language reference

Every construct dpm-xl accepts, with its syntax, meaning, operand and result types, null and interval behaviour, how it treats keyed records, the errors it raises, and examples whose results the test suite computes. The quick reference lists the same constructs on one page; the concept pages explain the semantics in depth.

How to read this page

Syntax notation

Syntax is written in an EBNF in the style of the XML specification:

  • "with" is the text itself; keywords match in any case.
  • expression is another construct, defined on this page.
  • a b is a followed by b; a | b is a or b.
  • a? is an optional a; a* and a+ repeat a zero or more, and one or more times.
  • ( … ) groups.

name is a name, number a number literal, code a table code, alnum a letter or digit, digit a digit, and literal any literal.

Examples and results

The examples run against a small report, built by examples/language_report.py:

Table Layout Values
T rows 0010–0030, columns 0010, 0020 c0010: 100, 60, 40; c0020: 5, -5 and nothing in r0030. Reported with decimals 0, so ±0.5 with interval: true.
U rows 0010–0030, column 0010 1, 2, 3, exact
S row 0010, column 0010, sheets 0001, 0002 7, 8
X row 0010, columns 0010–0040 "LEI-A", [eba_CU:EUR], #2026-06-30#, true
O open, keys qKEY, qDAT; columns 0010, 0020 a, 2026-03-31: 10, EUR; b, 2026-06-30: 20, USD; c, 2026-09-30: 30, JPY
P open, key qKEY; column 0010 b: 2; d: 4

Report parameters: refPeriod = 2026-12-31, Level = "solo", Limit = 5 and the set Allowed = {[CU:EUR], [CU:USD]}. Table group G holds T and U; operation v1 is with {tT, c0010}: {r*} * 2. In the report one year earlier (time_shift(…, A, 1)), T r0010 c0010 is 50.

A result without keys is one value; a keyed result lists its records as key=value, …: value, separated by ;. Numbers are shown in full, with ± tolerance when they carry an interval tolerance; text is quoted and items are in brackets. error: … is an evaluation error (in a keyed result, of that record only), unsupported: … a reference the provider cannot resolve, syntax error: … a syntax error, and no records an empty result. To try an expression of your own:

python examples/language_report.py "sum({tT, c0010, r*})"

Data types

Type Values Literal
number Decimals with 34 significant digits, and a tolerance from reported precision 12, 4.5%
text Character strings "text"
boolean true, false true
date Dates and date-times #2026-12-31#
item A member of a category, category:code [eba_CU:EUR]
set Distinct non-null values {1, 2}
null No value null

integer exists only as a parameter type: a number without a fraction. Each entry below states the types it takes; another type is an evaluation error.

Records, keys and nulls

An operand is a set of records: one value, or one value per key such as r=0010 or qKEY=a. Unless an entry says otherwise:

  • Operators and functions of several operands join their operands on the keys they share, and a key-less operand applies to every record (Operators join on shared keys). Keyed operands must have the same keys, or one operand's keys must include every other's; anything else is the error operands have incompatible keys.
  • An operand with a default stands in for the records it lacks (Defaults fill in missing records).
  • A null operand makes the result null (Null logic). A record whose result is null is not evaluated, never a failure.
  • An evaluation error in one record, such as a division by zero, fails only that record; it is the rule's error only if the record reaches the result (Errors stay in their record).
  • A value passed on unchanged, such as an if branch, the value nvl or filter keeps, or a record that where, sub or rename keeps, keeps its interval tolerance.
  • where, sub, filter, rename, a with context's where and a time_shift of a date key keep their operand's default; the results of get, aggregates and analytic functions have none and join on shared keys only (Defaults fill in missing records).

Errors

Kind When Rule status
Syntax error The text does not parse: DpmXlSyntaxError, with its position error
Evaluation error A wrong type, an unknown table, key or parameter, incompatible keys, a division by zero error
Unsupported The rule needs a provider method the provider lacks, or calls an unknown function unsupported

diagnose finds syntax errors, unknown functions and wrong operand counts without data, and with table layouts also unknown tables, coordinates and keys and operands of the wrong type. Messages may be reworded in minor releases; statuses do not change (Stability).

Lexical structure

Whitespace and comments

Spaces, tabs and line breaks separate tokens and are otherwise ignored outside text literals. The words of group by, partition by, order by, data points and current data point may be separated by any whitespace.

Expressions have no comments. Text rule files skip lines that start with #, but that belongs to the file format.

Case

Keywords, function names, true, false, null and parameter types match in any case. Everything else is case-sensitive: the reference prefixes t g v o p and the axis letters r c s are lower case, the period codes A S Q M W D upper case, and names of temporaries match exactly. Key names in clauses ignore case.

Expression Result
IF TRUE THEN Abs(-1) ENDIF 1
{TT, r0010, c0010} syntax error: unknown selection component 'TT'

Keywords and word boundaries

A word is a letter or _ followed by letters, digits, _ and ., not ending in .. A word is read whole, so a keyword needs whitespace or punctuation between it and a neighbouring word: ornot is one name, not or not, and trueendif is not true endif. A word may directly follow a number (2endif reads 2 endif), and symbols need no spaces (1<2and(true)).

Expression Result
true ornot false syntax error: expected end of expression, found 'ornot'
true or(not false) true
1<2and 2>1 true

diagnose suggests the missing space: did you mean 'or not'?.

Names

name ::= word | "`" character* "`"

A name is a word that is not a reserved word, or any text without backticks between backticks. Names stand for temporaries, report parameters and, inside clauses, key components, and parse to Name. Backticks make a reserved word or text with spaces a name: `to`, `a b`.

The keywords and else endif get group by if in not or over rename sub then to where with xor are reserved everywhere. The window keywords are reserved only inside over (…), default and interval only inside selections, function names only before (, and period codes only where a period is expected; elsewhere they are ordinary names.

Expression Result
Level "solo"
`Level` "solo"
`a.b` := 4; `a.b` + 1 5
range := 2; sum := 3; range * sum 6
to syntax error: unexpected keyword 'to'

Literals

literal ::= number | percentage | text | date | "true" | "false" | "null" | item

Literals are exact values. They parse to Literal_ with kind number, string, date, boolean, null or item (whose value is an Item). Set literals are described with sets.

Numbers

number   ::= digit+ ( "." digit+ )? exponent? | "." digit+ exponent?
exponent ::= ( "e" | "E" ) ( "+" | "-" )? digit+

A decimal, read exactly: 0.1 is one tenth. A number literal has no sign; -3 is unary minus applied to 3. A point needs a digit after it, so 1. is a syntax error. A number whose exponent is outside the decimal128 range (about ±6144) is the syntax error number out of range.

Percentages

percentage ::= ( number | "(" number ")" ) "%"

% after a number literal, possibly in parentheses, divides it by 100. After anything else, such as a name or (1 + 1), it is the syntax error '%' must follow a number, and so is 5%%.

Expression Result
12 12
-3.5 -3.5
.5 0.5
1.5e3 1500
0.1 + 0.2 = 0.3 true
4.5% 0.045
2 * 3 % 0.06
1. syntax error: unexpected character '.'
(1)% 0.01
Limit% syntax error: '%' must follow a number

Text

text ::= '"' character* '"' | "'" character* "'"

Text between double or single quotes, possibly empty, possibly spanning lines. There are no escape sequences: a text cannot contain its own quote, so write "it's" or 'say "yes"'.

Expression Result
"text" "text"
"it's" "it's"
'' ""

Dates

date ::= "#" YYYY "-" MM "-" DD ( "T" hh ":" mm ":" ss )? "#"

A calendar date, or a date-time with a time part, with every digit written. #2026-1-1# and impossible dates such as #2026-02-30# are the syntax error invalid date. A date equals the date-time at its midnight.

Expression Result
#2026-12-31# 2026-12-31
#2026-12-31T10:30:00# 2026-12-31T10:30:00
#2026-12-31# = #2026-12-31T00:00:00# true
#2026-02-30# syntax error: invalid date '2026-02-30'

Booleans and null

true and false are the Boolean values and null the absent value, in any case. Null propagates through most operations (Null logic).

Expression Result
TRUE true
null null
isnull(null) true

Items

item ::= "[" category ":" code "]" | "[" code "]" | "[" "`" code "`" "]"

A member of a DPM category, such as a currency or a country. The category starts with a letter and holds letters, digits, _ and -; the code holds letters, digits, _, . and - and ends in a letter or digit. Spaces may pad the inside of the brackets, but not the :. The second form, a code alone such as [qEBB] or [ei86], is a property or legacy item code.

Items support only = and !=. Two items are equal when their codes match and their categories match, ignoring an eba_ prefix and a category missing on either side: [eba_CU:EUR], [CU:EUR] and [EUR] are equal. Text compared with an item is read as an item.

A [ followed by where, get, sub or rename opens a clause instead.

Expression Result
[eba_CU:EUR] [CU:EUR]
[eba_CU:EUR] = [EUR] true
[CU:EUR] = "eba_CU:EUR" true
[qEBB] [qEBB]
[CU:EUR] < [CU:USD] error: items do not support '<'
[eba_CU : EUR] syntax error: invalid item '[eba_CU : EUR]'

Limits

An expression nests at most 50 levels deep (parentheses, signs, not, if, calls, with bodies and chained clauses count); deeper is the syntax error expression too deeply nested. Arithmetic keeps 34 significant digits.

Programs and statements

program    ::= statement ( ";" statement )* ";"?
statement  ::= name ":=" assigned | assigned
assigned   ::= target "<-" context | context
context    ::= "with" selection ( "[" "where" expression "]" )? ":" context | expression

A rule is one expression. A script is statements separated by ;, run in order; the last statement gives the result and needs no ;. parse reads one expression (a trailing ; is allowed) and parse_program a script, which evaluate_rule also accepts (Statements and assignments). Parses to Program.

Expression Result
x := 1; y := x + 1; y * 10; 20
1;; syntax error: unexpected ';' where an operand is expected

Temporary assignment :=

name ":=" assigned

Evaluates the right side and binds its records, keys included, to name for the statements that follow; the statement's result is that value. A temporary hides a report parameter of the same name, and inside a clause a key component of the same name hides it. Parses to Assignment.

Expression Result
d := {tT, c0010} - {tT, c0020}; d r=0010: 95; r=0020: 65; r=0030: null
Level := 1; Level 1
x := 1; X error: unknown key component or parameter 'X'

Persistent assignment <-

target ::= selection | "{" "v" name "}" | "{" "v_" code "}"

target <- value evaluates the value and returns it in RuleResult.assignments under the target's normalized text, such as {tT, r0010, c0010}. Nothing is written to the report: later statements still read the reported values. The statement's result is the value. Outside clauses <- is always this assignment, so write a comparison with a negative operand as a < -1. A target that is not a selection or {v…} reference is a syntax error. Parses to PersistentAssignment.

Expression Result
{tT, r0010, c0010} <- {tU, r0010, c0010} * 2 2
{tT, r0010, c0010} <- 5; {tT, r0010, c0010} 100
{vTotal} <- sum({tU}) 6

with

"with" selection ( "[" "where" expression "]" )? ":" context

Sets a context for the selections of its body: each takes the context's table, axes, default and interval where it does not write its own. A nested with replaces the components it names. with may start a statement, an assignment's value or another with body; elsewhere, such as in parentheses, it is a syntax error.

The optional where applies, as a where clause, to each selection of the body that has the keys it names. Its and terms that name a key the selection lacks (neither one of its keys nor a temporary or report parameter) leave that selection alone, and a key-less selection takes none of it. A where or sub written on a selection replaces the context condition's terms on the same key (Clauses change keys and records). Parses to With.

Expression Result
with {tT, c0010}: {r0010} + {r0020} 160
with {tT, c0020, default: 0}: {r0030} 0
with {tT, c0020, default: 0}: {r0030, default: 1} 1
with {tT, interval: true}: {r0010, c0010} 100 ± 0.5
with {tT}: with {c0010}: {r0010} 100
with {tO, c0010}[where qKEY = "a"]: {tO} qKEY=a, qDAT=2026-03-31: 10
with {tO, c0010}[where qKEY = "a"]: {c0010}[sub qKEY = "b"] qDAT=2026-06-30: 20
with {tO}[where qKEY = "a"]: {c0010} + {tT, r0010, c0010} qKEY=a, qDAT=2026-03-31: 110
with {tO}[where qDAT > #2026-05-01#]: {c0010} + {tP, c0010} qKEY=b, qDAT=2026-06-30: 22
with {tO}[where qKEY = "a" and r = "0010"]: {c0010} qKEY=a, qDAT=2026-03-31: 10
(with {tT}: {r0010, c0010}) syntax error: unexpected keyword 'with'

Selections

selection ::= "{" component ( "," component )* "}"
component ::= source | axis | "default" ":" default | "interval" ":" ( "true" | "false" )
source    ::= ( "t" | "g" | "o" ) "_"? code
code      ::= ( letter | digit | "_" | "." | "-" )+ | "`" character* "`"

A selection reads cells. Its components are separated by commas, come in any order and appear at most once each (one source, one selector per axis, one default, one interval); a repeated one is a syntax error. The source is written or comes from an enclosing with; without one the selection is the evaluation error selection … has no table. Braces that start with a literal, an item or a signed number are a set literal instead, and {v…} and {p…} braces are references. Parses to Selection holding a SelectionSpec.

Table t

tCode names a table, such as tC_01.00. A _ after t is cosmetic (t_C_01.00 is tC_01.00), and backticks escape other codes: t`C 01.00`. An unknown table is the evaluation error unknown table …. The sources g and o select from a table group or an operation.

Rows, columns and sheets r c s

axis ::= part | "(" part ( "," part )* ")" | ( "r" | "c" | "s" ) "*"
part ::= ( "r" | "c" | "s" ) alnum+ ( "-" ( "r" | "c" | "s" )? alnum+ )?

r, c and s select rows, columns and sheets: one code (r0010), an inclusive range (r0010-0050), a list of codes and ranges on one axis in parentheses ((c0010, c0030-0050)), or every coordinate (r*). Codes hold letters and digits; a range may repeat its axis letter (r0010-r0050). An axis that is not written selects every coordinate on it.

Codes match as DPM numbers them: numeric codes as numbers padded to four digits (r10 is row 0010), others ignoring case. A range is numeric when both ends are numeric and compares text otherwise. A list cannot mix axes or hold *. A coordinate the table lacks selects nothing.

Keys. Each axis that selects more than one coordinate is a key, r, c or s, with the coordinate codes as text; open tables add their key components, such as qKEY (Selections yield records).

Expression Result
{tT, r0010, c0010} 100
{t_T, r10, c10} 100
{tT, c0010} r=0010: 100; r=0020: 60; r=0030: 40
{tT, r0010-0020, c0020} r=0010: 5; r=0020: -5
{tT, (r0010, r0030), c0010} r=0010: 100; r=0030: 40
{tT, r0010, c*} c=0010: 100; c=0020: 5
{tS} s=0001: 7; s=0002: 8
{tS, s0002} 8
sum({tS, r0010, c0010, s*}) 15
{tO, c0010} qKEY=a, qDAT=2026-03-31: 10; qKEY=b, qDAT=2026-06-30: 20; qKEY=c, qDAT=2026-09-30: 30
{tT, r0010, r0020} syntax error: duplicate rows selector
{tT, (r0010, c0010)} syntax error: axis list mixes axes
{tZ, r0010} error: unknown table Z

default

default ::= ( "+" | "-" )? number "%"? | "(" default ")" | text | "true" | "false" | "null" | item | date | set

The value of a selected cell without a fact; without default it is null. A written default, default: null included, also stands in for records that another operand has and the selection lacks (Defaults fill in missing records). The value is a literal, not an expression: default: 1 + 1 is a syntax error. A set is a default only of a set parameter; on a selection it is an evaluation error.

Expression Result
{tT, r*, c0020} r=0010: 5; r=0020: -5; r=0030: null
{tT, r*, c0020, default: 0} r=0010: 5; r=0020: -5; r=0030: 0
{tT, r0030, c0020, default: (-1)} -1
{tO, c0010} + {tP, c0010} qKEY=b, qDAT=2026-06-30: 22
{tO, c0010} + {tP, c0010, default: 0} qKEY=a, qDAT=2026-03-31: 10; qKEY=b, qDAT=2026-06-30: 22; qKEY=c, qDAT=2026-09-30: 30
{tT, c0010, default: {1}} error: a set default applies only to set parameters

interval

interval: true keeps each reported number's tolerance (from its XBRL decimals), so that arithmetic and comparisons use interval arithmetic; interval: false, or no interval, makes the numbers exact. The value is true or false.

Expression Result
{tT, r0010, c0010, interval: true} 100 ± 0.5
{tT, r0010, c0010, interval: true} = 100.4 true
{tT, r0010, c0010} = 100.4 false
{tT, r0010, c0010, interval: 1} syntax error: interval must be true or false

References

reference ::= "{" "v_" code "}" | "{" "v" name "}"
            | "{" "p" "_"? code "," type ( "," "default" ":" default )? "}"

Braces also read report-level data and other rules' results; each kind of reference goes to a provider method (Parameters, operations and table groups).

Filing indicator {v_…}

{v_Code} is true when table or template Code was reported, else false (the provider's table_reported). The _ matters: without it the braces read a report parameter. Usually a precondition. Parses to TableReported.

Expression Result
{v_T} true
{v_Z} false
{v_T} and not {v_Z} true

Report parameter {v…}

{vName} is report parameter Name as the provider gives it, of any type; null when it is missing. Name starts with a letter; backticks escape other names: {v`a b`}. Parses to Parameter.

Expression Result
{vrefPeriod} 2026-12-31
{vLevel} "solo"
{vMissing} null

Bare names

A name reads a temporary or, failing that, the report parameter of that name; inside a clause a key component comes first (Key names). An unknown name is the evaluation error unknown key component or parameter.

Expression Result
refPeriod 2026-12-31
missing error: unknown key component or parameter 'missing'

Typed parameter {p_…}

type ::= "number" | "integer" | "string" | "date" | "boolean" | "item"
       | "set-number" | "set-integer" | "set-string" | "set-date" | "set-boolean" | "set-item"

{p_Name, type} reads report parameter Name and checks its type; a value of another type is the evaluation error parameter … is not …. Text is read as a date or an item for those types, and integer takes whole numbers. A missing parameter takes the default, or is null. A set-… type takes a set of that member type, and its default may be a set literal. The _ after p is cosmetic; the type comes before the default. Parses to TypedParameter.

Expression Result
{p_refPeriod, date} 2026-12-31
{p_Limit, number} + 1 6
{pLimit, integer} 5
{p_Level, string} "solo"
{p_Allowed, set-item} {[CU:EUR], [CU:USD]}
{p_Missing, boolean, default: true} true
{p_Missing, item, default: [CU:EUR]} [CU:EUR]
{p_Missing, set-number, default: {1, 2}} {1, 2}
{p_Missing, set-integer} null
{p_Missing, set-string, default: {"a"}} {"a"}
{p_Missing, set-date, default: {#2026-01-01#}} {2026-01-01}
{p_Missing, set-boolean, default: {true}} {true}
{p_Limit, date} error: parameter Limit is not a date
{p_Limit} syntax error: expected ',', found '}'

Operation {o_…}

"{" "o" "_"? code ( "," ( axis | "default" ":" default | "interval" ":" ( "true" | "false" ) ) )* "}"

Evaluates operation Code, the expression the provider's optional operation(code) method returns, on its own: the referring rule's with context, temporaries and assignments do not reach it. On its result, axes keep the matching r, c and s records, default fills nulls and interval: false makes numbers exact. An operation that refers to itself is an evaluation error; without the provider method the rule is unsupported. Parses to a Selection with spec.operation.

Expression Result
{o_v1} r=0010: 200; r=0020: 120; r=0030: 80
{o_v1, r0010} 200
{o_X} unsupported: operation X needs a provider that resolves operations

Table group {g_…}

{g_Group, …} selects from every table of a group, which the provider's optional table_group(code) method lists. With several tables the records gain the key t, the table code, and the tables must have the same keys for the selection. Without the provider method the rule is unsupported. Parses to a Selection with spec.table_group.

Expression Result
{g_G, r0010, c0010} t=T: 100; t=U: 1
{g_G, r0010} error: the tables of group G have different keys
{g_X, r0010} unsupported: table group X needs a provider that resolves table groups

Operators

Precedence and associativity

From loosest to tightest binding:

Level Operators Associativity Entry
1 ;, :=, <-, with … : statements only Statements
2 or, xor left Logical operators
3 and left Logical operators
4 not prefix; nests (not not x) not
5 =, !=, <>, <, <=, >, >=, in, not in none: one per operand Comparison, in
6 & left Concatenation
7 +, - left Arithmetic
8 *, / left Arithmetic
9 unary +, - prefix; nests (- -x) Unary plus and minus
10 % after a number literal, clauses […] postfix; chain left to right Percentages, Clauses
11 literals, selections, references, names, calls, if … endif, ( … )

Without parentheses not cannot be an operand of a comparison, arithmetic or a sign: 1 = not true and - not x are syntax errors. Comparisons do not chain: a < b < c is a syntax error.

Expression Result
1 + 2 * 3 7
(1 + 2) * 3 9
10 - 4 - 3 3
12 / 4 / 3 1
-2 * -3 6
"a" & "b" = "ab" true
1 + 1 in {2} true
not 1 = 2 true
not true and false false
true or false and false true
true xor true or true true
1 < 2 < 3 syntax error: expected end of expression, found '<'
1 = not true syntax error: unexpected keyword 'not'

Arithmetic + - * /

additive       ::= multiplicative ( ( "+" | "-" ) multiplicative )*
multiplicative ::= unary ( ( "*" | "/" ) unary )*

Addition, subtraction, multiplication and division of numbers.

  • Types: numbers in, a number out; exact decimal arithmetic with 34 significant digits.
  • Null: null if either operand is null.
  • Intervals: tolerances propagate (Arithmetic).
  • Keys: the operands join.
  • Errors: + needs numbers, found …; division by zero when the divisor's value is zero.
  • Node: Binary.
Expression Result
{tT, r0020, c0010} + {tT, r0030, c0010} 100
{tT, c0010} - {tT, c0020} r=0010: 95; r=0020: 65; r=0030: null
{tT, c0010, interval: true} * 2 r=0010: 200 ± 1; r=0020: 120 ± 1; r=0030: 80 ± 1
1 / 3 0.3333333333333333333333333333
1 + null null
1 / 0 error: division by zero
{tT, c0010} / {tT, c0020} r=0010: 20; r=0020: -12; r=0030: null
1 + "a" error: + needs numbers, found string
{tT, r0010} + {tT, c0010} error: operands have incompatible keys (r) and (c)

Unary plus and minus

unary ::= ( "+" | "-" ) unary | postfix

-x negates a number and +x returns it, for each record, keeping its tolerance. Null stays null; another type is the error unary - needs numbers. Parses to Unary.

Expression Result
-{tT, r0010, c*} c=0010: -100; c=0020: -5
- -1 1
-"a" error: unary - needs numbers, found string

Concatenation &

concatenation ::= additive ( "&" additive )*

Joins two texts; null if either is null. Another type is the error & needs text, found …. Binds looser than arithmetic and tighter than comparisons. Parses to Binary.

Expression Result
"LEI" & "-" & "A" "LEI-A"
{tX, c0010} & "/2026" "LEI-A/2026"
"a" & null null
"a" & 1 error: & needs text, found number

Comparison = != <> < <= > >=

comparison ::= concatenation ( ( "=" | "!=" | "<>" | "<" | "<=" | ">" | ">=" ) concatenation )?

Compares two values and yields a Boolean. <> is !=; the node's op is !=.

Operands Comparison
number, number By value; with tolerances as intervals (Comparisons)
text, text By character code
date, date In date order; a date is the date-time at its midnight
boolean, boolean false before true; the text "true", "false", "1" or "0" counts as a Boolean
item, item = and != only, as under Items; text counts as an item
date, text As text
  • Null: null if either operand is null.
  • Keys: the operands join.
  • Errors: cannot compare number with string using '=' and the like for other pairs, sets included; items do not support '<'.
  • Node: Binary.
Expression Result
{tT, r0010, c0010} > {tT, r0020, c0010} true
{tT, c0010} >= 50 r=0010: true; r=0020: true; r=0030: false
"a" < "b" true
#2026-01-01# < #2026-01-02# true
true > false true
{tX, c0040} = "true" true
{tX, c0020} = [CU:EUR] true
1 != 2 true
1 <> 2 true
null = null null
1 = "1" error: cannot compare number with string using '='
{1} = {1} error: cannot compare set with set using '='

in, not in

membership ::= concatenation "not"? "in" concatenation

x in s is true when x equals (=) a member of the set s, so x's interval tolerance applies; x not in s is not (x in s). s is a set literal, a set parameter, a set function, or any other operand, which stands for the set of its non-null values (Sets).

  • Null: null when x is null, or when s is a single null, such as a missing set parameter.
  • Keys: applies to each record of x; the set is not joined.
  • Errors: incompatible types, as for =.
  • Node: In; not in is Unary("not", In(…)).
Expression Result
{tU, c0010} in {1, 3} r=0010: true; r=0020: false; r=0030: true
{tO, c0020} in {p_Allowed, set-item} qKEY=a, qDAT=2026-03-31: true; qKEY=b, qDAT=2026-06-30: true; qKEY=c, qDAT=2026-09-30: false
{tO, c0020} not in {[CU:JPY]} qKEY=a, qDAT=2026-03-31: true; qKEY=b, qDAT=2026-06-30: true; qKEY=c, qDAT=2026-09-30: false
60 in {tT, c0010} true
{tT, r0010, c0010, interval: true} in {100.4} true
null in {1} null
1 in {p_Missing, set-number} null
1 in {} false

not

negation ::= "not" negation | comparison

Negates a Boolean, for each record; null stays null. Another type is the error not needs a boolean. not binds looser than comparisons: not a = b is not (a = b). Parses to Unary.

Expression Result
not {tT, c0010} > 50 r=0010: false; r=0020: false; r=0030: true
not null null
not 1 error: not needs a boolean, found number

Logical operators and or xor

disjunction ::= conjunction ( ( "or" | "xor" ) conjunction )*
conjunction ::= negation ( "and" negation )*

Conjunction, disjunction and exclusive or with three-valued (Kleene) logic: false and null is false and true or null is true; otherwise a null operand makes the result null, and xor with a null is always null. Both operands are always evaluated.

  • Keys: the operands join.
  • Errors: and needs booleans, found ….
  • Node: Binary.
Expression Result
{tT, c0010} > 50 and {tT, c0020} > 0 r=0010: true; r=0020: false; r=0030: false
{v_T} or {v_Z} true
true xor false true
null and false false
null or false null
true xor null null
1 and true error: and needs booleans, found number

if

"if" expression "then" expression ( "else" expression )? "endif"

Chooses a branch by a Boolean condition; a null condition takes the else branch. Without else, a false or null condition yields true when the then branch is Boolean, so that a guarded check passes when its guard does not hold, and null otherwise (Conditionals). if … endif is an operand: it nests and combines with operators.

  • Keys: a key-less condition picks a whole branch. A keyed condition gives one record per condition record, from the matching branch record; branch keys the condition lacks widen it. Defaults on the condition or a branch fill in missing keys (Defaults fill in missing records).
  • Errors: if needs a boolean condition, found …, in the record concerned.
  • Node: If.
Expression Result
if {v_T} then {tT, r0010, c0010} > 0 endif true
if {tT, c0010} > 50 then {tT, c0010} else 0 endif r=0010: 100; r=0020: 60; r=0030: 0
if {tT, c0010} > 50 then {tT, c0020} > 0 endif r=0010: true; r=0020: false; r=0030: true
if {tT, c0010} > 50 then {tT, c0020} endif r=0010: 5; r=0020: -5; r=0030: null
if null then 1 else 2 endif 2
if false then 1 else if false then 2 else 3 endif endif + 1 4
if 1 then 2 endif error: if needs a boolean condition, found number

Clauses

postfix ::= primary ( "%" | clause )*
clause  ::= "[" "where" expression "]"
          | "[" "get" name "]"
          | "[" "sub" name "=" additive "]"
          | "[" "rename" name "to" name ( "," name "to" name )* "]"

A clause follows any operand in brackets, usually a selection or a name. Clauses chain left to right. Inside a clause <- reads < -, so [where qX<-1] compares with -1.

Key names

Names in clauses, group by and over resolve against the operand's keys: exactly, else ignoring case and the DPM 2.0 q prefix, so KEY, key and qkey all find qKEY. A name that matches no key, or several, is read as a temporary or report parameter in where and get, and is an error in sub, rename, group by and over. The keys r, c and s hold coordinate codes as text (r = "0010", not r = 10); open keys hold the values the provider reports, such as text, dates and items.

where

Keeps the records whose keys satisfy a condition. The condition is evaluated for each record, with the record's key components as names, and must yield one Boolean; records where it is false or null are dropped. It tests keys, not values: to test values use filter. The result keeps the operand's default, which stands in for the keys other operands bring (Defaults fill in missing records). A key-less operand is the error where needs a keyed operand. Parses to Where.

Expression Result
{tT, c0010}[where r = "0010"] r=0010: 100
{tT, c0010}[where r in {"0010", "0020"}] r=0010: 100; r=0020: 60
{tO, c0010}[where qDAT > #2026-05-01#] qKEY=b, qDAT=2026-06-30: 20; qKEY=c, qDAT=2026-09-30: 30
{tO, c0010}[where KEY <> "a" and qDAT < #2026-09-01#] qKEY=b, qDAT=2026-06-30: 20
{tO, c0010}[where qDAT<-1] error: cannot compare date with number using '<'
{tT, c0010}[where r = 10] error: cannot compare string with number using '='
{tT, r0010, c0010}[where true] error: where needs a keyed operand
{tO, c0010}[where {tO, c0010} > 10] error: expected a single value, found records keyed by qKEY, qDAT

get

Replaces each record's value by the value of one of its key components, keeping the keys; records whose value is null are dropped, and the result has no default. A name that is not a key reads the report parameter of that name for every record. Parses to Get.

Expression Result
{tO, c0010}[get qDAT] qKEY=a, qDAT=2026-03-31: 2026-03-31; qKEY=b, qDAT=2026-06-30: 2026-06-30; qKEY=c, qDAT=2026-09-30: 2026-09-30
{tT, c0020}[get r] r=0010: "0010"; r=0020: "0020"
{tT, c0010}[get foo] error: unknown key component or parameter 'foo'

sub

Keeps the records whose key component equals a value, compared as with =, and removes that key. The value is an additive expression (a literal, a parameter, an item or arithmetic; parenthesize anything else) with one value. The result keeps the operand's default, as for where. Parses to Sub.

Expression Result
{tO, c0010}[sub qKEY = "a"] qDAT=2026-03-31: 10
{tO, c0010}[sub qKEY = "a"][sub qDAT = #2026-03-31#] 10
{tT, c0010}[sub r = "0010"] 100
{tO, c0010}[sub qKEY = "z"] no records
{tO, c0010, default: 0}[sub qDAT = #2026-09-30#] + {tP, c0010} qKEY=b: 2; qKEY=d: 4
{tO, c0010}[sub foo = 1] error: unknown key component 'foo'

rename

Renames key components, so that operands with different key names join. The old names resolve as key names; the new ones are taken as written. Records, values and the default are unchanged. A new name that is already a key component (also ignoring case and the q prefix), or two pairs with the same new name, is the error rename: key component … already exists; pairs apply in order, so keys cannot be swapped in one clause. Parses to Rename.

Expression Result
{tO, c0010}[rename qKEY to K, qDAT to D] K=a, D=2026-03-31: 10; K=b, D=2026-06-30: 20; K=c, D=2026-09-30: 30
{tP, c0010}[rename qKEY to K] + {tO, c0010}[sub qDAT = #2026-06-30#][rename qKEY to K] K=b: 22
{tO, c0010}[rename foo to K] error: unknown key component 'foo'
{tO, c0010}[rename qKEY to DAT] error: rename: key component qDAT already exists
{tO, c0010}[rename qKEY to X, qDAT to X] error: rename: key component X already exists

Functions

call ::= name "(" ( expression ( "," expression )* )? ")"

A word followed by ( is a call; function names match in any case. Calls parse to Call with the canonical name (canonical_function), except analytic calls. Unless an entry says otherwise, a function applies to each record, joins keyed operands, and is null when an operand is null.

  • Operand counts are checked against SIGNATURES: a wrong count is the error abs takes 1 operand, not 2, and group by in a function that does not aggregate is group by is not allowed in abs.
  • Unknown functions parse, so that rules with newer functions can be read, and evaluate as unsupported: unknown function 'foo'.
Expression Result
ABS(-1) 1
abs(1, 2) error: abs takes 1 operand, not 2
abs(1 group by r) error: group by is not allowed in abs
foo(1) unsupported: unknown function 'foo'

Numeric functions

abs

abs(x): the absolute value of a number, keeping its tolerance. Errors: abs needs numbers, found ….

Expression Result
abs(-3) 3
abs({tT, r*, c0020}) r=0010: 5; r=0020: 5; r=0030: null
abs({tT, r0020, c0020, interval: true}) 5 ± 0.5
abs("x") error: abs needs numbers, found string

exp, ln, sqrt

exp(x), ln(x) and sqrt(x): the exponential, natural logarithm and square root of a number. They are computed in binary floating point, to about 16 significant digits, and the result is exact, without tolerance. A result that is undefined or out of range, such as ln(0) or sqrt(-1), is null. Errors: exp needs numbers, found ….

Expression Result
exp(0) 1
exp(1) 2.718281828459045
ln(1) 0
sqrt(16) 4
sqrt(2) 1.4142135623730951
ln(0) null
sqrt(-1) null
sqrt("a") error: sqrt needs numbers, found string

power

power(base, exponent): base raised to exponent, in binary floating point like exp; null when undefined or out of range.

Expression Result
power(2, 10) 1024
power(2, 0.5) 1.4142135623730951
power(0, -1) null
power(-8, 1 / 3) null

log

log(x, base): the logarithm of x to base, in binary floating point like ln; null outside its domain (x ≤ 0, base ≤ 0 or 1).

Expression Result
log(8, 2) 3
log(100, 10) 2
log(8, 1) null
log(-8, 2) null

max, min

With two or more operands, max(a, b, …) and min(a, b, …) pick the largest or smallest value per record, keeping its tolerance; null if any operand is null. Numbers compare by value; dates, text and items, which cannot be mixed with numbers, by their text (ISO dates in date order). Booleans are an error. With one operand they are aggregates.

Expression Result
max(1, 5, 3) 5
min({tT, c0010}, {tT, c0020}) r=0010: 5; r=0020: -5; r=0030: null
max({tT, c0010}, 50) r=0010: 100; r=0020: 60; r=0030: 50
max(#2026-01-01#, #2026-02-01#) 2026-02-01
max(1, null) null
max(1, "a") error: max cannot compare numbers with dates, text or items

Null functions

isnull

isnull(x): true where x is null, else false; never null. It applies to each record, so it finds the unreported cells of a selection.

Expression Result
isnull({tT, c0020}) r=0010: false; r=0020: false; r=0030: true
isnull(null) true
isnull(0) false

nvl

nvl(x, replacement): x, or replacement where x is null. The operands join, so nvl replaces null values but adds no records; a default on x covers the records x lacks.

Expression Result
nvl({tT, c0020}, 0) r=0010: 5; r=0020: -5; r=0030: 0
nvl(null, "none") "none"
nvl({tO, c0010}, {tP, c0010}) qKEY=b, qDAT=2026-06-30: 20

Text functions

len, length

len(x), also spelled length(x): the number of characters of a text. Other values count the characters of their text form; a number counts as written, without an exponent.

Expression Result
len("abc") 3
length({tX, c0010}) 5
len(12.50) 5
len(null) null

substr

substr(text), substr(text, start) and substr(text, start, length): part of a text. start counts from 1 (default 1) and length, by default the rest, is at least 0; both are whole numbers. Past the end the result is "". Errors: substr needs text, found …, substr start must be at least 1, substr length must not be negative, substr needs whole numbers.

Expression Result
substr("abcdef", 2, 3) "bcd"
substr("abcdef", 3) "cdef"
substr("abcdef", 10) ""
substr("abcdef", 0) error: substr start must be at least 1
substr(123, 1) error: substr needs text, found number

match

match(x, pattern): true when the whole text of x matches the regular expression pattern, in Python re syntax, as if anchored at both ends. Numbers match their text. Errors: match needs a text pattern, invalid match pattern: ….

Expression Result
match({tX, c0010}, "LEI-[A-Z]") true
match("xLEI-A", "LEI-[A-Z]") false
match(2026, "[0-9]{4}") true
match("a", "(") error: invalid match pattern: missing ), unterminated subpattern at position 0

Date functions

year, semester, quarter, month, week, day

The part of a date or date-time, as a number: year, semester (1–2), quarter (1–4), month (1–12), week (the ISO 8601 week, 1–53) and day of the month. Errors: year needs a date, found …; text is not read as a date.

Expression Result
year(#2026-05-31#) 2026
semester(#2026-07-01#) 2
quarter(#2026-05-31#) 2
month({tX, c0030}) 6
week(#2026-01-01#) 1
day(#2026-05-31T10:00:00#) 31
year({tO, c0010}[get qDAT]) qKEY=a, qDAT=2026-03-31: 2026; qKEY=b, qDAT=2026-06-30: 2026; qKEY=c, qDAT=2026-09-30: 2026
year("2026-05-31") error: year needs a date, found string

date

date(year, month, day): the date of three whole numbers. Errors: date needs whole numbers, invalid date: … for a day the month lacks.

Expression Result
date(2026, 2, 28) 2026-02-28
date(2026, 12, 31) = #2026-12-31# true
date(2026, 2, 30) error: invalid date: 2026-02-30

Time functions

time_shift

"time_shift" "(" expression "," period "," expression ( "," name )? ")"
period ::= "A" | "S" | "Q" | "M" | "W" | "D"

time_shift(x, period, count, key) presents x as it was count periods earlier (later when negative): years, semesters, quarters, months, weeks or days. period is an upper-case code and count a whole number.

  • When key is a date key component of x, its values move count periods later within the report, so that each record joins with those of the later date. Months move by calendar months, and a month's last day stays the last day.
  • Otherwise, without key or with a name such as refPeriod that is not a key of x, x is evaluated on the report count periods earlier, from the provider's optional earlier_report(period, count) method; without that report the rule is unsupported.

Errors: time_shift needs a period of A, S, Q, M, W or D, time_shift needs a key name as its fourth operand, time_shift needs dates in key …, and time_shift moves several … dates to … when two records would merge. See Time and Compare with earlier reports.

Expression Result
time_shift({tT, r0010, c0010}, A, 1) 50
{tT, r0010, c0010} - time_shift({tT, r0010, c0010}, A, 1, refPeriod) 50
time_shift({tO, c0010}, Q, 1, qDAT) qKEY=a, qDAT=2026-06-30: 10; qKEY=b, qDAT=2026-09-30: 20; qKEY=c, qDAT=2026-12-31: 30
time_shift({tO, c0010}, S, 1, qDAT) qKEY=a, qDAT=2026-09-30: 10; qKEY=b, qDAT=2026-12-31: 20; qKEY=c, qDAT=2027-03-31: 30
time_shift({tO, c0010}, W, 1, qDAT) qKEY=a, qDAT=2026-04-07: 10; qKEY=b, qDAT=2026-07-07: 20; qKEY=c, qDAT=2026-10-07: 30
time_shift({tO, c0010}, D, -1, qDAT) qKEY=a, qDAT=2026-03-30: 10; qKEY=b, qDAT=2026-06-29: 20; qKEY=c, qDAT=2026-09-29: 30
time_shift({tO, c0010}, M, -1, qDAT) qKEY=a, qDAT=2026-02-28: 10; qKEY=b, qDAT=2026-05-31: 20; qKEY=c, qDAT=2026-08-31: 30
time_shift({tT, r0010, c0010}, Q, 1) unsupported: time_shift needs the report 1 quarter(s) earlier, which the provider does not have
time_shift({tT, r0010, c0010}, a, 1) error: time_shift needs a period of A, S, Q, M, W or D
time_shift({tO, c0010}, A, 1, qKEY) error: time_shift needs dates in key qKEY, found string

annualise

annualise(x, fiscalYearEnd, key) scales a year-to-date amount to a year: x · 12 / months, where months counts the months after the fiscal year's last month (fiscalYearEnd, 1–12) up to and including the month of the date in key. key is a date key component of x, else a date report parameter. The tolerance scales with the amount. Errors: annualise needs a fiscal year end month of 1 to 12, annualise needs a date key or report parameter …, annualise needs a key name as its third operand.

Expression Result
annualise({tO, c0010}, 12, qDAT) qKEY=a, qDAT=2026-03-31: 40; qKEY=b, qDAT=2026-06-30: 40; qKEY=c, qDAT=2026-09-30: 40
annualise(30, 6, refPeriod) 60
annualise(30, 12, Level) error: annualise needs a date key or report parameter 'Level'

Set functions

Each operand of a set function is a set, or any other operand, which stands for the set of its non-null values. A single null operand, such as a missing set parameter, makes the result null; set_of gives {} instead. The result has no keys, and its members keep their first-seen order.

set_of

set_of(x): the set of the non-null values of x.

Expression Result
set_of({tU}) {1, 2, 3}
set_of({tT, c0020}) {5, -5}
set_of(null) {}

union, intersect

union(a, b, …) has the members of any operand; intersect(a, b, …) the members of the first operand that every other operand has. Both take two or more operands.

Expression Result
union({1}, {2}, {1, 3}) {1, 2, 3}
intersect({1, 2}, {2, 3}, {2}) {2}
union({tU}, {tP}) {1, 2, 3, 4}
union({1}, {p_Missing, set-number}) null

setdiff, symdiff

setdiff(a, b) has the members of a that b lacks; symdiff(a, b) the members of exactly one of the two.

Expression Result
setdiff({1, 2}, {2, 3}) {1}
symdiff({1, 2}, {2, 3}) {1, 3}
setdiff({1, 2, 3, 4}, {tU}) {4}

filter

filter(data, condition) keeps the records of data whose condition record is true; a false, null or non-Boolean condition drops the record. The two operands join, so the condition is usually a comparison on the same selection. Unlike where it tests values, not keys. The result keeps data's default, which stands in for the keys other operands bring.

Expression Result
filter({tT, c0010}, {tT, c0010} > 50) r=0010: 100; r=0020: 60
filter({tO, c0010}, {tO, c0020} = [CU:USD]) qKEY=b, qDAT=2026-06-30: 20
count(filter({tT, c0020}, {tT, c0020} > 0)) 1

Sets

Set literals

set ::= "{" "}" | "{" expression ( "," expression )* "}"

Braces whose first member is a literal, an item, a signed number or a parenthesized number are a set; other braces are a selection. Each member is an expression with one value; nulls and duplicates are dropped, and a set cannot contain a set. Sets cannot be compared with = or the other comparisons and cannot be a rule's result (Sets). Parses to SetLiteral.

Expression Result
{1, 2, 2} {1, 2}
{(-5), 3} {-5, 3}
{-5, 1 + 1} {-5, 2}
{[eba_CU:EUR], [eba_CU:USD]} {[CU:EUR], [CU:USD]}
{"a", #2026-01-01#, true, null} {"a", 2026-01-01, true}
{} {}

Sets are tested with in, built with the set functions and read from set parameters.

Aggregates

aggregate ::= ( "sum" | "count" | "avg" | "median" | "max" | "min" | "max_aggr" | "min_aggr" )
              "(" expression ( "group" "by" name ( "," name )* )? ")"

An aggregate reduces an operand's records to one value, or to one value per combination of the group by keys (Key names), skipping null values. Over no records an aggregate is null, except count, which is 0; so is a group whose values are all null. The result has the group by keys, or none, and no default: a key without records is no group (Aggregates).

  • Errors: group by 'qX' is not a key of the operand (r, c); sum needs numbers, found …; max with group by takes 1 operand, not 2.
  • Node: Call with group_by; with over, an analytic function.
Expression Result
sum({tT} group by c) c=0010: 200; c=0020: 0
count({tT} group by r, c) r=0010, c=0010: 1; r=0010, c=0020: 1; r=0020, c=0010: 1; r=0020, c=0020: 1; r=0030, c=0010: 1; r=0030, c=0020: 0
sum({tO, c0010} group by KEY) qKEY=a: 10; qKEY=b: 20; qKEY=c: 30
sum({tT} group by qX) error: group by 'qX' is not a key of the operand (r, c)

sum

The sum of the numbers; their tolerances add up.

Expression Result
sum({tT, c0010}) 200
sum({tT, c0010, interval: true}) 200 ± 1.5
sum({tT, r0030, c0020}) null
sum({tX, c0010}) error: sum needs numbers, found string

count

The number of non-null values, of any type.

Expression Result
count({tT}) 5
count({tT, r0030, c0020}) 0
count({tO} group by c) c=0010: 3; c=0020: 3

avg

The mean of the numbers, with the sum's tolerance divided by the count.

Expression Result
avg({tU}) 2
avg({tT, c0010, interval: true}) 66.66666666666666666666666667 ± 0.5

median

The middle number, or the mean of the two middle numbers; exact, without tolerance.

Expression Result
median({tU}) 2
median({tT, c0020}) 0

max, min, max_aggr, min_aggr

With one operand, max and min are aggregates, also spelled max_aggr and min_aggr, which take exactly one operand. They pick the largest or smallest value, keeping its tolerance. Besides numbers they order dates, text and items by their text (ISO dates in date order, items by category and code), as presence checks expect; Booleans, and numbers mixed with other values, are errors. With several operands max and min are the scalar functions.

Expression Result
max({tU}) 3
min_aggr({tT, c0020}) -5
max_aggr({tO, c0020}) [CU:USD]
max({tO, c0010} group by qKEY) qKEY=a: 10; qKEY=b: 20; qKEY=c: 30
max({tX}) error: max needs numbers, dates, text or items
max_aggr(1, 2) syntax error: max_aggr takes one operand

Analytic functions

analytic  ::= function "(" expression "over" "(" partition? order? window? ")" ")"
function  ::= "rank" | "sum" | "count" | "avg" | "median" | "max" | "min" | "max_aggr" | "min_aggr"
partition ::= "partition" "by" name ( "," name )*
order     ::= "order" "by" name ( "asc" | "desc" )? ( "," name ( "asc" | "desc" )? )*
window    ::= ( "data" "points" | "range" ) "between" bound "and" bound
bound     ::= "unbounded" ( "preceding" | "following" )
            | "current" "data" "point"
            | digit+ period? ( "preceding" | "following" )

An analytic function keeps its operand's records: each gets the aggregate of the records in its window, or its rank, within its partition. partition by and order by name keys of the operand (Key names); without partition by the whole operand is one partition. Without a window the window is the whole partition, or with order by every record up to the current one and its peers. data points windows count records; range windows with an offset need a single number or date order key, and 3 M preceding is three calendar months earlier. The result has no default. The window keywords are reserved only inside over (…) (Partitions, order and windows).

  • Errors: the syntax errors rank needs an order by clause, abs takes no over clause and a window offset is a whole number; sum over 'qX', which is not a key of the operand (r, c); a range window offset needs a number or date order key; a range window with offsets needs one order key.
  • Node: Analytic with a Window.
Expression Result
sum({tU} over ()) r=0010: 6; r=0020: 6; r=0030: 6
sum({tU} over (order by r)) r=0010: 1; r=0020: 3; r=0030: 6
sum({tT} over (partition by c)) r=0010, c=0010: 200; r=0020, c=0010: 200; r=0030, c=0010: 200; r=0010, c=0020: 0; r=0020, c=0020: 0; r=0030, c=0020: 0
avg({tU} over (order by r data points between 1 preceding and current data point)) r=0010: 1; r=0020: 1.5; r=0030: 2.5
sum({tU} over (order by r data points between current data point and unbounded following)) r=0010: 6; r=0020: 5; r=0030: 3
min_aggr({tU} over (order by r desc data points between unbounded preceding and 1 following)) r=0030: 2; r=0020: 1; r=0010: 1
sum({tO, c0010} over (order by qDAT range between 3 M preceding and current data point)) qKEY=a, qDAT=2026-03-31: 10; qKEY=b, qDAT=2026-06-30: 30; qKEY=c, qDAT=2026-09-30: 50
count({tO, c0010} over (order by qDAT asc range between current data point and 1 Q following)) qKEY=a, qDAT=2026-03-31: 2; qKEY=b, qDAT=2026-06-30: 2; qKEY=c, qDAT=2026-09-30: 1
sum({tU} over (order by r range between 1 preceding and current data point)) error: a range window offset needs a number or date order key
abs({tU} over ()) syntax error: abs takes no over clause

rank

rank(x over (partition by … order by …)): the position of each record in its partition by the order keys, from 1; ties share the lowest rank and leave gaps (1, 1, 3). Values do not matter, only keys. rank needs over with order by; a window is ignored.

Expression Result
rank({tU} over (order by r desc)) r=0030: 1; r=0020: 2; r=0010: 3
rank({tT} over (partition by c order by r desc)) r=0030, c=0010: 1; r=0020, c=0010: 2; r=0010, c=0010: 3; r=0030, c=0020: 1; r=0020, c=0020: 2; r=0010, c=0020: 3
filter({tU}, rank({tU} over (order by r)) <= 2) r=0010: 1; r=0020: 2
rank({tU}) syntax error: rank needs an over clause
rank({tU} over (partition by r)) syntax error: rank needs an order by clause

Where dpm-xl differs from the grammar

Some readings differ from the published DPM-XL grammar on purpose, so that EBA rules keep their meaning:

  • not binds looser than comparisons and in: not a = b is not (a = b).
  • Chained comparisons such as a < b < c or a in b in c, - not x, and a selection that repeats an axis, default or interval are syntax errors.
  • Outside clauses <- is the persistent assignment, so compare with a negated operand as a < -b.
  • {v_Code} tests a filing indicator and {vName} reads a report parameter: the _ after v is not cosmetic, unlike after t, g, o and p.
{tT, r0010} < {tT, r0020} < {tT, r0030}
1 in {1} in {true}
- not true
{tT, r0010, r0020}

In the other direction dpm-xl accepts keywords in any case, null and <> anywhere, a last statement without ;, length for len, codes without leading zeros (r310 is row 0310), ranges that repeat the axis letter (r0440-r0480), key names without the q prefix or in another case, item codes without a category ([ei86]), and max and min over dates, text and items.

Every distinct EBA rule and precondition expression of DPM releases 3.4–4.4 parses, except two source expressions with typos (trueendif, ornot), which are reported as syntax errors.

Known limitations

  • No comments, and no escape sequences in text.
  • with only starts a statement, an assignment's value or another with body (with).
  • exp, ln, sqrt, power and log compute in binary floating point and drop the tolerance (exp).
  • A coordinate a table lacks selects nothing rather than raising an error; diagnose with table layouts warns about it.
  • time_shift across reports, {o_…} and {g_…} need optional provider methods; without them a rule is unsupported (Connect your data).
  • The columnar evaluator implements a subset and raises ColumnarUnsupported for the rest, such as scripts, time_shift, analytic functions and most sets.
  • Expressions nest at most 50 deep, and numbers stay within the decimal128 range (Limits).

Index

Every word and symbol of dpmxl.grammar, with its entry. The test suite checks that this index and the grammar module agree.

Name Kind Entry
and keyword Logical operators
else keyword if
endif keyword if
get keyword get
group by keyword Aggregates
if keyword if
in keyword in, not in
not keyword not
or keyword Logical operators
over keyword Analytic functions
rename keyword rename
sub keyword sub
then keyword if
to keyword rename
where keyword where
with keyword with
xor keyword Logical operators
asc window keyword Analytic functions
between window keyword Analytic functions
current data point window keyword Analytic functions
data points window keyword Analytic functions
desc window keyword Analytic functions
following window keyword Analytic functions
order by window keyword Analytic functions
partition by window keyword Analytic functions
preceding window keyword Analytic functions
range window keyword Analytic functions
unbounded window keyword Analytic functions
default selection option default
interval selection option interval
false literal Booleans and null
null literal Booleans and null
true literal Booleans and null
boolean parameter type Typed parameter
date parameter type Typed parameter
integer parameter type Typed parameter
item parameter type Typed parameter
number parameter type Typed parameter
set-boolean parameter type Typed parameter
set-date parameter type Typed parameter
set-integer parameter type Typed parameter
set-item parameter type Typed parameter
set-number parameter type Typed parameter
set-string parameter type Typed parameter
string parameter type Typed parameter
A period time_shift
S period time_shift
Q period time_shift
M period time_shift
W period time_shift
D period time_shift
abs function abs
annualise function annualise
avg function avg
count function count
date function date
day function Date parts
exp function exp, ln, sqrt
filter function filter
intersect function union, intersect
isnull function isnull
len function len, length
length function len, length
ln function exp, ln, sqrt
log function log
match function match
max function max, min
max_aggr function max_aggr, min_aggr
median function median
min function max, min
min_aggr function max_aggr, min_aggr
month function Date parts
nvl function nvl
power function power
quarter function Date parts
rank function rank
semester function Date parts
set_of function set_of
setdiff function setdiff, symdiff
sqrt function exp, ln, sqrt
substr function substr
sum function sum
symdiff function setdiff, symdiff
time_shift function time_shift
union function union, intersect
week function Date parts
year function Date parts
+ operator Arithmetic, unary plus
- operator Arithmetic, unary minus
* operator Arithmetic
/ operator Arithmetic
& operator Concatenation
= operator Comparison
!= operator Comparison
<> operator Comparison
< operator Comparison
<= operator Comparison
> operator Comparison
>= operator Comparison
% operator Percentages
:= operator Temporary assignment
<- operator Persistent assignment
( punctuation Precedence (grouping), calls, axis lists
) punctuation Precedence (grouping), calls, axis lists
[ punctuation Clauses, items
] punctuation Clauses, items
{ punctuation Selections, references, sets
} punctuation Selections, references, sets
, punctuation Selections, calls, sets
: punctuation with, selection options
; punctuation Programs and statements
t reference prefix Table
g reference prefix Table group
v reference prefix Filing indicator, report parameter
o reference prefix Operation
p reference prefix Typed parameter
r axis Rows, columns and sheets
c axis Rows, columns and sheets
s axis Rows, columns and sheets