Rule References
Rule references are what let grammars scale: rather than repeating the same words everywhere, you define a rule once and reference it wherever you need it — even from a separate grammar file you can reuse across projects. You have already seen this in the simple yes/no grammar, where the root rule referenced the yes and no rules. Rule references work slightly differently in ABNF and GrXML.
Referencing Rules in the Same Grammar
ABNF example:
| $yesorno = $yes | $no; |
In ABNF, you reference a rule by its rulename as part of a rule expansion. The dollar-sign character $ indicates a rulename (so $yes is a rule reference to the "yes" rule, not the word "yes").
GrXML example:
| <rule id="yesorno"> <one-of> <item><ruleref uri="#yes"/></item> <item><ruleref uri="#no"/></item> </one-of> </rule> |
In GrXML, the special ruleref element is used. It takes a uri attribute whose value is the URI of the rule you are referencing. If the referenced rule is in the current grammar, prefix the rule name with the hash symbol # to indicate it is local. Because the ruleref element takes no children, it must be closed with a slash / before the closing >.
When either grammar is parsed, the contents of the yes and no rules are included as part of the yesorno rule. A rule is considered the child of any rule that references it.
Referencing External Grammars
You can also reference external grammar files — or rules within external files — to build more complex grammars and reuse existing ones. Suppose you had a simple phone-number grammar at the remote URI http://www.mycompany.com/phone_number.gram that looked like this:
ABNF example:
| #ABNF 1.0; language en-US; mode voice; root $phone_number; $phone_number = [$area_code] $number; $digit = one | two | three | four | five | six | seven | eight | nine | zero; $area_code = [one | area code] $digit<3>; $number = $digit<7>; |
You can use this grammar in another grammar by specifying its location, inside angle brackets, as a rulename:
| #ABNF 1.0; language en-US; mode voice; root $main; $main = (my | the) [phone] number is $<http://www.mycompany.com/phone_number.gram>; |
GrXML example:
| <?xml version="1.0" encoding="UTF-8" ?> <grammar xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en-US" root="phone_number" mode="voice"> <rule id="phone_number"> <item repeat="0-1"><ruleref uri="#area_code"/></item> <ruleref uri="#number"/> </rule> <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="area_code"> <item repeat="0-1"> <one-of> <item>one</item> <item>area code</item> </one-of> </item> <item repeat="3"><ruleref uri="#digit"/></item> </rule> <rule id="number"> <item repeat="7"><ruleref uri="#digit"/></item> </rule> </grammar> |
The grammar above can be referenced in another GrXML grammar by giving the fully qualified URI in the ruleref element:
| <?xml version="1.0" encoding="UTF-8" ?> <grammar xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en-US" root="phone_number" mode="voice"> <rule id="main"> <one-of> <item>my</item> <item>the</item> </one-of> <item repeat="0-1">phone</item> number is <ruleref uri="http://www.mycompany.com/phone_number.gram"/> </rule> </grammar> |
In both GrXML and ABNF, the same basic logic applies: the second grammar uses the root rule of the phone_number grammar in its main rule. You can reference grammar files using HTTP, FTP, or your operating system's local or network file paths. When writing grammars that use external grammar files, it is usually a good idea to specify a base URI in the grammar header.
Referencing a Specific Rule in an External Grammar
By default, referencing an external grammar references that grammar's root rule. You can instead reference a specific rule within an external grammar by adding the # symbol followed by the rule name immediately after the URI.
ABNF example:
| #ABNF 1.0; language en-US; mode voice; root $main; $main = (my | the) area code is $<http://www.mycompany.com/phone_number.gram#area_code>; |
Here, $main references only the $area_code rule from the phone_number grammar. It looks similar in GrXML:
GrXML example:
| <?xml version="1.0" encoding="UTF-8" ?> <grammar xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en-US" root="phone_number" mode="voice"> <rule id="main"> <one-of> <item>my</item> <item>the</item> </one-of> <item repeat="0-1">phone</item> number is <ruleref uri="http://www.mycompany.com/phone_number.gram#area_code"/> </rule> </grammar> |
Referencing Built-in Grammars
In addition to external grammar files, you can reference any of the platform's built-in grammars.
ABNF example:
| #ABNF 1.0; language en-US; mode voice; root $main; $main = (my | the) [phone] number is $<builtin:grammar/phone>; |
GrXML example:
| <?xml version="1.0" encoding="UTF-8" ?> <grammar xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en-US" root="phone_number" mode="voice"> <rule id="main"> <one-of> <item>my</item> <item>the</item> </one-of> <item repeat="0-1">phone</item> number is <ruleref uri="builtin:grammar/phone"/> </rule> </grammar> |
To reference a built-in grammar, provide a URI in the format builtin:grammar/name, where name is one of the built-in types.
The next part of the grammar tutorial covers writing Special Rules.
Related Articles
- Rule Expansions — the previous step.
- Special Rules — the next step.
- Builtin Grammars
