jsgf 0.4 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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