jsgf 0.4 → 0.4.1

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: 9e90d5a58e0adaadef490c11911c9443e14fb0a5
4
- data.tar.gz: fd7deb3081c443f76c4505b72e1f18397d1ce183
3
+ metadata.gz: ae316ae11c63ab1272f04970e188ac162df75dd5
4
+ data.tar.gz: 4e960c23772bc117c4b7955144b72eeffc2ac3b5
5
5
  SHA512:
6
- metadata.gz: 28d2d63a8f51d32efdcf597877e18ce86d45bded53077ef40e2908364af21fa23eb7b1f90262630738c866dd1df79d0a193bea81e04cb9619685bfbe9541645a
7
- data.tar.gz: 132cefa593326e8b2d7c603746c8e114a1872de5bb566a5fa1fe8ec76ff5127492a8e28e9fa6f686ba4d1641071732399459bb976cb4a27c2b10592306a98d28
6
+ metadata.gz: 42d12240171fd99346507d7850f73e880c321337bf50d421cf4411e5a1d300badc2c4459491fcacc2c97716f739616488bb74c4c95a79912bae51dbfa3617536
7
+ data.tar.gz: 4e34672b1e1cd91993f55d069270e692fddb16590610934cce1136b04c9c10b21c77c369afb55269802b547d5e562e5cc7c36a305d9678803468e5221b7c014e
data/jsgf.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "jsgf"
7
- spec.version = '0.4'
7
+ spec.version = '0.4.1'
8
8
  spec.authors = ["Brandon Fosdick"]
9
9
  spec.email = ["bfoz@bfoz.net"]
10
10
  spec.summary = %q{Java Speech Grammar Format}
@@ -1,3 +1,5 @@
1
+ require_relative 'rule'
2
+
1
3
  module JSGF
2
4
  class Alternation
3
5
  include Enumerable
@@ -9,12 +11,7 @@ module JSGF
9
11
  def initialize(*args)
10
12
  @elements = args.map do |a|
11
13
  case a
12
- when String
13
- case a
14
- when /\<(.*)\>/, /:(.*)/ then {name:$1, weight:1.0, tags:[]}
15
- else
16
- {atom:a, weight:1.0, tags:[]}
17
- end
14
+ when String then Rule.parse_atom(a)
18
15
  when Symbol then {name:a.to_s, weight:1.0, tags:[]}
19
16
  else
20
17
  a
@@ -35,12 +32,14 @@ module JSGF
35
32
  @elements.push *args
36
33
  end
37
34
 
35
+ # @group Attributes
38
36
  def size
39
37
  @elements.size
40
38
  end
41
39
 
42
40
  def weights
43
- @elements.map {|a| a[:weight]}
41
+ @elements.map {|a| a.respond_to?(:weight) ? a.weight : a[:weight]}
44
42
  end
43
+ # @endgroup
45
44
  end
46
45
  end
data/lib/jsgf/atom.rb ADDED
@@ -0,0 +1,34 @@
1
+ module JSGF
2
+ class Atom
3
+ # @!attribute atom
4
+ # @return [String] the atom of the {Atom}
5
+ attr_accessor :atom
6
+
7
+ # @!attribute weight
8
+ # @return [Number] the {Atom}'s weight, when part of an {Alternation}. Defaults to 1.0.
9
+ attr_accessor :weight
10
+
11
+ # @!attribute tags
12
+ # @return [Array] the collection of tags to be stored with the {Atom}
13
+ attr_accessor :tags
14
+
15
+ # @param atom [String] the atom of the {Atom}
16
+ # @param weight [Number] the weight to be used when part of an {Alternation}. Valid values are 0..1.0.
17
+ # @param tags [Array] any tags to be stored with the {Atom}
18
+ def initialize(atom, *tags, weight:nil)
19
+ @atom = atom
20
+ @tags = tags
21
+ @weight = (weight && (weight != 1.0)) ? weight : nil
22
+ end
23
+
24
+ def eql?(other)
25
+ @atom.eql?(other.atom) && @tags.eql?(other.tags) && @weight.eql?(other.weight)
26
+ end
27
+ alias == eql?
28
+
29
+ # Stringify in a manner suitable for output to a JSGF file
30
+ def to_s
31
+ [(weight && (weight != 1.0)) ? "/#{weight}/" : nil, atom, *tags].compact.join(' ')
32
+ end
33
+ end
34
+ end
data/lib/jsgf/builder.rb CHANGED
@@ -37,16 +37,10 @@ module JSGF
37
37
  def rule(**options)
