ruby_speech 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a4f1b109d9aca99877fdea094ae7898d160c2bc5
4
- data.tar.gz: 61f380357241df94f39f25db15e17433d6766bb5
3
+ metadata.gz: de37299d09f7a9dc63c8c5944db79f80594bfffc
4
+ data.tar.gz: c01558ff39e76c034f1b18df7288c27d04ec84b1
5
5
  SHA512:
6
- metadata.gz: 01c6b26ae73ae0627b8ce474ea6fdddc8d0b87779a07c3908c57b71e3101ec8a447a8980a88d17de53c216442137122b03c821026146fd650066ec44030ce949
7
- data.tar.gz: 7075b29b0be7f4a7f1ca2b83fc3694be0e09566dbd0ef12be3c66933538cb885053d9971a933e094ac59c5090f56bdb82774ef0c3afcd69cd4eedc21d3a2bf82
6
+ metadata.gz: a2dc9ae2659cc93d40f7f0d55a2d6b4344accf12f7b1d7cf130aba09c4949a868bc47e2c641183aecad8bd42b0312a50d3a14d27eb9b933664fbaaa15de60cdc
7
+ data.tar.gz: 3df44bf14ab55473bd2dab097e2e972493744d299390085506e90ff437eb82441f535a3b29b1a45ac73d22c1770d0f4e4de9dbbb954d3d3c7c6983f12a741b75
data/.travis.yml CHANGED
@@ -7,7 +7,9 @@ rvm:
7
7
  - jruby-19mode
8
8
  - rbx-19mode
9
9
  - ruby-head
10
-
10
+ matrix:
11
+ allow_failures:
12
+ # - rvm: jruby-19mode
11
13
  before_install:
12
14
  - sudo apt-get install libpcre3 libpcre3-dev
13
15
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # [develop](https://github.com/benlangfeld/ruby_speech)
2
2
 
3
+ # [2.0.2](https://github.com/benlangfeld/ruby_speech/compare/v2.0.1...v2.0.2) - [2013-05-01](https://rubygems.org/gems/ruby_speech/versions/2.0.2)
4
+ * Bugfix: Differentiate between GRXML match cases with are and are not maximal
5
+ * A Match can accept further input while still matching, while a a MaxMatch cannot.
6
+ * Matching implementation moved down to C/Java to avoid repeated regex compilation and confusing jumping about.
7
+ * Bugfix: Back to functioning on JRuby with latest Nokogiri release
8
+
3
9
  # [2.0.1](https://github.com/benlangfeld/ruby_speech/compare/v2.0.0...v2.0.1) - [2013-04-27](https://rubygems.org/gems/ruby_speech/versions/2.0.1)
4
10
  * Bugfix: Build native C extension in the correct location
5
11
 
data/Guardfile CHANGED
@@ -1,5 +1,5 @@
1
1
  guard 'rake', :task => 'compile' do
2
- watch(%r{^ext/(.+)\.c$})
2
+ watch(%r{^ext/(.+)\.(c|java)$})
3
3
  end
4
4
 
5
5
  guard 'rspec', :cli => '--format documentation' do
@@ -17,26 +17,48 @@ import java.util.regex.*;
17
17
  @JRubyClass(name="RubySpeech::GRXML::Matcher")
