jsgf 0.2.1 → 0.3

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: e5f37d8d1978f31b192515183e6be841c83f4dc4
4
- data.tar.gz: 3179b3009527599016cafec61255e4d38003f841
3
+ metadata.gz: a35679fd0c76d2953a7e6bf557f145e0fff63a63
4
+ data.tar.gz: 04a9e77a8561aa76bf73e4977933adfdec8f9f13
5
5
  SHA512:
6
- metadata.gz: 17d0b2333de1dd3ee537f091b79fe4aaa44eec199528c14af461a328fbd009ee5f5976187bfc6c7a6a3d077c41d8bedaaf782760d653bec7503bd3e89196beaf
7
- data.tar.gz: f9f966bd54797f0aa5e49fbe60b5ebd015d9dc9ea3f755ea2053add15a6a83fe2910a2231875309b8409a58750ce8d0d77d6142931f16984b8697cfb55f1f5b5
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.2.1'
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}
@@ -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
@@ -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.2.1
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-07 00:00:00.000000000 Z
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