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:
[
and ]
) enclose optional parameters.<
and >
) enclose required parameters.|
) symbol is an alternating symbol where the predicate before the pipe or the predicate after the pipe is possible.BOOL
STRING
VECTOR3
(in SecondLife, a tuple with , and components describing a point in space or a spatial vector)VECTOR2
(in SecondLife, a tuple with , components describing a point in a plane or a planar vector)INTEGER
FLOAT
UUID
TYPE[,TYPE…]
where TYPE := BOOL | STRING | VECTOR3 | VECTOR2 | INTEGER | UUID
. Enumerators can be added to any type and are always optional.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.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.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.:
) symbol splits a context from the predicates.&
following the key-value pair format. [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¶meter=&somethingelse=whatever
which has parameter=
breaking the key-value pair syntax).[
, ]
and <
, >
:
|
,
&
=
Here are some basic examples that are used to describe the syntax of commands.
In the following example:
<command=test>&[option=<BOOL>]
for each key-value pair:
<command=test>
is a required key-value pair due to the enclosing angle brackets.[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:
<command=test>&[option=<BOOL[,BOOL...]>]
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
In the following example:
<command=<hello|bye>>&command=hello:<greeting=<STRING>>&command=bye:[greeting=<STRING>]
command
is a required key with two possible required values, either:
hello
as in command=hello
, orbye
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:
command
key takes the value hello
then the key greeting
is required with its value being a string.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:
<command=hello>&<join=<hello|hi>>&<part=<bye|ciao>>&join=hello,part=bye:<say=<STRING>>&join=hi,part=ciao:[say=<STRING>]
which reads the following way:
command=hello
key-value pair is required.join
key is required and just one of the following key-value pairs is required:join=hello
join=hi
part
key is required and just one of the following key-value pairs is required:part=bye
part=ciao
join=hello,part=bye:<say=<STRING»
reads the following way:join=hello
was specified and part=bye
was specified then the command must contain a say
key with its value set to a string.join=hi,part=ciao:[say=<STRING>]
reads the following way: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)
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:
<command=kiss>&<agent=<UUID>|firstname=<STRING>&lastname=<STRING>>&[intensity=<INTEGER>]
which reads:
command
key is required and must be set to kiss
<agent=<UUID>|firstname=<STRING>&lastname=<STRING»
and is interpreted as follows:agent
must be specified in which case the value of the agent
key must be an UUID
, orfirstname
key must be specified with its value set to a string and the lastname
must be specified with its value set to a string.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 &
.