18
18
  public class RubySpeechGRXMLMatcher extends RubyObject {
19
19
 
20
+ Pattern p;
21
+
20
22
  public RubySpeechGRXMLMatcher(final Ruby runtime, RubyClass rubyClass) {
21
23
  super(runtime, rubyClass);
22
24
  }
23
25
 
24
26
  @JRubyMethod(visibility=Visibility.PRIVATE)
25
- public IRubyObject check_potential_match(ThreadContext context, IRubyObject buffer)
26
- {
27
+ public IRubyObject compile_regex(ThreadContext context, IRubyObject regex) {
27
28
  Ruby runtime = context.getRuntime();
29
+ p = Pattern.compile(regex.toString());
30
+ return runtime.getNil();
31
+ }
28
32
 
29
- IRubyObject regex = getInstanceVariable("@regex");
30
-
31
- Pattern p = Pattern.compile(regex.toString());
32
- Matcher m = p.matcher(buffer.toString());
33
+ @JRubyMethod(visibility=Visibility.PUBLIC)
34
+ public IRubyObject find_match(ThreadContext context, IRubyObject buffer)
35
+ {
36
+ Ruby runtime = context.getRuntime();
37
+ String string_buffer = buffer.toString();
38
+ Matcher m = p.matcher(string_buffer);
33
39
 
34
40
  if (m.matches()) {
41
+ if (is_max_match(string_buffer)) {
42
+ return RuntimeHelpers.invoke(context, this, "match_for_buffer", buffer, runtime.getTrue());
43
+ }
44
+ return callMethod(context, "match_for_buffer", buffer);
35
45
  } else if (m.hitEnd()) {
36
46
  RubyModule potential_match = runtime.getClassFromPath("RubySpeech::GRXML::PotentialMatch");
37
- return RuntimeHelpers.invoke(context, potential_match, "new");
47
+ return potential_match.callMethod(context, "new");
38
48
  }
39
- return runtime.getNil();
49
+ RubyModule nomatch = runtime.getClassFromPath("RubySpeech::GRXML::NoMatch");
50
+ return nomatch.callMethod(context, "new");
51
+ }
52
+
53
+ public Boolean is_max_match(String buffer)
54
+ {
55
+ String search_set = "0123456789#*ABCD";
56
+ for (int i = 0; i < 16; i++) {
57
+ String new_buffer = buffer + search_set.charAt(i);
58
+ Matcher m = p.matcher(new_buffer);
59
+ if (m.matches()) return false;
60
+ }
61
+ return true;
40
62
  }
41
63
 
42
64
  }
@@ -2,33 +2,88 @@
2
2
  #include "pcre.h"
3
3
  #include <stdio.h>
4
4
 
5
- static VALUE method_check_potential_match(VALUE self, VALUE buffer)
5
+ static VALUE method_compile_regex(VALUE self, VALUE regex_string)
6
6
  {
7
- int erroffset = 0;
8
- const char *errptr = "";
9
- int options = 0;
10
- VALUE regex_string = rb_funcall(rb_iv_get(self, "@regex"), rb_intern("to_s"), 0);
11
- const char *regex = StringValueCStr(regex_string);
7
+ int erroffset = 0;
8
+ const char *errptr = "";
9
+ int options = 0;
10
+ const char *regex = StringValueCStr(regex_string);
12
11
 
13
12
  pcre *compiled_regex = pcre_compile(regex, options, &errptr, &erroffset, NULL);
13
+ VALUE compiled_regex_wrapper = Data_Wrap_Struct(rb_cObject, 0, pcre_free, compiled_regex);
14
+ rb_iv_set(self, "@regex", compiled_regex_wrapper);
14
15
 
16
+ return Qnil;
17
+ }
18
+
19
+ #define MAX_INPUT_SIZE 128
20
+ #define OVECTOR_SIZE 30
21
+ #define WORKSPACE_SIZE 1024
22
+
23
+ /**
24
+ * Check if no more digits can be added to input and match
25
+ * @param compiled_regex the regex used in the initial match
26
+ * @param input the input to check
27
+ * @return true if end of match (no more input can be added)
28
+ */
29
+ static int is_match_end(pcre *compiled_regex, const char *input)
30
+ {
31
+ int ovector[OVECTOR_SIZE];
32
+ int input_size = (int)strlen(input);
33
+ char search_input[MAX_INPUT_SIZE + 2];
34
+ const char *search_set = "0123456789#*ABCD";
35
+ const char *search = strchr(search_set, input[input_size - 1]); /* start with last digit in input */
36
+
37
+ /* For each digit in search_set, check if input + search_set digit is a potential match.
38
+ If so, then this is not a match end.
39
+ */
40
+ sprintf(search_input, "%sZ", input);
41
+ int i;
42
+ for (i = 0; i < 16; i++) {
43
+ int result;
44
+ if (!*search) {
45
+ search = search_set;
46
+ }
47
+ search_input[input_size] = *search++;
48
+ result = pcre_exec(compiled_regex, NULL, search_input, input_size + 1, 0, 0,
49
+ ovector, sizeof(ovector) / sizeof(ovector[0]));
50
+ if (result > 0) return 0;
51
+ }
52
+ return 1;
53
+ }
54
+
55
+ static VALUE method_find_match(VALUE self, VALUE buffer)
56
+ {
57
+ VALUE RubySpeech = rb_const_get(rb_cObject, rb_intern("RubySpeech"));
58
+ VALUE GRXML = rb_const_get(RubySpeech, rb_intern("GRXML"));
59
+ VALUE NoMatch = rb_const_get(GRXML, rb_intern("NoMatch"));
60
+ pcre *compiled_regex;
15
61
  int result = 0;
16
- int ovector[30];
17
- int workspace[1024];
62
+ int ovector[OVECTOR_SIZE];
63
+ int workspace[WORKSPACE_SIZE];
18
64
  char *input = StringValueCStr(buffer);
19
- result = pcre_dfa_exec(compiled_regex, NULL, input, strlen(input), 0, PCRE_PARTIAL,
65
+
66
+ Data_Get_Struct(rb_iv_get(self, "@regex"), pcre, compiled_regex);
67
+
68
+ if (!compiled_regex) {
69
+ return rb_class_new_instance(0, NULL, NoMatch);
70
+ }
71
+
72
+ result = pcre_dfa_exec(compiled_regex, NULL, input, (int)strlen(input), 0, PCRE_PARTIAL,
20
73
  ovector, sizeof(ovector) / sizeof(ovector[0]),
21
74
  workspace, sizeof(workspace) / sizeof(workspace[0]));
22
- pcre_free(compiled_regex);
23
75
 
76
+ if (result > 0) {
77
+ if (is_match_end(compiled_regex, input)) {
78
+ return rb_funcall(self, rb_intern("match_for_buffer"), 2, buffer, Qtrue);
79
+ }
80
+ return rb_funcall(self, rb_intern("match_for_buffer"), 1, buffer);
81
+ }
24
82
  if (result == PCRE_ERROR_PARTIAL) {
25
- VALUE RubySpeech = rb_const_get(rb_cObject, rb_intern("RubySpeech"));
26
- VALUE GRXML = rb_const_get(RubySpeech, rb_intern("GRXML"));
27
- VALUE PotentialMatch = rb_const_get(GRXML, rb_intern("PotentialMatch"));
28
-
83
+ VALUE PotentialMatch = rb_const_get(GRXML, rb_intern("PotentialMatch"));
29
84
  return rb_class_new_instance(0, NULL, PotentialMatch);
30
85
  }
31
- return Qnil;
86
+ return rb_class_new_instance(0, NULL, NoMatch);
32
87
  }
33
88
 
34
89
  void Init_ruby_speech()
@@ -37,5 +92,6 @@ void Init_ruby_speech()
37
92
  VALUE GRXML = rb_define_module_under(RubySpeech, "GRXML");
38
93
  VALUE Matcher = rb_define_class_under(GRXML, "Matcher", rb_cObject);
39
94
 
40
- rb_define_method(Matcher, "check_potential_match", method_check_potential_match, 1);
95
+ rb_define_method(Matcher, "find_match", method_find_match, 1);
96
+ rb_define_method(Matcher, "compile_regex", method_compile_regex, 1);
41
97
  }
@@ -109,17 +109,14 @@ module RubySpeech
109
109
 
110
110
  def children(type = nil, attributes = nil)
111
111
  if type
112
- expression = type.to_s
112
+ expression = namespace_href ? 'ns:' : ''
113
+ expression << type.to_s
113
114
 
114
115
  expression << '[' << attributes.inject([]) do |h, (key, value)|
115
- h << "@#{key}='#{value}'"
116
+ h << "@#{namespace_href && Nokogiri.jruby? ? 'ns:' : ''}#{key}='#{value}'"
116
117
  end.join(',') << ']' if attributes
117
118
 
118
- if namespace_href
119
- xpath "ns:#{expression}", :ns => namespace_href
120
- else
121
- xpath expression
122
- end
119
+ xpath expression, :ns => namespace_href
123
120
  else
124
121
  super()
125
122
  end.map { |c| self.class.import c }
@@ -109,7 +109,7 @@ module RubySpeech
109
109
  ref.swap rule.nokogiri_children
110
110
  end
111
111
 
112
- non_root_rules = xpath "./ns:rule[@id!='#{root}']", :ns => namespace_href
112
+ non_root_rules = xpath "./ns:rule[@#{namespace_href && Nokogiri.jruby? ? 'ns:' : ''}id!='#{root}']", :ns => namespace_href
113
113
  non_root_rules.remove
114
114
 
115
115
  self
@@ -8,7 +8,7 @@ module RubySpeech
8
8
  end
9
9
 
10
10
  def eql?(o)
11
- o.is_a?(self.class) && [:mode, :confidence, :utterance, :interpretation].all? { |f| self.__send__(f) == o.__send__(f) }
11
+ o.instance_of?(self.class) && [:mode, :confidence, :utterance, :interpretation].all? { |f| self.__send__(f) == o.__send__(f) }
12
12
  end
13
13
  alias :== :eql?
14
14
  end
@@ -8,15 +8,12 @@ end
8
8
  module RubySpeech
9
9
  module GRXML
10
10
  class Matcher
11
-
12
- BLANK_REGEX = //.freeze
13
-
14
- attr_reader :grammar, :regex
11
+ attr_reader :grammar
15
12
 
16
13
  def initialize(grammar)
17
14
  @grammar = grammar
18
15
  prepare_grammar
19
- @regex = /^#{regexp_content.join}$/
16
+ compile_regex regexp_content
20
17
  end
21
18
 
22
19
  ##
@@ -24,7 +21,7 @@ module RubySpeech
24
21
  #
25
22
  # @param [String] other the input string to check for a match with the grammar
26
23
  #
27
- # @return [NoMatch, Match] depending on the result of a match attempt. If a match can be found, it will be returned with appropriate mode/confidence/utterance and interpretation attributes
24
+ # @return [NoMatch, PotentialMatch, Match, MaxMatch] depending on the result of a match attempt. A potential match indicates that the buffer is valid, but incomplete. A MaxMatch is differentiated from a Match in that it cannot accept further input. If a match can be found, it will be returned with appropriate mode/confidence/utterance and interpretation attributes
28
25
  #
29
26
  # @example A grammar that takes a 4 digit pin terminated by hash, or the *9 escape sequence
30
27
  # ```ruby
@@ -85,34 +82,27 @@ module RubySpeech
85
82
  # ```
86
83
  #
87
84
  def match(buffer)
88
- buffer = buffer.dup
89
-
90
- return check_potential_match(buffer) if regex == BLANK_REGEX
91
-
92
- check_full_match(buffer) || check_potential_match(buffer) || NoMatch.new
85
+ find_match buffer.dup
93
86
  end
94
87
 
95
88
  private
96
89
 
90
+ def regexp_content
91
+ '^' + grammar.root_rule.children.map(&:regexp_content).join + '$'
92
+ end
93
+
97
94
  def prepare_grammar
98
95
  grammar.inline!
99
96
  grammar.tokenize!
100
97
  grammar.normalize_whitespace
101
98
  end
102
99
 
103
- def check_full_match(buffer)
104
- match = regex.match buffer
105
-
106
- return unless match
107
-
108
- Match.new :mode => grammar.mode,
109
- :confidence => grammar.dtmf? ? 1 : 0,
110
- :utterance => buffer,
111
- :interpretation => interpret_utterance(buffer)
112
- end
113
-
114
- def regexp_content
115
- grammar.root_rule.children.map &:regexp_content
100
+ def match_for_buffer(buffer, maximal = false)
101
+ match_class = maximal ? MaxMatch : Match
102
+ match_class.new mode: grammar.mode,
103
+ confidence: grammar.dtmf? ? 1 : 0,
104
+ utterance: buffer,
105
+ interpretation: interpret_utterance(buffer)
116
106
  end
117
107
 
118
108
  def interpret_utterance(utterance)
@@ -0,0 +1,6 @@
1
+ module RubySpeech
2
+ module GRXML
3
+ class MaxMatch < Match
4
+ end
5
+ end
6
+ end
@@ -15,6 +15,7 @@ module RubySpeech
15
15
 
16
16
  autoload :Match
17
17
  autoload :Matcher
18
+ autoload :MaxMatch
18
19
  autoload :NoMatch
19
20
  autoload :PotentialMatch
20
21
 
@@ -1,3 +1,3 @@
1
1
  module RubySpeech
2
- VERSION = "2.0.1"
2
+ VERSION = "2.0.2"
3
3
  end
data/ruby_speech.gemspec CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
25
25
  s.extensions = ['ext/ruby_speech/extconf.rb']
26
26
  end
27
27
 
28
- s.add_runtime_dependency %q<niceogiri>, ["~> 1.1", ">= 1.1.1"]
28
+ s.add_runtime_dependency %q<niceogiri>, ["~> 1.1", ">= 1.1.2"]
29
29
  s.add_runtime_dependency %q<nokogiri>, ["~> 1.5", ">= 1.5.6"]
30
30
  s.add_runtime_dependency %q<activesupport>, [">= 3.0.7"]
31
31
 
@@ -3,45 +3,11 @@ require 'spec_helper'
3
3
  module RubySpeech
4
4
  module GRXML
5
5
  describe Match do
6
- subject do
7
- Match.new :mode => :dtmf,
8
- :confidence => 1,
9
- :utterance => '6',
10
- :interpretation => 'foo'
11
- end
12
-
13
- its(:mode) { should == :dtmf }
14
- its(:confidence) { should == 1 }
15
- its(:utterance) { should == '6' }
16
- its(:interpretation) { should == 'foo' }
6
+ it_behaves_like "match"
17
7
 
18
8
  describe "equality" do
19
- it "should be equal when mode, confidence, utterance and interpretation are the same" do
20
- Match.new(:mode => :dtmf, :confidence => 1, :utterance => '6', :interpretation => 'foo').should == Match.new(:mode => :dtmf, :confidence => 1, :utterance => '6', :interpretation => 'foo')
21
- end
22
-
23
- describe "when the mode is different" do
24
- it "should not be equal" do
25
- Match.new(:mode => :dtmf).should_not == Match.new(:mode => :speech)
26
- end
27
- end
28
-
29
- describe "when the confidence is different" do
30
- it "should not be equal" do
31
- Match.new(:confidence => 1).should_not == Match.new(:confidence => 0)
32
- end
33
- end
34
-
35
- describe "when the utterance is different" do
36
- it "should not be equal" do
37
- Match.new(:utterance => '6').should_not == Match.new(:utterance => 'foo')
38
- end
39
- end
40
-
41
- describe "when the interpretation is different" do
42
- it "should not be equal" do
43
- Match.new(:interpretation => 'foo').should_not == Match.new(:interpretation => 'bar')
44
- end
9
+ it "should never be equal to a MaxMatch" do
10
+ described_class.new.should_not eql(MaxMatch.new)
45
11
  end
46
12
  end
47
13
  end
@@ -17,9 +17,9 @@ module RubySpeech
17
17
  end
18
18
  end
19
19
 
20
- it "should match '6'" do
20
+ it "should max-match '6'" do
21
21
  input = '6'
22
- expected_match = GRXML::Match.new :mode => :dtmf,
22
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
23
23
  :confidence => 1,
24
24
  :utterance => '6',
25
25
  :interpretation => 'dtmf-6'
@@ -43,8 +43,8 @@ module RubySpeech
43
43
  end
44
44
  end
45
45
 
46
- it "should match '56'" do
47
- expected_match = GRXML::Match.new :mode => :dtmf,
46
+ it "should maximally match '56'" do
47
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
48
48
  :confidence => 1,
49
49
  :utterance => '56',
50
50
  :interpretation => 'dtmf-5 dtmf-6'
@@ -73,8 +73,8 @@ module RubySpeech
73
73
  end
74
74
  end
75
75
 
76
- it "should match '*6'" do
77
- expected_match = GRXML::Match.new :mode => :dtmf,
76
+ it "should maximally match '*6'" do
77
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
78
78
  :confidence => 1,
79
79
  :utterance => '*6',
80
80
  :interpretation => 'dtmf-star dtmf-6'
@@ -101,8 +101,8 @@ module RubySpeech
101
101
  end
102
102
  end
103
103
 
104
- it "should match '#6'" do
105
- expected_match = GRXML::Match.new :mode => :dtmf,
104
+ it "should maximally match '#6'" do
105
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
106
106
  :confidence => 1,
107
107
  :utterance => '#6',
108
108
  :interpretation => 'dtmf-pound dtmf-6'
@@ -134,8 +134,8 @@ module RubySpeech
134
134
  end
135
135
  end
136
136
 
137
- it "should match '*6'" do
138
- expected_match = GRXML::Match.new :mode => :dtmf,
137
+ it "should maximally match '*6'" do
138
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
139
139
  :confidence => 1,
140
140
  :utterance => '*6',
141
141
  :interpretation => 'dtmf-star dtmf-6'
@@ -165,16 +165,16 @@ module RubySpeech
165
165
  end
166
166
  end
167
167
 
168
- it "should match '6'" do
169
- expected_match = GRXML::Match.new :mode => :dtmf,
168
+ it "should maximally match '6'" do
169
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
170
170
  :confidence => 1,
171
171
  :utterance => '6',
172
172
  :interpretation => 'dtmf-6'
173
173
  subject.match('6').should == expected_match
174
174
  end
175
175
 
176
- it "should match '7'" do
177
- expected_match = GRXML::Match.new :mode => :dtmf,
176
+ it "should maximally match '7'" do
177
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
178
178
  :confidence => 1,
179
179
  :utterance => '7',
180
180
  :interpretation => 'dtmf-7'
@@ -206,16 +206,16 @@ module RubySpeech
206
206
  end
207
207
  end
208
208
 
209
- it "should match '65'" do
210
- expected_match = GRXML::Match.new :mode => :dtmf,
209
+ it "should maximally match '65'" do
210
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
211
211
  :confidence => 1,
212
212
  :utterance => '65',
213
213
  :interpretation => 'dtmf-6 dtmf-5'
214
214
  subject.match('65').should == expected_match
215
215
  end
216
216
 
217
- it "should match '72'" do
218
- expected_match = GRXML::Match.new :mode => :dtmf,
217
+ it "should maximally match '72'" do
218
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
219
219
  :confidence => 1,
220
220
  :utterance => '72',
221
221
  :interpretation => 'dtmf-7 dtmf-2'
@@ -255,16 +255,16 @@ module RubySpeech
255
255
  end
256
256
  end
257
257
 
258
- it "should match '652'" do
259
- expected_match = GRXML::Match.new :mode => :dtmf,
258
+ it "should maximally match '652'" do
259
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
260
260
  :confidence => 1,
261
261
  :utterance => '652',
262
262
  :interpretation => 'dtmf-6 dtmf-5 dtmf-2'
263
263
  subject.match('652').should == expected_match
264
264
  end
265
265
 
266
- it "should match '728'" do
267
- expected_match = GRXML::Match.new :mode => :dtmf,
266
+ it "should maximally match '728'" do
267
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
268
268
  :confidence => 1,
269
269
  :utterance => '728',
270
270
  :interpretation => 'dtmf-7 dtmf-2 dtmf-8'
@@ -297,16 +297,16 @@ module RubySpeech
297
297
  end
298
298
  end
299
299
 
300
- it "should match '*6'" do
301
- expected_match = GRXML::Match.new :mode => :dtmf,
300
+ it "should maximally match '*6'" do
301
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
302
302
  :confidence => 1,
303
303
  :utterance => '*6',
304
304
  :interpretation => 'dtmf-star dtmf-6'
305
305
  subject.match('*6').should == expected_match
306
306
  end
307
307
 
308
- it "should match '*7'" do
309
- expected_match = GRXML::Match.new :mode => :dtmf,
308
+ it "should maximally match '*7'" do
309
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
310
310
  :confidence => 1,
311
311
  :utterance => '*7',
312
312
  :interpretation => 'dtmf-star dtmf-7'
@@ -337,24 +337,26 @@ module RubySpeech
337
337
  end
338
338
  end
339
339
 
340
- it "should match '6*'" do
341
- expected_match = GRXML::Match.new :mode => :dtmf,
340
+ it "should maximally match '6*'" do
341
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
342
342
  :confidence => 1,
343
343
  :utterance => '6*',
344
344
  :interpretation => 'dtmf-6 dtmf-star'
345
345
  subject.match('6*').should == expected_match
346
346
  end
347
347
 
348
- it "should match '7*'" do
349
- expected_match = GRXML::Match.new :mode => :dtmf,
348
+ it "should maximally match '7*'" do
349
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
350
350
  :confidence => 1,
351
351
  :utterance => '7*',
352
352
  :interpretation => 'dtmf-7 dtmf-star'
353
353
  subject.match('7*').should == expected_match
354
354
  end
355
355
 
356
- it "should potentially match '6'" do
357
- subject.match('6').should == GRXML::PotentialMatch.new
356
+ %w{6 7}.each do |input|
357
+ it "should potentially match '#{input}'" do
358
+ subject.match(input).should == GRXML::PotentialMatch.new
359
+ end
358
360
  end
359
361
 
360
362
  it "should potentially match '7'" do
@@ -380,8 +382,8 @@ module RubySpeech
380
382
  end
381
383
  end
382
384
 
383
- it "should match '166'" do
384
- expected_match = GRXML::Match.new :mode => :dtmf,
385
+ it "should maximally match '166'" do
386
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
385
387
  :confidence => 1,
386
388
  :utterance => '166',
387
389
  :interpretation => 'dtmf-1 dtmf-6 dtmf-6'
@@ -413,8 +415,8 @@ module RubySpeech
413
415
  end
414
416
  end
415
417
 
416
- it "should match '661'" do
417
- expected_match = GRXML::Match.new :mode => :dtmf,
418
+ it "should maximally match '661'" do
419
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
418
420
  :confidence => 1,
419
421
  :utterance => '661',
420
422
  :interpretation => 'dtmf-6 dtmf-6 dtmf-1'
@@ -446,11 +448,18 @@ module RubySpeech
446
448
  end
447
449
  end
448
450
 
451
+ it "should maximally match '1666'" do
452
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
453
+ :confidence => 1,
454
+ :utterance => '1666',
455
+ :interpretation => 'dtmf-1 dtmf-6 dtmf-6 dtmf-6'
456
+ subject.match('1666').should == expected_match
457
+ end
458
+
449
459
  {
450
460
  '1' => 'dtmf-1',
451
461
  '16' => 'dtmf-1 dtmf-6',
452
462
  '166' => 'dtmf-1 dtmf-6 dtmf-6',
453
- '1666' => 'dtmf-1 dtmf-6 dtmf-6 dtmf-6'
454
463
  }.each_pair do |input, interpretation|
455
464
  it "should match '#{input}'" do
456
465
  expected_match = GRXML::Match.new :mode => :dtmf,
@@ -486,8 +495,8 @@ module RubySpeech
486
495
  '661' => 'dtmf-6 dtmf-6 dtmf-1',
487
496
  '6661' => 'dtmf-6 dtmf-6 dtmf-6 dtmf-1'
488
497
  }.each_pair do |input, interpretation|
