Rule variables

Once you understand SISR Basics, it is time to start actually putting SISR tags into action. This page will describe how to do that.

SISR is concerned mainly with accessing and modifying rule variables. The ultimate return of a grammar is the rule variable of the root rule. How rule variables are modified depends on whether one is using string literals or SI Script.


String Literals

In grammars using the string literals format, anything in a tag is put into the rule variable for a current rule. There is no way to perform any sort of operations. In order to set the root rule's variable, you must either explicitly put the entire desired return result in the root rule or else rely on inheritance.


Rule Visibility and Inheritance

When a rule references another rule that is matched, the referenced rule becomes a child of the original rule. Consider a very simple grammar using the string literals tag format:

#ABNF 1.0 UTF-8;
language en-US;
mode voice;
tag-format <semantics/1.0-literals>;

root $boolean;

$boolean = $yes | $no;
$yes = yes {true};
$no = no {false};

If a speaker says "yes" the parse tree looks like:

$boolean

        $yes

The $yes rule is a child rule of $boolean. Only the direct children of a rule are "visible" to the parent rule, meaning that a rule can only access the variables of its children rules.

If no semantic interpretation tags are present in a matched rule, that rule's variable will inherit the value of the variable of the last visible rule. So in the example above, $boolean has no SISR tags, so it inherits the value of $yes, which in this case is the string "true."

Note that it is good practice to not rely too heavily on inheritance, as it can be difficult to troubleshoot. It is often easier to explicitly give each rule SISR tags.


SI Script

Inheritance and visibility is even more important when using SI Script, which does allow for any sort of operations that can be performed in ECMAScript (most commonly known by its JavaScript implementation).

The current rule's variable is identified by the object called out. It is modified using the standard ECMAScript operators. All variables are initialized as empty objects, but can be converted to strings or integers on the fly by setting their values to those types. For instance, this duplicates the grammar from above using SI Script:

#ABNF 1.0 UTF-8;
language en-US;
mode voice;
tag-format <semantics/1.0>;

root $boolean;

$boolean = $yes | $no;
$yes = yes {out="true"};
$no = no {out="false"};

This grammar sets the value of out to be a string (either "true" or "false") and the root rule's variable still derives its value via inheritance.


Variable Types

Rule variables can be of any type available in ECMAScript. Until they have values assigned to them, they are not explicitly typed. Most variables will be either strings or integers, but you also may use more structured objects. You can create these objects by simply assigning values to properties. You should refer to the ECMAScript specification for more information on working with variables and variable types.

It is important to remember how operations affect data types. For instance, adding two strings combines them into a single string, while adding two integers is treated as mathematical addition on two numbers.


Accessing Other Rule Variables

One of the powers of SI Script is the ability to access the value of any visible rule. This is necessary for concatenating strings or performing mathematical operations. For instance, a digits grammar generally expects that rules will be matched multiple times. One way of building this sort of grammar is to loop through a rule multiple times and add to a variable with each iteration. Consider the following grammar, designed to capture an indefinitely long string of ones and zeroes:

root $binary;
$binary = ($one | $zero) <1->;
$one = one;
$zero = zero;

The difficulty here is that even if we add SISR tags to the $one and $zero rule, we need to concatenate them in the root rule. SI Script provides us with an object called rules that contains, as properties, the variables of all currently visible rules. Using rules.rulename, where rulename is the name of the rule variable we want to access, we can read the values of other rule variables. One way to add SISR to this grammar is as follows:

root $binary;
$binary = {out=""} ($one {out+=rules.one} | $zero {out+=rules.zero}) <1->;
$one = one {out="1"};
$zero = zero {out="0"};

In the $binary rule, we are doing two things that require some explanation. First, we initialize out as an empty string. Second, whenever $one or $zero is matched, we add the value of rules.one or rules.zero to the current rule variable (out). Thus if a caller says "one one zero" the return is the string "110."

The rules object provides a useful shortcut in the latest() property. rules.latest() always refers to the latest rule matched. This can save time when a rule contains many alternatives or when it is impossible to know the exact name of the last rule matched. Here is a modified version of the binary grammar:

root $binary;
$binary = (($one | $zero) {out+=rules.latest()})<1->;
$one = one {out="1"};
$zero = zero {out="0"};

In this implementation, there is no way to tell from the $binary rule whether the $one or the $zero alternatives were matched, but using rules.latest() provides the same functionality as the example before it.


Meta Variables

SI Script provides one other feature that is useful for advanced development. Each rule has associated with it a meta variable that provides information from the Speech Engine about how the rule was matched. The meta object functions similarly to the rules object: specify meta.rulename to access the meta variable for a specific rule, or meta.latest() for the last rule matched. There is also a meta.current() for the current rule (note that there is no rules.current(); the equivalent there is out).

There are two meta properties that can be accessed: text and scoretext returns the raw text from the Engine that caused the Engine to match a rule (i.e. what the Engine recognized the user saying). score provides the confidence score for that text (i.e. how likely it is that what the user said corresponds with the raw text).

As an example, consider the following rule:

$yes = yes {out.interpretation="true"; out.confidence=meta.current().score; out.rawtext=meta.current().text;};

If matched, it returns an object with three properties: interpretation, confidence, and rawtext. The interpretation property contains "true", the confidence property contains a confidence score supplied by the Engine, and the rawtext property contains "yes".

For a more comprehensive example of these principles, see SI Script by Example.


Was this article helpful?
Copyright (C) 2001-2024, Ai Software, LLC d/b/a LumenVox