38
38
  options.each do |name, v|
39
39
  @rules[name.to_s] = case v
40
- when Array then [Alternation.new(*v)]
41
- when Symbol then [{name:v.to_s, weight:1.0, tags:[]}]
40
+ when Array then Rule.new [Alternation.new(*v)]
41
+ when Symbol then Rule.new [{name:v.to_s, weight:1.0, tags:[]}]
42
42
  else
43
- v.split(' ').map do |a|
44
- case a
45
- when /\<(.*)\>/, /:(.*)/ then {name:$1, weight:1.0, tags:[]}
46
- else
47
- {atom:a, weight:1.0, tags:[]}
48
- end
49
- end
43
+ v.split(' ').map {|a| Rule.parse_atom(a) }
50
44
  end
51
45
  end
52
46
  end
data/lib/jsgf/grammar.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require_relative 'atom'
1
2
  require_relative 'optional'
2
3
 
3
4
  module JSGF
@@ -26,6 +27,7 @@ module JSGF
26
27
  case rule
27
28
  when Alternation, Array, Optional
28
29
  rule.flat_map {|a| find_rule_names(a) }
30
+ when Atom then []
29
31
  when Hash
30
32
  rule[:name]
31
33
  else
@@ -110,13 +112,12 @@ module JSGF
110
112
  when Alternation
111
113
  s = atom.elements.map {|a| unparse_atom(a, nested:true)}.join(' | ')
112
114
  atom.optional ? ('[' + s + ']') : s
115
+ when Atom then atom.to_s
113
116
  when Optional then '[' + atom.elements.map {|a| unparse_atom(a, nested:nested)}.join(' | ') + ']'
114
117
  else
115
118
  weight = (atom[:weight] != 1.0) ? "/#{atom[:weight]}/" : nil
116
119
  if atom[:name]
117
120
  [weight, '<' + atom[:name] + '>'].compact.join(' ')
118
- else
119
- [weight, atom[:atom], *atom[:tags]].compact.join(' ')
120
121
  end
121
122
  end
122
123
  end
data/lib/jsgf/parser.rb CHANGED
@@ -11,6 +11,7 @@ require_relative 'alternation'
11
11
  require_relative 'grammar'
12
12
  require_relative 'optional'
13
13
  require_relative 'repetition'
14
+ require_relative 'rule'
14
15
  require_relative 'tokenizer'
15
16
 
16
17
  module JSGF
@@ -47,10 +48,6 @@ def define_optional(*args)
47
48
  end
48
49
  end
49
50
 
50
- def define_atom(atom, weight=1.0, tags=[])
51
- {atom:atom, weight:weight, tags:[]}
52
- end
53
-
54
51
  def define_rule(name, visibility=:private, *args)
55
52
  r = {name: name, visibility:visibility, atoms:args.flatten}
56
53
  @rules[name] = r
@@ -70,9 +67,9 @@ def parse
70
67
 
71
68
  @rules.each do |(k,v)|
72
69
  if v[:visibility] == :private
73
- @private_rules[k] = v[:atoms]
70
+ @private_rules[k] = JSGF::Rule.new(v[:atoms])
74
71
  else
75
- @public_rules[k] = v[:atoms]
72
+ @public_rules[k] = JSGF::Rule.new(v[:atoms])
76
73
  end
77
74
  end
78
75
 
@@ -353,7 +350,7 @@ end
353
350
  # reduce 23 omitted
354
351
 
355
352
  def _reduce_24(val, _values, result)
356
- val[0][:tags].push(val[1]); result = val[0]
353
+ val[0].tags.push(val[1]); result = val[0]
357
354
  result
358
355
  end
359
356
 
@@ -365,7 +362,7 @@ def _reduce_26(val, _values, result)
365
362
  end
366
363
 
367
364
  def _reduce_27(val, _values, result)
368
- val[1][:weight] = val.first[1..-2].to_f; result = val[1]
365
+ val[1].respond_to?(:weight) ? (val[1].weight = val.first[1..-2].to_f) : (val[1][:weight] = val.first[1..-2].to_f); result = val[1]
369
366
  result