489
- it "should match '#{input}'" do
490
- expected_match = GRXML::Match.new :mode => :dtmf,
498
+ it "should maximally match '#{input}'" do
499
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
491
500
  :confidence => 1,
492
501
  :utterance => input,
493
502
  :interpretation => interpretation
@@ -564,8 +573,8 @@ module RubySpeech
564
573
  '6661' => 'dtmf-6 dtmf-6 dtmf-6 dtmf-1',
565
574
  '66661' => 'dtmf-6 dtmf-6 dtmf-6 dtmf-6 dtmf-1'
566
575
  }.each_pair do |input, interpretation|
567
- it "should match '#{input}'" do
568
- expected_match = GRXML::Match.new :mode => :dtmf,
576
+ it "should maximally match '#{input}'" do
577
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
569
578
  :confidence => 1,
570
579
  :utterance => input,
571
580
  :interpretation => interpretation
@@ -617,8 +626,8 @@ module RubySpeech
617
626
  '5678#' => 'dtmf-5 dtmf-6 dtmf-7 dtmf-8 dtmf-pound',
618
627
  '1111#' => 'dtmf-1 dtmf-1 dtmf-1 dtmf-1 dtmf-pound'
619
628
  }.each_pair do |input, interpretation|
620
- it "should match '#{input}'" do
621
- expected_match = GRXML::Match.new :mode => :dtmf,
629
+ it "should maximally match '#{input}'" do
630
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
622
631
  :confidence => 1,
