A Comprehensive Example

This chapter includes the following topics:

  • Ordering a pizza
  • Match output for the pizza example
  • Application that tests the pizza example
  • Using the special GARBAGE rule

A grammar for ordering a pizza

This grammar example, taken from the Semantic Interpretation for Speech Recognition (SISR) Version 1.0 specification, should test your comprehension of the material presented in this document up to here.

A VoiceXML application that uses this grammar can be found in Application that tests the pizza example.

1. <?xml version="1.0" encoding="UTF-8"?> 
 2. <!DOCTYPE  grammar PUBLIC "-//W3C//DTD GRAMMAR 1.0//EN"
 3.            "http://www.w3.org/TR/speech-grammar/grammar.dtd">

 4. <grammar 
 5.    xml:lang="en"
 6.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 7.    xsi:schemaLocation="http://www.w3.org/2001/06/grammar
 8.                        http://www.w3.org/TR/speech-grammar/grammar.xsd"
 9.    version="1.0"
10.    mode="voice"
11.    tag-format="semantics/1.0"
12.    root="order">

13.    <rule id="order">
14.       i would like a
15.       <ruleref uri="#drink"/>
16.       <tag>
17.         out.drink = new Object();
18.         out.drink.liquid=rules.drink.liquid;
19.         out.drink.drinksize=rules.drink.drinksize;
20.       </tag>
21.       and
22.       <ruleref uri="#pizza"/>
23.       <tag>out.pizza=rules.pizza;</tag>
24.    </rule>

25.    <rule id="kindofdrink">
26.       <one-of>
27.          <item>coke</item>
28.          <item>pepsi</item>
29.          <item>coca cola<tag>out="coke";</tag></item>
30.       </one-of>
31.    </rule>

32.    <rule id="foodsize">
33.       <!-- "medium" is default if nothing said -->
34.       <tag>out="medium";</tag>       
35.      <item repeat="0-1">
36.          <one-of>
37.             <item>small<tag>out="small";</tag></item>
38.             <item>medium</item>
39.             <item>large<tag>out="large";</tag></item>
40.             <item>regular<tag>out="medium";</tag></item>
41.          </one-of>
42.       </item>
43.    </rule>

44.    <!-- Construct Array of toppings, return Array -->
45.    <rule id="tops">
46.       <tag>out=new Array;</tag>
47.       <ruleref uri="#top"/>
48.       <tag>out.push(rules.top);</tag>
49.       <item repeat="1-">
50.          and
51.          <ruleref uri="#top"/>
52.          <tag>out.push(rules.top);</tag>
53.       </item>
54.    </rule>

55.    <rule id="top">
56.       <one-of>
57.          <item>anchovies</item>
58.          <item>pepperoni</item>
59.          <item>mushroom<tag>out="mushrooms";</tag></item>
60.          <item>mushrooms</item>
61.       </one-of>
62.    </rule>

63.    <!-- Two properties (drinksize, type) 
64.         in Rule Variable -->
65.    <rule id="drink">
66.       <ruleref uri="#foodsize"/>
67.       <ruleref uri="#kindofdrink"/>
68.       <tag>
69.          out.drinksize=rules.foodsize; 
70.          out.liquid=rules.kindofdrink;
71.       </tag>
72.    </rule>

73.    <!-- Three properties on rules.pizza -->
74.    <rule id="pizza">
75.       <ruleref uri="#number"/>
76.       <ruleref uri="#foodsize"/>
77.       <tag>
78.          out.pizzasize=rules.foodsize; 
79.          out.number=rules.number;
80.       </tag>
81.       pizzas with
82.       <ruleref uri="#tops"/>
83.       <tag>out.topping=rules.tops;</tag>
84.    </rule>

85.    <rule id="number">
86.       <one-of>
87.          <item>
88.             <tag>out=1;</tag>
89.             <one-of>
90.                <item>a</item>
91.                <item>one</item>
92.             </one-of>
93.          </item>
94.          <item>two<tag>out=2;</tag></item>
95.          <item>three<tag>out=3;</tag></item>
96.       </one-of>
97.    </rule>
98. </grammar>