370
367
  end
371
368
 
@@ -384,7 +381,7 @@ def _reduce_31(val, _values, result)
384
381
  end
385
382
 
386
383
  def _reduce_32(val, _values, result)
387
- result = define_atom(val.first)
384
+ result = JSGF::Atom.new(val.first)
388
385
  result
389
386
  end
390
387
 
data/lib/jsgf/rule.rb ADDED
@@ -0,0 +1,13 @@
1
+ module JSGF
2
+ class Rule < Array
3
+ # Convert a string containing a single atom into an {Atom} or a rule reference
4
+ # @param atom [String] the text to parse
5
+ def self.parse_atom(atom)
6
+ case atom
7
+ when /\<(.*)\>/, /:(.*)/ then {name:$1, weight:1.0, tags:[]}
8
+ else
9
+ Atom.new(atom)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -4,7 +4,7 @@ require 'jsgf/parser'
4
4
  describe JSGF::Alternation do
5
5
  it 'must convert string arguments into atoms' do
6
6
  alternation = JSGF::Alternation.new('one', 'two', 'three')
7
- alternation.elements.must_equal [{atom:'one', weight:1.0, tags:[]}, {atom:'two', weight:1.0, tags:[]}, {atom:'three', weight:1.0, tags:[]}]
7
+ alternation.elements.must_equal [Atom.new('one'), Atom.new('two'), Atom.new('three')]
8
8
  end
9
9
 
10
10
  it 'must be enumerable' do
data/test/jsgf/atom.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'minitest/autorun'
2
+ require 'jsgf/atom'
3
+
4
+ describe JSGF::Atom do
5
+ Atom = JSGF::Atom
6
+
7
+ it 'must have a word' do
8
+ Atom.new('test').atom.must_equal 'test'
9
+ end
10
+
11
+ it 'must not have a weight until given a weight' do
12
+ Atom.new('test').weight.must_equal nil
13
+ end
14
+
15
+ it 'must stringify a word' do
16
+ Atom.new('test').to_s.must_equal 'test'
17
+ end
18
+
19
+ it 'must stringify a weight' do
20
+ Atom.new('test', weight:0.5).to_s.must_equal '/0.5/ test'
21
+ end
22
+
23
+ it 'must not stringify a nil weight' do
24
+ Atom.new('test').to_s.must_equal 'test'
25
+ end
26
+
27
+ it 'must not stringify a default weight' do
28
+ Atom.new('test', weight:1.0).to_s.must_equal 'test'
29
+ Atom.new('test', weight:1).to_s.must_equal 'test'
30
+ end
31
+ end
data/test/jsgf/builder.rb CHANGED
@@ -20,13 +20,13 @@ describe JSGF::Builder do
20
20
  end
21
21
 
22
22
  grammar.rules.size.must_equal 1
23
- grammar.rules['rule1'].must_equal [{atom:'one', weight:1.0, tags:[]}]
23
+ grammar.rules['rule1'].must_equal [Atom.new('one')]
24
24
  end
25
25
 
26
26
  it 'must build a multi-atom rule' do
27
27
  grammar = JSGF::Builder.build {rule rule1: 'one two' }
28
28
  grammar.rules.size.must_equal 1
29
- grammar.rules['rule1'].must_equal [{atom:'one', weight:1.0, tags:[]}, {atom:'two', weight:1.0, tags:[]}]
29
+ grammar.rules['rule1'].must_equal [Atom.new('one'), Atom.new('two')]
30
30
  end
31
31
 
32
32
  it 'must build a rule with a rule reference as a Symbol' do
@@ -66,7 +66,7 @@ describe JSGF::Builder do
66
66
  end
67
67
  grammar.rules.size.must_equal 1
68
68
  grammar.rules['rule1'].first.must_be_kind_of JSGF::Alternation
69
- grammar.rules['rule1'].first.elements.must_equal [{atom:'one', weight:1.0, tags:[]}, {atom:'two', weight:1.0, tags:[]}]
69
+ grammar.rules['rule1'].first.elements.must_equal [Atom.new('one'), Atom.new('two')]
70
70
  end
71
71
 
72
72
  it 'must build an alternation from an array of rule reference symbols' do
