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 +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
|