Some hints:

  • In line 17 a new object is created. out is already an object, but out.drink is a property of out and is not an object. By making out.drink an object, it can have its own properties, such as out.drink.liquid and out.drink.drinksize.
  • The <tag> element in line 17 could have been written more succinctly as <tag>out.drink=rules.drink;</tag>.
  • The foodsize grammar rule is used for both drinks and pizzas. It can be small, medium, or large. If a speaker says "regular" they get a medium, which is the default. The value medium is set as the default in line 34. Line 35 specifies that naming a size is optional.
  • The drink rule (line 65) is where the type of drink and its size is determined.
  • The number rule (line 85) is used to determine the number of pizzas.

Note

There is no way for the speaker to order more than one drink.

  • The top rule (line 55) lists the three toppings the speaker can choose.
  • The tops (plural) rule (line 45) creates an array of toppings. The top rule is called at least twice so that the speaker must choose at least two toppings.
  • The pizza rule (line 74) combines the number, size, and toppings.
  • The order rule (line 13) combines the drink and pizza orders. Note that the drink and pizza parts of the order are treated differently (see the first two hints, above).

Match output for the pizza example

When all the grammar rules have been parsed, the Rule Variable (out) for the root rule (id="order") in the example is an object with a number of properties, each with an assigned value. You should be able to understand how they were created and given values by studying the example. The properties are:

  • out.drink.drinksize
  • out.drink.liquid
  • out.pizza.number
  • out.pizza.pizzasize
  • out.pizza.topping[0]
  • out.pizza.topping[1]
  • out.pizza.topping[2]

Note

out.pizza.topping[] is an array with at least two elements, and possibly three.

In the application that tests the example grammar, below, the out object that is the result of executing the grammar is placed in the field variable, softDrinkAndPizza (also an object). So, in the application, the variables are:

  • softDrinkAndPizza.drink.drinksize
  • softDrinkAndPizza.drink.liquid
  • softDrinkAndPizza.pizza.number
  • softDrinkAndPizza.pizza.pizzasize
  • softDrinkAndPizza.pizza.topping[0]
  • softDrinkAndPizza.pizza.topping[1]
  • softDrinkAndPizza.pizza.topping[2]

The test application asks the caller for input and then, using the code in the <filled> section speaks the values of these variables.

If the topping array has only two elements, the empty element, [2], is simply not spoken by the application.

Application that tests the pizza example

This VBoic eXML application includes the pizza grammar described above (A grammar for ordering a pizza).

<?xml version="1.0"?>
      " revision="4" 
      xmlns="http://www/w3/org/2001/VXML" 
      xml:lang="en-US">

