jsgf 0.2.1 → 0.3
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 +8 -0
- data/lib/jsgf/grammar.rb +33 -0
- data/lib/jsgf/optional.rb +8 -0
- data/test/jsgf/alternation.rb +15 -0
- data/test/jsgf/grammar.rb +37 -1
- data/test/jsgf/optional.rb +15 -0
- data/test/jsgf/tokenizer.rb +12 -0
- 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: a35679fd0c76d2953a7e6bf557f145e0fff63a63
|
4
|
+
data.tar.gz: 04a9e77a8561aa76bf73e4977933adfdec8f9f13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43fd8dc5e6757e7c9cc3753784e1fecda9cf4fda61049c54eeb45a0e4b48cf318d1f953ecd2b3b454be709f081ab6d61c885e73a03b24a8bcc1d7bba708563da
|
7
|
+
data.tar.gz: a5d9a59efb08497e731232b6554aaa9015cc8cb8fdc71b7444fdcad6c769789d34d42a2e23643edf9be9814da5dba0eca3c6b663f9e95edd8812139f3609ca6e
|
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.
|
7
|
+
spec.version = '0.3'
|
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,5 +1,7 @@
|
|
1
1
|
module JSGF
|
2
2
|
class Alternation
|
3
|
+
include Enumerable
|
4
|
+
|
3
5
|
attr_reader :elements
|
4
6
|
attr_accessor :optional
|
5
7
|
attr_reader :tags
|
@@ -10,6 +12,12 @@ module JSGF
|
|
10
12
|
@tags = []
|
11
13
|
end
|
12
14
|
|
15
|
+
# @group Enumerable
|
16
|
+
def each(*args, &block)
|
17
|
+
elements.each(*args, &block)
|
18
|
+
end
|
19
|
+
# @endgroup
|
20
|
+
|
13
21
|
def push(*args)
|
14
22
|
@elements.push *args
|
15
23
|
end
|
data/lib/jsgf/grammar.rb
CHANGED
@@ -8,6 +8,7 @@ module JSGF
|
|
8
8
|
attr_reader :version
|
9
9
|
|
10
10
|
def initialize(name:nil, character_encoding:nil, locale:nil, private_rules:{}, public_rules:{}, version:nil)
|
11
|
+
raise ArgumentError, "Grammar requires a name" unless name
|
11
12
|
@character_encoding = character_encoding
|
12
13
|
@locale = locale
|
13
14
|
@grammar_name = name
|
@@ -16,12 +17,30 @@ module JSGF
|
|
16
17
|
@version = version
|
17
18
|
end
|
18
19
|
|
20
|
+
# @!attribute roots
|
21
|
+
# @return [Hash] the set of public rules that comprise the roots of the {Grammar} tree
|
22
|
+
def roots
|
23
|
+
# Descend through the public rule trees to see if they reference each other
|
24
|
+
root_rules = public_rules.dup
|
25
|
+
public_rules.each do |(name, rule)|
|
26
|
+
names = find_rule_names(rule).compact
|
27
|
+
root_rules.delete_if {|k,v| names.include?(k)}
|
28
|
+
end
|
29
|
+
root_rules.empty? ? nil : root_rules
|
30
|
+
end
|
31
|
+
|
19
32
|
# @!attribute rules
|
20
33
|
# @return [Hash] Returns a {Hash} of the public and private rules, keyed by rule name
|
21
34
|
def rules
|
22
35
|
@public_rules.merge(@private_rules)
|
23
36
|
end
|
24
37
|
|
38
|
+
# @!attribute version
|
39
|
+
# @return [String] the JSGF specification version
|
40
|
+
def version
|
41
|
+
@version || 'V1.0'
|
42
|
+
end
|
43
|
+
|
25
44
|
def to_s
|
26
45
|
private_rule_array = @private_rules.map do |(name, rule)|
|
27
46
|
atoms = rule.map {|a| unparse_atom(a) }.join(' ')
|
@@ -36,6 +55,20 @@ module JSGF
|
|
36
55
|
end
|
37
56
|
|
38
57
|
private
|
58
|
+
# Expand the given rule and collect any references to other rules
|
59
|
+
# @param rule [Array] the right-hand-side of the rule to expand
|
60
|
+
# @return [Array] an array of referenced rule names
|
61
|
+
def find_rule_names(rule)
|
62
|
+
case rule
|
63
|
+
when Alternation, Array, Optional
|
64
|
+
rule.flat_map {|a| find_rule_names(a) }
|
65
|
+
when Hash
|
66
|
+
rule[:name]
|
67
|
+
else
|
68
|
+
raise StandardError, "Unkown atom #{rule.class}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
39
72
|
# Generate the grammar name header line
|
40
73
|
def grammar_header
|
41
74
|
"grammar #{grammar_name};"
|
data/lib/jsgf/optional.rb
CHANGED
@@ -1,11 +1,19 @@
|
|
1
1
|
module JSGF
|
2
2
|
class Optional
|
3
|
+
include Enumerable
|
4
|
+
|
3
5
|
attr_reader :elements
|
4
6
|
|
5
7
|
def initialize(*args)
|
6
8
|
@elements = args
|
7
9
|
end
|
8
10
|
|
11
|
+
# @group Enumerable
|
12
|
+
def each(*args, &block)
|
13
|
+
elements.each(*args, &block)
|
14
|
+
end
|
15
|
+
# @endgroup
|
16
|
+
|
9
17
|
def optional
|
10
18
|
true
|
11
19
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'jsgf/parser'
|
3
|
+
|
4
|
+
describe JSGF::Alternation do
|
5
|
+
it 'must be enumerable' do
|
6
|
+
alternation = JSGF::Alternation.new('one', 'two', 'three')
|
7
|
+
alternation.all? {|a| a}
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'must be mappable' do
|
11
|
+
alternation = JSGF::Alternation.new('one', 'two', 'three')
|
12
|
+
i = 0
|
13
|
+
alternation.map {|a| i = i + 1 }.must_equal [1,2,3]
|
14
|
+
end
|
15
|
+
end
|
data/test/jsgf/grammar.rb
CHANGED
@@ -2,9 +2,45 @@ require 'minitest/autorun'
|
|
2
2
|
require 'jsgf/parser'
|
3
3
|
|
4
4
|
describe JSGF::Grammar do
|
5
|
+
it 'must require a grammar name' do
|
6
|
+
-> { JSGF::Grammar.new }.must_raise ArgumentError
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'must have a default version' do
|
10
|
+
JSGF::Grammar.new(name:'test').version.must_equal 'V1.0'
|
11
|
+
JSGF::Grammar.new(name:'test').to_s.must_equal "#JSGF V1.0;\ngrammar test;"
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'roots' do
|
15
|
+
it 'must not have roots without public rules' do
|
16
|
+
grammar = JSGF::Parser.new('#JSGF V1.0; grammar test; <rule>=one | two | three;').parse
|
17
|
+
grammar.roots.must_equal nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'must have one root for one public rule' do
|
21
|
+
grammar = JSGF::Parser.new('#JSGF V1.0; grammar test; public <rule>=one | two | three;').parse
|
22
|
+
grammar.roots.size.must_equal 1
|
23
|
+
grammar.roots['rule'].must_be_kind_of Array
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'must have two roots for two public rules' do
|
27
|
+
grammar = JSGF::Parser.new('#JSGF V1.0; grammar test; public <rule1>=one | two | three; public <rule2>=four five;').parse
|
28
|
+
grammar.roots.size.must_equal 2
|
29
|
+
grammar.roots['rule1'].must_be_kind_of Array
|
30
|
+
grammar.roots['rule2'].must_be_kind_of Array
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'must ignore nested roots' do
|
34
|
+
grammar = JSGF::Parser.new('#JSGF V1.0; grammar test; public <rule1>=one | two | three; public <rule2>=four <rule3>; public <rule3>=five;').parse
|
35
|
+
grammar.roots.size.must_equal 2
|
36
|
+
grammar.roots['rule1'].must_be_kind_of Array
|
37
|
+
grammar.roots['rule2'].must_be_kind_of Array
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
5
41
|
it 'must unparse a header' do
|
6
42
|
grammar = JSGF::Parser.new('#JSGF; grammar header_grammar;').parse
|
7
|
-
grammar.to_s.must_equal "#JSGF;\ngrammar header_grammar;"
|
43
|
+
grammar.to_s.must_equal "#JSGF V1.0;\ngrammar header_grammar;"
|
8
44
|
end
|
9
45
|
|
10
46
|
it 'must unparse a header with a version' do
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'jsgf/parser'
|
3
|
+
|
4
|
+
describe JSGF::Optional do
|
5
|
+
it 'must be enumerable' do
|
6
|
+
optional = JSGF::Optional.new('one', 'two', 'three')
|
7
|
+
optional.all? {|a| a}
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'must be mappable' do
|
11
|
+
optional = JSGF::Optional.new('one', 'two', 'three')
|
12
|
+
i = 0
|
13
|
+
optional.map {|a| i = i + 1 }.must_equal [1,2,3]
|
14
|
+
end
|
15
|
+
end
|
data/test/jsgf/tokenizer.rb
CHANGED
@@ -38,5 +38,17 @@ describe JSGF::Tokenizer do
|
|
38
38
|
it 'must skip C-style comments' do
|
39
39
|
JSGF::Tokenizer.new(' /* a comment */ some_token ').next_token.must_equal [:TOKEN, 'some_token']
|
40
40
|
end
|
41
|
+
|
42
|
+
it 'must skip multi-line C-style comments' do
|
43
|
+
JSGF::Tokenizer.new(" /* a\nmulti-line\ncomment */ some_token ").next_token.must_equal [:TOKEN, 'some_token']
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'must skip single-line C++ comments' do
|
47
|
+
JSGF::Tokenizer.new(' some_token // a comment ').next_token.must_equal [:TOKEN, 'some_token']
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'must skip single-line C++ comments at the beginning of a line' do
|
51
|
+
JSGF::Tokenizer.new(" some_token // \n//a comment ").next_token.must_equal [:TOKEN, 'some_token']
|
52
|
+
end
|
41
53
|
end
|
42
54
|
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
|
+
version: '0.3'
|
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-01-
|
11
|
+
date: 2015-01-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -58,7 +58,9 @@ files:
|
|
58
58
|
- lib/jsgf/parser.rb
|
59
59
|
- lib/jsgf/repetition.rb
|
60
60
|
- lib/jsgf/tokenizer.rb
|
61
|
+
- test/jsgf/alternation.rb
|
61
62
|
- test/jsgf/grammar.rb
|
63
|
+
- test/jsgf/optional.rb
|
62
64
|
- test/jsgf/parser.rb
|
63
65
|
- test/jsgf/tokenizer.rb
|
64
66
|
homepage: http://github.com/bfoz/jsgf-ruby
|
@@ -86,6 +88,8 @@ signing_key:
|
|
86
88
|
specification_version: 4
|
87
89
|
summary: Java Speech Grammar Format
|
88
90
|
test_files:
|
91
|
+
- test/jsgf/alternation.rb
|
89
92
|
- test/jsgf/grammar.rb
|
93
|
+
- test/jsgf/optional.rb
|
90
94
|
- test/jsgf/parser.rb
|
91
95
|
- test/jsgf/tokenizer.rb
|