data/test/jsgf/parser.rb CHANGED
@@ -64,9 +64,9 @@ describe JSGF::Parser do
64
64
  alternation = grammar.rules['rule'].first
65
65
  alternation.must_be_kind_of JSGF::Alternation
66
66
  alternation.size.must_equal 3
67
- alternation.elements[0].must_equal Hash[atom:'one', weight:1.0, tags:[]]
68
- alternation.elements[1].must_equal Hash[atom:'two', weight:1.0, tags:[]]
69
- alternation.elements[2].must_equal Hash[atom:'three', weight:1.0, tags:[]]
67
+ alternation.elements[0].must_equal Atom.new('one')
68
+ alternation.elements[1].must_equal Atom.new('two')
69
+ alternation.elements[2].must_equal Atom.new('three')
70
70
  end
71
71
 
72
72
  it 'must parse a weighted alternation' do
@@ -78,7 +78,9 @@ describe JSGF::Parser do
78
78
  alternation.must_be_kind_of JSGF::Alternation
79
79
  alternation.size.must_equal 3
80
80
  alternation.weights.must_equal [0.5, 0.25, 0.25]
81
- alternation.elements[0].must_equal Hash[atom:'one', weight:0.5, tags:[]]
81
+ alternation.elements[0].must_equal Atom.new('one', weight:0.5)
82
+ alternation.elements[1].must_equal Atom.new('two', weight:0.25)
83
+ alternation.elements[2].must_equal Atom.new('three', weight:0.25)
82
84
  end
83
85
 
84
86
  it 'must parse a grouped alternation' do
@@ -127,7 +129,7 @@ describe JSGF::Parser do
127
129
  grammar.rules.size.must_equal 2
128
130
  grammar.rules.keys.must_equal ['rule', 'rule1']
129
131
  grammar.rules['rule'].must_equal [{name:'rule1', weight:1.0, tags:[]}]
130
- grammar.rules['rule1'].must_equal [{atom:'one', weight:1.0, tags:[]}]
132
+ grammar.rules['rule1'].must_equal [Atom.new('one')]
131
133
  end
132
134
 
133
135
  it 'must parse a weighted rule reference' do
@@ -137,9 +139,9 @@ describe JSGF::Parser do
137
139
 
138
140
  grammar.rules['rule'].size.must_equal 1
139
141
  grammar.rules['rule'].first.must_be_kind_of JSGF::Alternation
140
- grammar.rules['rule'].first.elements.must_equal [{name:'rule1', weight:0.5, tags:[]}, {atom:'two', weight:0.5, tags:[]}]
142
+ grammar.rules['rule'].first.elements.must_equal [{name:'rule1', weight:0.5, tags:[]}, Atom.new('two', weight:0.5)]
141
143
 
142
- grammar.rules['rule1'].must_equal [{atom:'one', weight:1.0, tags:[]}]
144
+ grammar.rules['rule1'].must_equal [Atom.new('one')]
143
145
  end
144
146
  end
145
147
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsgf
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.4'
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Fosdick
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-08 00:00:00.000000000 Z
11
+ date: 2015-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,13 +53,16 @@ files:
53
53
  - jsgf.gemspec
54
54
  - lib/jsgf.rb
55
55
  - lib/jsgf/alternation.rb
56
+ - lib/jsgf/atom.rb
56
57
  - lib/jsgf/builder.rb
57
58
  - lib/jsgf/grammar.rb
58
59
  - lib/jsgf/optional.rb
59
60
  - lib/jsgf/parser.rb
60
61
  - lib/jsgf/repetition.rb
62
+ - lib/jsgf/rule.rb
61
63
  - lib/jsgf/tokenizer.rb
62
64
  - test/jsgf/alternation.rb
65
+ - test/jsgf/atom.rb
63
66
  - test/jsgf/builder.rb
64
67
  - test/jsgf/grammar.rb
65
68
  - test/jsgf/optional.rb
@@ -91,6 +94,7 @@ specification_version: 4
91
94
  summary: Java Speech Grammar Format
92
95
  test_files:
93
96
  - test/jsgf/alternation.rb
97
+ - test/jsgf/atom.rb
94
98
  - test/jsgf/builder.rb
95
99
  - test/jsgf/grammar.rb
96
100
  - test/jsgf/optional.rb