Skip to content

Literal

MaartenHilferink edited this page Sep 16, 2026 · 1 revision

A literal is a value written directly in a calculation rule: a number such as 42, 2.5 or 1000f, or a string such as 'Amsterdam'. Literals are one of the three kinds of expression elements, next to operator and function applications and references to other tree items. Every numeric literal has a value type, which the notation determines: an unadorned integer is a uint32, an unadorned real is a float64, and a suffix selects any other type or a values unit.

numeric literals

the two forms

  • An integer literal is a sequence of decimal digits: 0, 42, 1000000. Its value type is uint32.
  • A real literal contains a decimal point or an exponent: 2.5, .5, 5., 1e3, 15e-1, 2E2. Its value type is float64. A number without a point or exponent is never a real: 1000 is a uint32, 1000.0 and 1e3 are float64.
  • A hexadecimal literal is a percent sign followed by hexadecimal digits, in either case: %FF and %ff are 255. Its value type is uint32 like a decimal integer, and a suffix applies in the same way. A suffix that starts with a letter that is also a hexadecimal digit (b, c, d, f) is read as more digits: %1Fb is 507, not the uint8 value 31; write uint8(%1F) or 31b instead.

The digits are read as an unsigned number. There is no negative literal: -1 is the negation operator applied to the literal 1, and negation of an unsigned value results in the signed type of the same width, so -1 is an int32, -1b an int8 and -1.5 a float64.

An integer literal must fit the uint32 range. Up to 4294967295 is accepted, but note that 4294967295 is the null value of uint32, so uint64(4294967295) is null. From 4294967296 on the parser reports Cannot convert 4294967296 to UInt32, consider adding the suffix u64 or i64, and with that suffix the full 64 bits range is available (since the GeoDMS 9.0 series; before, such a literal was rejected whatever its suffix).

suffixes

A suffix is written directly after the digits, without a space, and gives the literal another value type. It is shorthand for the conversion function of that type: 1000f is float32(1000), and because it is a conversion, 2.7u is uint32(2.7), which is 2.

Since GeoDMS 20.21.0 the suffixes in the table below are case sensitive and are written in lower case: 4.5f is a float32, 4.5F is not. Up to 20.20.0 they were case insensitive, and the letters d, f, u, i, w, s, b and c were registered as names in the same case-folded namespace as every item name, so a configuration that named a unit W, a container C or a function type parameter D reported a case mix-up against the suffix letter on every run. A suffix is now recognised as text and is not a name at all; those item names are free. An upper-case suffix is read the way any other name after a number is, as a values unit (see below), and fails as an unknown identifier when no such unit exists: 60D used to be 60d, write 60d.

value type suffix also example
uint8 b u8 200b
uint16 w u16 1000w
uint32 u u32 42u, the same as 42
uint64 u64 4294967296u64
int8 c i8 -100c
int16 s i16 7s
int32 i i32 42i
int64 i64 -5000000000i64
float32 f 2.5f, 1000f
float64 d 2.5d, the same as 2.5; 42d is 42.0
uint2 u2 3u2
uint4 u4 15u4

The full name of any value type is accepted as a suffix as well: 3float32 is 3f. The one-letter suffixes b, w, u, c, s, i, f and d have been available since GeoDMS 7.105.

Any other name directly after a number is taken as the name of a values unit: 5m means 5[m], that is value(5, m), the value 5 expressed in the unit m (see value). This makes the suffix letters above unavailable as unit suffixes: with a unit named s for seconds, 5s is the int16 value 5, not five seconds; write 5[s]. The bracket form is unambiguous and works for any unit path, as in 10[Units/m]. Since 20.21.0 the upper-case letter is a unit suffix like any other name, so 5W with a unit W for watt is five watt, while 5w is a uint16.

the literal must match the item

A literal is an expression with a value type, and the item that holds it must agree with that type. parameter<int32> x := 42; is refused with ItemType DataItem is incompatible with the result of the calculation which is of type DataItem, because 42 is a uint32; write 42i. The same holds for parameter<float32> f := 2.5;, where 2.5f is needed.

The operands of an arithmetic operator must have the same value type as well; the GeoDMS never promotes one operand to the type of the other. With length a float32 attribute, Road/length * 2 and Road/length * 2.0 are both refused with mul Error: Cannot find operator for these arguments, and Road/length * 2f is accepted. So the suffix of a literal follows the type of the data it is combined with. Conversion functions such as float32(2) do the same as the suffix, at more length.

what is not a literal

  • true and false are constant functions, as are pi() and the typed null values null_b, null_u, null_f, ...; there is no boolean or null literal.
  • Point values are constructed with functions such as point_xy.
  • A whole array of values is not written in an expression; that is what a data block (attribute<int32> a : [1, 2, 3]) is for.

string literals

A string literal is text between single quotes or between double quotes: 'Amsterdam' and "Amsterdam" are the same value. The difference is how the quote character itself is written inside the string:

  • in a single quoted string, a single quote is written twice: 'it''s' is it's;
  • in a double quoted string, a double quote is escaped with a backslash: "say \"yes\"" is say "yes", while a single quote needs nothing: "it's".

In a single quoted string a backslash does not escape the quote: 'it\'s' is a syntax error, since the string ends at the first quote that is not doubled. Which quote style to use often follows from the context: in the original expr = "..." notation the whole expression is a double quoted string, so its string literals are single quoted; see Expression syntax.

Two or more string literals written after each other, with only whitespace in between, form one string: 'Amster' 'dam' is 'Amsterdam', and the styles may be mixed. This joins long texts over several lines without a +.

character escapes

In both quote styles, a backslash starts an escape code that stands for one character:

escape character
\t tab
\n line feed
\r carriage return
\0 the NUL character
\\ a backslash
\" a double quote
\' a single quote (in a double quoted string; in a single quoted string a quote is doubled instead)
\xHH the byte with hexadecimal value HH, e.g. \x41 is A (since GeoDMS 20.0.2)

A backslash before any other character is dropped and that character is kept: 'a\d+b' is the four characters ad+b. This is what turns a Windows path with single backslashes into nonsense: 'C:\temp\data.csv' reads as C:, a tab, empdata.csv, and "C:\Users\x.pdf" as C:Usersx.pdf. Write the separator as \\ or as /, which the GeoDMS accepts in every file name: 'C:/temp/data.csv'. Since GeoDMS 20.10.0 such a literal is reported in the event log as unknown escape code '\d' in the string ..., with the file, line and column when it occurs in a configuration file; the value is still read with the backslash dropped, as before.

The same rules apply to every quoted string in a configuration, not only in calculation rules: a string in a property value such as url, Descr or StorageName and a string in a data block are read by the same parser. Strings that reach the GeoDMS through data, from a file or a database, are not parsed and contain no escape codes.

see also

Clone this wiki locally