623
632
  :utterance => input,
624
633
  :interpretation => interpretation
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ module RubySpeech
4
+ module GRXML
5
+ describe MaxMatch do
6
+ it_behaves_like "match"
7
+
8
+ it { should be_a Match }
9
+
10
+ describe "equality" do
11
+ it "should never be equal to a MaxMatch" do
12
+ described_class.new.should_not eql(Match.new)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,43 @@
1
+ shared_examples_for "match" do
2
+ subject do
3
+ described_class.new :mode => :dtmf,
4
+ :confidence => 1,
5
+ :utterance => '6',
6
+ :interpretation => 'foo'
7
+ end
8
+
9
+ its(:mode) { should == :dtmf }
10
+ its(:confidence) { should == 1 }
11
+ its(:utterance) { should == '6' }
12
+ its(:interpretation) { should == 'foo' }
13
+
14
+ describe "equality" do
15
+ it "should be equal when mode, confidence, utterance and interpretation are the same" do
16
+ described_class.new(:mode => :dtmf, :confidence => 1, :utterance => '6', :interpretation => 'foo').should == described_class.new(:mode => :dtmf, :confidence => 1, :utterance => '6', :interpretation => 'foo')
17
+ end
18
+
19
+ describe "when the mode is different" do
20
+ it "should not be equal" do
21
+ described_class.new(:mode => :dtmf).should_not == described_class.new(:mode => :speech)
22
+ end
23
+ end
24
+
25
+ describe "when the confidence is different" do
26
+ it "should not be equal" do
27
+ described_class.new(:confidence => 1).should_not == described_class.new(:confidence => 0)
28
+ end
29
+ end
30
+
31
+ describe "when the utterance is different" do
32
+ it "should not be equal" do
33
+ described_class.new(:utterance => '6').should_not == described_class.new(:utterance => 'foo')
34
+ end
35
+ end
36
+
37
+ describe "when the interpretation is different" do
38
+ it "should not be equal" do
39
+ described_class.new(:interpretation => 'foo').should_not == described_class.new(:interpretation => 'bar')
40
+ end
41
+ end
42
+ end
43
+ end
@@ -14,13 +14,7 @@ class SpeechDocMatcher
14
14
  end