<form  id="mainMenu">
  <field name="softDrinkAndPizza">
    <prompt>Please say something</prompt>
    <!--BEGIN PIZZA GRAMMAR-->
    <grammar version="1.0" mode="voice" 
             tag-format="semantics/1.0" root="order">
      <rule id="order">
         i would like a
         <ruleref uri="#drink"/>
         <tag>
            out.drink = new Object();
            out.drink.liquid=rules.drink.liquid;
            out.drink.drinksize=rules.drink.drinksize;
         </tag>
         and
         <ruleref uri="#pizza"/>
         <tag>out.pizza=rules.pizza;</tag>
      </rule>
      <rule id="kindofdrink">
         <one-of>
            <item>coke</item>
            <item>pepsi</item>
            <item>coca cola<tag>out="coke";</tag></item>
         </one-of>
      </rule>
      <rule id="foodsize">
         <tag>out="medium";</tag> <!-- default if nothing said -->
         <item repeat="0-1">
            <one-of>
               <item>small<tag>out="small";</tag></item>
               <item>medium</item>
               <item>large<tag>out="large";</tag></item>
               <item>regular<tag>out="medium";</tag></item>
            </one-of>
         </item>
      </rule>
      <!-- Construct Array of toppings, return Array -->
      <rule id="tops">
         <tag>out=new Array;</tag>
         <ruleref uri="#top"/>
         <tag>out.push(rules.top);</tag>
         <item repeat="1-">
            and
            <ruleref uri="#top"/>
            <tag>out.push(rules.top);</tag>
         </item>
      </rule>
      <rule id="top">
         <one-of>
            <item>anchovies</item>
            <item>pepperoni</item>
            <item>mushroom<tag>out="mushrooms";</tag></item>
            <item>mushrooms</item>
         </one-of>
      </rule>
      <!-- Two properties (drinksize, liquid) of Rule Variable -->
      <rule id="drink">
         <ruleref uri="#foodsize"/>
         <ruleref uri="#kindofdrink"/>
            <tag>out.drinksize=rules.foodsize; out.liquid=
            rules.kindofdrink;</tag>
      </rule>
      <!-- Three properties on rules.pizza -->
      <rule id="pizza">
         <ruleref uri="#number"/>
         <ruleref uri="#foodsize"/>
         <tag>out.pizzasize=rules.foodsize; out.number=rules.number;</tag>
         pizzas with
         <ruleref uri="#tops"/>
         <tag>out.topping=rules.tops;</tag>
      </rule>
      <rule id="number">
         <one-of>
            <item>
               <tag>out=1;</tag>
               <one-of>
                  <item>a</item>
                  <item>one</item>
               </one-of>
            </item>
            <item>two<tag>out=2;</tag></item>
            <item>three<tag>out=3;</tag></item>
         </one-of>
      </rule>
   </grammar>
    <!--END PIZZA GRAMMAR-->
   <filled>
      <prompt>
         Thank you
      </prompt>
      <prompt>
         drinksize is <value expr="softDrinkAndPizza.drink.drinksize"/>
      </prompt>
      <prompt>
         drink brand is <value expr="softDrinkAndPizza.drink.liquid"/>
      </prompt>
      <prompt>
         number of pizzas is <value expr="softDrinkAndPizza.pizza.number"/>
      </prompt>
      <prompt>
         pizza size is <value expr="softDrinkAndPizza.pizza.pizzasize"/>
      </prompt>
      <prompt>
         topping one is <value expr="softDrinkAndPizza.pizza.topping[0]"/>
      </prompt>
      <prompt>
         topping two is <value expr="softDrinkAndPizza.pizza.topping[1]"/>
      </prompt>
      <prompt>
         topping three is <value expr="softDrinkAndPizza.pizza.topping[2]"/>
      </prompt>
   </filled>
   <noinput> </noinput>
   <nomatch> </nomatch>
  </field>
</form>
</VXML>

Using the special GARBAGE rule

When you run the application that tests the pizza example in the Tellme Studio Scratchpad, you must be careful to say:

"i would like a 
[small || medium || large] 
[pepsi ||coke ||coca cola] 
and 
[a || one || two || three]
[small || medium || large]
pizza with
[mushrooms || anchovies || pepperoni]
and
[mushrooms || anchovies || pepperoni]          
and
 [mushrooms || anchovies || pepperoni] "

The third topping is optional, but you must name at least two.

If you do not speak the phrases above exactly as they are written, no match occurs. If, on the other hand, most of the phrases are replaced with <ruleref special="GARBAGE"/>, then the grammar works for a wide variety of input utterances. Specifically, referring to the example “Ordering a pizza”:

  1. Replace the phrases in lines 14, 21, and 50 of the grammar ("i would like a", "and", and "and" with <ruleref special="GARBAGE"/>.
  2. Replace the phrase "with" in line 81 with <ruleref special="GARBAGE"/>, but keep the phrase "pizzas".
  3. In the <one-of> list starting in line 89, add a third alternative, <item><ruleref special="GARBAGE"/></item>.

When these changes are made, the requirements on what the caller must say to get a match are almost completely relaxed. The caller still must say "pizza", however.

These are the new requirements:

"(caller can say anything here, including nothing)
[small || medium || large] 
[pepsi ||coke || coca cola] 
(caller can say anything here, including nothing)
[a || one || two || three]
[small || medium || large]
pizza (caller must say this)
(caller can say anything else here, including nothing)
[mushrooms || anchovies || pepperoni]
(caller can say anything here, including nothing)
[mushrooms || anchovies || pepperoni]          
(caller can say anything here, including nothing)
 [mushrooms || anchovies || pepperoni] "