We can create a language for key-value pairs that will allow us to specify how a key-value pair encoded string can be formatted. For instance, it is useful to know whether certain keys depend on other keys or values of other keys, which keys are optional and which are required, etc… This language is used by the Corrade scripted agent to describe the syntax of its commands.


Here are the basic definitions of the syntax string:

  • Square brackets ([ and ]) enclose optional parameters.
  • Angle brackets (< and >) enclose required parameters.
  • The pipe (|) symbol is an alternating symbol where the predicate before the pipe or the predicate after the pipe is possible.
  • Primitive types are capitalised, for example, in a SecondLife context:
    • Booleans: BOOL
    • Strings: STRING
    • Vectors3D: VECTOR3 (in SecondLife, a tuple with $x$, $y$ and $z$ components describing a point in space or a spatial vector)
    • Vectors2D: VECTOR2 (in SecondLife, a tuple with $x$, $y$ components describing a point in a plane or a planar vector)
    • Integers: INTEGER
    • Floats: FLOAT
    • UUIDs: UUID
  • The grammar for writing enumerations is the following: TYPE[,TYPE…] where TYPE := BOOL | STRING | VECTOR3 | VECTOR2 | INTEGER | UUID. Enumerators can be added to any type and are always optional.
    • One can distinguish between mixed-type enumerations, alternating enumerators or sequences in the following way:
      • For mixed-type enumerations, we write: TYPE_1[,TYPE_2,TYPE_3…], for example STRING[,BOOL,INTEGER…] meaning that a list of mixed-types of strings, booleans and integers is possible.
      • For alternating same-type enumerations, we write TYPE_1[,TYPE_1]|TYPE_2[,TYPE_2]|TYPE_3[,TYPE_3], for example STRING,STRING,STRING… or BOOL,BOOL,BOOL… or INTGER,INTEGER,INTEGER… meaning that only a list of strings, or a list of booleans or a list of integers is possible - but do not mix the types.
      • For sequences of types, we write: TYPE_1,TYPE_2,TYPE_3[,TYPE_1,TYPE_2,TYPE_3…], for example STRING,BOOL,INTEGER,STRING,BOOL,INTEGER,STRING,BOOL,INTEGER… meaning that the sequence of types repeats itself as a sequence.
  • The semi-colon (:) symbol splits a context from the predicates.
  • Each key-value pair consists of a key and a value where the key or the value can be of any supported type.
    • Key-value pairs are separated by & following the key-value pair format.

Consequences (Lemmas)

  • A key-value pair such as [parameter=<BOOL>] is valid because it reads: parameter is and optional key and if specified then a boolean must be specified as the value. By contrast, a key-value pair such as <parameter=[BOOL]> will always be invalid because it reads: parameter is a required key and a boolean may be specified as its value - this would end-up breaking the key-value pairs syntax (the command would end up something like this command=hello&parameter=&somethingelse=whatever which has parameter= breaking the key-value pair syntax).

Precedence of Operators

  1. Bracket symbols: [, ] and <, >
  2. Context symbol :
  3. Alternating symbol: |
  4. Comma: ,
  5. Key-value pair binding symbol: &
  6. Key and value separator: =


Here are some basic examples that are used to describe the syntax of commands.

Required and Optional Keys

In the following example:


for each key-value pair:

  • <command=test> is a required key-value pair due to the enclosing angle brackets.
  • The key-value pair [option=<BOOL>] is optional due to the enclosing square brackets. However, in case the option key is specified, then a boolean value must be passed to that key.

This results in the possible commands:

  • command=test
  • command=test&option=true
  • command=test&option=false


In the following example:


The command key is required and must be set to test and the optional option key must be set to a CSV string of booleans. The construct BOOL[,BOOL…] indicates one or more booleans.

This leads to the following generated commands:

  • command=test
  • command=test&option=true
  • command=test&option=true,true
  • command=test&option=true,true,false
  • … and so on expanding on the booleans


In the following example:


command is a required key with two possible required values, either:

  • hello as in command=hello, or
  • bye as in command=bye

Then for each of the two possible required values, either hello or bye that must be passed to the command key, we have the following context judgements:

  • if the command key takes the value hello then the key greeting is required with its value being a string.
  • if the command key takes the value bye then they key greeting is optional, but if the greeting key is specified then it must takes as value a string.

Based on the above, the following commands can be generated:

  • command=hello&greeting=hi!
  • command=bye
  • command=bye&greeting=aufwiedersehen

The consequence being that the hello command requires a greeting but that greeting is optional for the bye command.

One can have multiple contexts, separated by a comma (,) for example:


which reads the following way:

  • the command=hello key-value pair is required.
  • the join key is required and just one of the following key-value pairs is required:
    • join=hello
    • join=hi
  • the part key is required and just one of the following key-value pairs is required:
    • part=bye
    • part=ciao
  • the key-value pair join=hello,part=bye:<say=<STRING» reads the following way:
    • if join=hello was specified and part=bye was specified then the command must contain a say key with its value set to a string.
  • the key-value pair join=hi,part=ciao:[say=<STRING>] reads the following way:
    • if join=hi was specified and part=ciao was specified then the command can contain a say key with its value set to a string.

This leads to the following possible generated valid command strings:

  • command=hello&join=hi&part=ciao (because in the context: join=hi and part=ciao, the say key is optional)
  • command=hello&join=hi&part=ciao&say=alors! (because in the context: join=hi and part=ciao, the say key is optional)
  • command=hello&join=hello&part=bye&say=arrividerci (because in the context: join=hello and part=bye, the say key is required)
  • command=hello&join=hello&part=ciao (because the context: join=hello and part=ciao does not require a say key)
  • command=hello&join=hi&part=bye (because the context: join=hi and part=bye does not require a say key)

Optional Keys

One frequently used construct in Corrade's command structure reads "agent by UUID or avatar by firstname and lastname" which means that you can refer to an agent by writing agent=UUID or you can refer to an agent by writing firstname=Mickey&lastname=Mouse. This meaning is encoded in the syntax as follows:


which reads:

  • the command key is required and must be set to kiss
  • the second pair reads <agent=<UUID>|firstname=<STRING>&lastname=<STRING» and is interpreted as follows:
    • either an agent must be specified in which case the value of the agent key must be an UUID, or
    • the firstname key must be specified with its value set to a string and the lastname must be specified with its value set to a string.
  • the intensity key is optional but if it is specified its value must be set to an integer.

It is important to notice that the bracket operators such as < and > or [ and ] are of a higher precedence than the ampersand &.


fuss/data_structures/key-value_pairs/language.txt · Last modified: 2019/01/03 01:38 (external edit)

Access website using Tor Access website using i2p

For the copyright, license, warranty and privacy terms for the usage of this website please see the license, privacy, data protection and copyright compliance.