15
15
 
16
16
  def subject=(s)
17
- if s.is_a? Nokogiri::XML::Document
18
- @subject = s
19
- else
20
- doc = Nokogiri::XML::Document.new
21
- doc << s.to_xml
22
- @subject = doc
23
- end
17
+ @subject = Nokogiri::XML(s.to_xml)
24
18
  end
25
19
 
26
20
  def failure_message
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_speech
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Langfeld
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-27 00:00:00.000000000 Z
11
+ date: 2013-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: niceogiri
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '1.1'
20
20
  - - '>='
21
21
  - !ruby/object:Gem::Version
22
- version: 1.1.1
22
+ version: 1.1.2
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: '1.1'
30
30
  - - '>='
31
31
  - !ruby/object:Gem::Version
32
- version: 1.1.1
32
+ version: 1.1.2
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: nokogiri
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -238,6 +238,7 @@ files:
238
238
  - lib/ruby_speech/grxml/item.rb
239
239
  - lib/ruby_speech/grxml/match.rb
240
240
  - lib/ruby_speech/grxml/matcher.rb
241
+ - lib/ruby_speech/grxml/max_match.rb
241
242
  - lib/ruby_speech/grxml/no_match.rb
242
243
  - lib/ruby_speech/grxml/one_of.rb
243
244
  - lib/ruby_speech/grxml/potential_match.rb
