Class: RubySpeech::GRXML::Grammar

Inherits:
Element
  • Object
show all
Includes:
XML::Language
Defined in:
lib/ruby_speech/grxml/grammar.rb

Overview

The Speech Recognition Grammar Language is an XML application. The root element is grammar.

www.w3.org/TR/speech-grammar/#S4.3

Attributes: uri, language, root, tag-format

tag-format declaration is an optional declaration of a tag-format identifier that indicates the content type of all tags contained within a grammar.

NOTE: A grammar without rules is allowed but cannot be used for processing input – www.w3.org/Voice/2003/srgs-ir/

TODO: Look into lexicon (probably a sub element)

Constant Summary collapse

VALID_CHILD_TYPES =
[Nokogiri::XML::Element, Nokogiri::XML::Text, Rule, Tag].freeze

Instance Attribute Summary

Attributes included from RubySpeech::GenericElement

#parent

Instance Method Summary collapse

Methods included from XML::Language

#language, #language=

Methods inherited from Element

module, namespace, #regexp_content, root_element, #to_doc

Methods included from RubySpeech::GenericElement

#+, #==, #base_uri, #base_uri=, #build, #children, #clone, #create_node, #eval_dsl_block, included, #inherit, #initialize, #inspect, #mass_assign, #method_missing, #namespace=, #namespace_href, #node, #nokogiri_children, #read_attr, #respond_to_missing?, #string, #to_s, #traverse, #version, #version=, #write_attr

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class RubySpeech::GenericElement

Instance Method Details

#<<(arg) ⇒ Object

Raises:


194
195
196
197
# File 'lib/ruby_speech/grxml/grammar.rb', line 194

def <<(arg)
  raise InvalidChildError, "A Grammar can only accept Rule and Tag as children" unless VALID_CHILD_TYPES.include? arg.class
  super
end

#assert_has_matching_root_ruleGrammar

Checks for a root rule matching the value of the root tag

Returns:

Raises:


100
101
102
103
# File 'lib/ruby_speech/grxml/grammar.rb', line 100

def assert_has_matching_root_rule
  raise InvalidChildError, "A GRXML document must have a rule matching the root rule name" unless has_matching_root_rule?
  self
end

#dtmf?Boolean

Returns:

  • (Boolean)

186
187
188
# File 'lib/ruby_speech/grxml/grammar.rb', line 186

def dtmf?
  mode == :dtmf
end

#embed(other) ⇒ Object

Raises:


203
204
205
206
# File 'lib/ruby_speech/grxml/grammar.rb', line 203

def embed(other)
  raise InvalidChildError, "Embedded grammars must have the same mode" if other.is_a?(self.class) && other.mode != mode
  super
end

#eql?(o) ⇒ Boolean

Returns:

  • (Boolean)

199
200
201
# File 'lib/ruby_speech/grxml/grammar.rb', line 199

def eql?(o)
  super o, :language, :base_uri, :mode, :root
end

#inlineGrammar

Returns an inlined copy of self.

Returns:

  • (Grammar)

    an inlined copy of self


108
109
110
# File 'lib/ruby_speech/grxml/grammar.rb', line 108

def inline
  clone.inline!
end

#inline!Object

Replaces rulerefs in the document with a copy of the original rule. Removes all top level rules except the root rule

Returns:

  • self


122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/ruby_speech/grxml/grammar.rb', line 122

def inline!
  previous_uris = {}
  loop do
    rule = nil
    uris = {}
    xpath('//ns:ruleref', ns: GRXML_NAMESPACE).each do |ref|
      uri = ref[:uri].sub(/^#/, '')
      uris[uri] = 1
      rule = rule_with_id uri
      unless rule
        raise MissingReferenceError,
              "Ruleref '##{uri}' is referenced but not defined"
      end
      ref.swap rule.dup.children
    end
    break unless rule
    if previous_uris.keys.eql? uris.keys
      raise ReferentialLoopError,
            'GRXML document contains cycles with ruleref(s): ' <<
            uris.keys.join(', ')
    end
    previous_uris = uris
  end

  query = "./ns:rule[@id!='#{root}']"
  query += "|./ns:rule[@ns:id!='#{root}']" if Nokogiri.jruby?
  non_root_rules = xpath query, ns: namespace_href
  non_root_rules.remove

  self
end

#modeString

The mode of a grammar indicates the type of input that the user agent should be detecting. The default mode is “voice” for speech recognition grammars. An alternative input mode is “dtmf” input“.

Returns:

  • (String)

42
43
44
# File 'lib/ruby_speech/grxml/grammar.rb', line 42

def mode
  read_attr :mode, :to_sym
end

#mode=(ia) ⇒ Object

Parameters:

  • ia (String)

49
50
51
# File 'lib/ruby_speech/grxml/grammar.rb', line 49

def mode=(ia)
  self[:mode] = ia
end

#normalize_whitespaceObject

Normalizes whitespace within tokens in the document according to the rules in the SRGS spec (www.w3.org/TR/speech-grammar/#S2.1) Leading and trailing whitespace is removed, and multiple spaces within the string are collapsed down to single spaces.


177
178
179
180
181
182
183
184
# File 'lib/ruby_speech/grxml/grammar.rb', line 177

def normalize_whitespace
  traverse do |element|
    next if element === self

    imported_element = self.class.import element
    imported_element.normalize_whitespace if imported_element.respond_to?(:normalize_whitespace)
  end
end

#rootString

The root (“rule”) attribute indicates declares a single rule to be the root rle of the grammar. This attribute is OPTIONAL. The rule declared must be defined within the scope of the grammar. It specified rule can be scoped “public” or “private.”

Returns:

  • (String)

59
60
61
# File 'lib/ruby_speech/grxml/grammar.rb', line 59

def root
  read_attr :root
end

#root=(ia) ⇒ Object

Parameters:

  • ia (String)

66
67
68
# File 'lib/ruby_speech/grxml/grammar.rb', line 66

def root=(ia)
  self[:root] = ia
end

#root_ruleRule

Returns The root rule node for the document.

Returns:

  • (Rule)

    The root rule node for the document


88
89
90
91
# File 'lib/ruby_speech/grxml/grammar.rb', line 88

def root_rule
  element = rule_with_id root
  self.class.import element if element
end

#tag_formatString

Returns:

  • (String)

74
75
76
# File 'lib/ruby_speech/grxml/grammar.rb', line 74

def tag_format
  read_attr :'tag-format'
end

#tag_format=(s) ⇒ Object

Parameters:

  • ia (String)

81
82
83
# File 'lib/ruby_speech/grxml/grammar.rb', line 81

def tag_format=(s)
  self['tag-format'] = s
end

#tokenize!Object

Replaces textual content of the document with token elements containing such content. This homogenises all tokens in the document to a consistent format for processing.


158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/ruby_speech/grxml/grammar.rb', line 158

def tokenize!
  traverse do |element|
    next unless element.is_a? Nokogiri::XML::Text

    element_type = self.class.import(element.parent).class
    next if [Token, Tag].include?(element_type)

    tokens = split_tokens(element).map do |string|
      Token.new(document).tap { |token| token << string }.node
    end

    element.swap Nokogiri::XML::NodeSet.new(document, tokens)
  end
end

#voice?Boolean

Returns:

  • (Boolean)

190
191
192
# File 'lib/ruby_speech/grxml/grammar.rb', line 190

def voice?
  mode == :voice
end