Rule Expansions

A grammar is only as expressive as its rules, and rule expansions are how you make a rule expressive. By combining small phrases with a few operations — alternatives, optional parts, and repetition — you can describe anything from a single word to a flexible, multi-part utterance. The operations are:

OperationGrXML exampleABNF exampleDescription
Alternatives<one-of>
  <item><ruleref uri="#A"/></item>
  <item><ruleref uri="#B"/></item>
</one-of>
$A | $B;Match either rule A or rule B.
Optional expansion<ruleref uri="#A"/>
<item repeat="0-1"><ruleref uri="#B"/></item>
$A [$B];Match rule A, optionally followed by rule B.
Repetition<item repeat="7"><ruleref uri="#A"/></item>$A <7>;Match rule A seven times.

Any two rule references not separated by an operator are treated as a logical "and." So $rule = $A $B; is matched if rule $A is matched followed by rule $B.


Rule Alternatives

As we saw in the previous yes/no grammar, the ASR can be told to accept one of several possibilities using the rule-alternative operator. In ABNF this is the pipe symbol (|):

$toppings = pepperoni | sausage | green peppers;

In GrXML, this is done with the <one-of> element to choose between one or more <item> elements:

<rule id="toppings">
  <one-of>
    <item>pepperoni</item>
    <item>sausage</item>
    <item>green peppers</item>
  </one-of>
</rule>

This rule is matched by "pepperoni," "sausage," or "green peppers."

Note that the rule-alternative operator in ABNF is greedy — it collects "peppers" with "green" to form the alternative "green peppers." To scope the effect of the operator, use parentheses:

$pizza = (pepperoni | sausage) pizza;

This rule matches "pepperoni pizza" or "sausage pizza." Without the parentheses, it would match "pepperoni" or "sausage pizza." In GrXML, the <item> element acts similarly to the parentheses.


Optional Expansion

To make a portion of a rule expansion optional, mark it as optional. In ABNF, there is an optional operator — square brackets ([ ]):

$yes = yes [please];

This rule matches "yes" or "yes please."

In GrXML, add a repeat attribute to an <item> element and set it to 0-1 to mark something optional (repeating 0 times means it does not occur; repeating once means it occurs one time):

<rule id="yes">
  yes <item repeat="0-1">please</item>
</rule>

Any of the ABNF operators may be nested inside one another, or used in sequence, to build more expressive sentences:

$yes = yes [please | thank you];

The same can be done with nested <item> and <one-of> elements in GrXML:

<rule id="yes">
  yes
  <item repeat="0-1">
    <one-of>
      <item>please</item>
      <item>thank you</item>
    </one-of>
  </item>
</rule>

This rule matches "yes," "yes please," or "yes thank you."


Repetition

To allow a portion of a rule expansion to be repeated, use the repeat operator — angle brackets (< >) — in ABNF. Inside the angle brackets, enter the number of times to repeat the preceding portion of the rule. The repeat operator can specify a fixed number of repetitions or a range.

ABNF example:

$digit = one | two | three | four | five | six | seven | eight | nine | zero;
$seven_digits = $digit <7>;
$seven_to_ten_digits = $digit <7-10>;
$one_or_more_digit = $digit <1->;

The $seven_digits rule allows any seven-digit combination to be recognized. The $seven_to_ten_digits rule allows any seven- to ten-digit combination. By specifying the range 1- (equivalent to 1-n times), the $one_or_more_digit rule allows one or more digits to be recognized.

In GrXML, the repeat attribute on an <item> element is used (as it was to indicate optionality). The same basic logic applies:

GrXML example:

<rule id="digit">
  <one-of>
    <item>one</item>
    <item>two</item>
    <item>three</item>
    <item>four</item>
    <item>five</item>
    <item>six</item>
    <item>seven</item>
    <item>eight</item>
    <item>nine</item>
    <item>zero</item>
  </one-of>
</rule>

<rule id="seven_digits">
  <item repeat="7"><ruleref uri="#digit"/></item>
</rule>

<rule id="seven_to_ten_digits">
  <item repeat="7-10"><ruleref uri="#digit"/></item>
</rule>

<rule id="one_or_more_digit">
  <item repeat="1-"><ruleref uri="#digit"/></item>
</rule>

The ABNF repeat operator binds tightly — it applies only to whatever immediately precedes it. Use parentheses to control how much of a rule expansion it applies to.

ABNF example:

$oh_boy1 = oh boy <3>;
$oh_boy2 = (oh boy)<3>;

The rule $oh_boy1 matches "oh boy boy boy." $oh_boy2 matches "oh boy oh boy oh boy." In GrXML this behavior is more obvious, since repeat applies only to the <item> it is attached to.

Be very careful when using the repeat operator, especially when allowing an unlimited number of repetitions in combination with rule references. It is possible to build recursive grammars with very large numbers of valid parses, and decoding utterances against such grammars can wreak havoc on your applications.


Unbound Repeat Operators


Once you are comfortable with rule expansions, move on to Rule References to continue the tutorial.

Related Articles


Was this article helpful?