@@ -271,6 +272,7 @@ files:
271
272
  - spec/ruby_speech/grxml/item_spec.rb
272
273
  - spec/ruby_speech/grxml/match_spec.rb
273
274
  - spec/ruby_speech/grxml/matcher_spec.rb
275
+ - spec/ruby_speech/grxml/max_match_spec.rb
274
276
  - spec/ruby_speech/grxml/no_match_spec.rb
275
277
  - spec/ruby_speech/grxml/one_of_spec.rb
276
278
  - spec/ruby_speech/grxml/potential_match_spec.rb
@@ -296,6 +298,7 @@ files:
296
298
  - spec/ruby_speech/ssml_spec.rb
297
299
  - spec/ruby_speech_spec.rb
298
300
  - spec/spec_helper.rb
301
+ - spec/support/match_examples.rb
299
302
  - spec/support/matchers.rb
300
303
  homepage: https://github.com/benlangfeld/ruby_speech
301
304
  licenses: []
@@ -325,6 +328,7 @@ test_files:
325
328
  - spec/ruby_speech/grxml/item_spec.rb
326
329
  - spec/ruby_speech/grxml/match_spec.rb
327
330
  - spec/ruby_speech/grxml/matcher_spec.rb
331
+ - spec/ruby_speech/grxml/max_match_spec.rb
328
332
  - spec/ruby_speech/grxml/no_match_spec.rb
329
333
  - spec/ruby_speech/grxml/one_of_spec.rb
330
334
  - spec/ruby_speech/grxml/potential_match_spec.rb
@@ -350,5 +354,6 @@ test_files:
350
354
  - spec/ruby_speech/ssml_spec.rb
351
355
  - spec/ruby_speech_spec.rb
352
356
  - spec/spec_helper.rb
357
+ - spec/support/match_examples.rb
353
358
  - spec/support/matchers.rb
354
359
  has_rdoc: