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