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 +4 -4
- data/jsgf.gemspec +1 -1
- data/lib/jsgf/alternation.rb +6 -7
- data/lib/jsgf/atom.rb +34 -0
- data/lib/jsgf/builder.rb +3 -9
- data/lib/jsgf/grammar.rb +3 -2
- data/lib/jsgf/parser.rb +6 -9
- data/lib/jsgf/rule.rb +13 -0
- data/test/jsgf/alternation.rb +1 -1
- data/test/jsgf/atom.rb +31 -0
- data/test/jsgf/builder.rb +3 -3
- data/test/jsgf/parser.rb +9 -7
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae316ae11c63ab1272f04970e188ac162df75dd5
|
4
|
+
data.tar.gz: 4e960c23772bc117c4b7955144b72eeffc2ac3b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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}
|
data/lib/jsgf/alternation.rb
CHANGED
@@ -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
|
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]
|
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 =
|
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
|
data/test/jsgf/alternation.rb
CHANGED
@@ -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 [
|
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 [
|
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 [
|
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 [
|
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
|
68
|
-
alternation.elements[1].must_equal
|
69
|
-
alternation.elements[2].must_equal
|
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
|
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 [
|
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:[]},
|
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 [
|
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:
|
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-
|
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
|