Class: JSGF::Grammar

Inherits:
Object
  • Object
show all
Defined in:
lib/jsgf/grammar.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name: nil, character_encoding: nil, locale: nil, private_rules: {}, public_rules: {}, rules: nil, version: nil) ⇒ Grammar

Returns a new instance of Grammar.

Raises:

  • (ArgumentError)


36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/jsgf/grammar.rb', line 36

def initialize(name:nil, character_encoding:nil, locale:nil, private_rules:{}, public_rules:{}, rules:nil, version:nil)
    raise ArgumentError, "Grammar requires a name" unless name
    @character_encoding = character_encoding
    @locale = locale
    @grammar_name = name
    @version = version

    if rules and !rules.empty?
	@public_rules, @private_rules = ::JSGF::Grammar.roots(rules)
    else
	@private_rules = private_rules
	@public_rules = public_rules
    end
end

Instance Attribute Details

#character_encodingObject (readonly)

Returns the value of attribute character_encoding.



5
6
7
# File 'lib/jsgf/grammar.rb', line 5

def character_encoding
  @character_encoding
end

#grammar_nameObject (readonly)

Returns the value of attribute grammar_name.



7
8
9
# File 'lib/jsgf/grammar.rb', line 7

def grammar_name
  @grammar_name
end

#localeObject (readonly)

Returns the value of attribute locale.



6
7
8
# File 'lib/jsgf/grammar.rb', line 6

def locale
  @locale
end

#private_rulesObject (readonly)

Returns the value of attribute private_rules.



8
9
10
# File 'lib/jsgf/grammar.rb', line 8

def private_rules
  @private_rules
end

#public_rulesObject (readonly)

Returns the value of attribute public_rules.



9
10
11
# File 'lib/jsgf/grammar.rb', line 9

def public_rules
  @public_rules
end

#rootsObject



53
54
55
56
# File 'lib/jsgf/grammar.rb', line 53

def roots
    r = self.class.roots(public_rules).first
    r.empty? ? nil : r
end

#rulesObject



60
61
62
# File 'lib/jsgf/grammar.rb', line 60

def rules
    @public_rules.merge(@private_rules)
end

#versionObject



66
67
68
# File 'lib/jsgf/grammar.rb', line 66

def version
  @version
end

Class Method Details

.find_rule_names(rule) ⇒ Array

Expand the given rule and collect any references to other rules

Parameters:

  • rule (Array)

    the right-hand-side of the rule to expand

Returns:

  • (Array)

    an array of referenced rule names



25
26
27
28
29
30
31
32
33
34
# File 'lib/jsgf/grammar.rb', line 25

def self.find_rule_names(rule)
    case rule
	when Alternation, Array, Optional
	    rule.flat_map {|a| find_rule_names(a) }
	when Hash
	    rule[:name]
	else
	    raise StandardError, "Unkown atom #{rule.class}"
    end
end

.roots(rules) ⇒ Array<Hash,Hash>

Returns the set of root and non-root rules from the given set of rules.

Parameters:

  • rules (Hash)

    the rules to search

Returns:

  • (Array<Hash,Hash>)

    the set of root and non-root rules from the given set of rules



14
15
16
17
18
19
20
# File 'lib/jsgf/grammar.rb', line 14

def self.roots(rules)
    # Descend through the rule trees to see if they reference each other.
    #  Root rules aren't referenced by any other rule.
    names = rules.flat_map {|(name,rule)| find_rule_names(rule)}.compact.uniq
    left, right = rules.partition {|name, rule| names.include?(name) }
    [Hash[right], Hash[left]]
end

Instance Method Details

#to_sObject



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/jsgf/grammar.rb', line 70

def to_s
    private_rule_array = @private_rules.map do |(name, rule)|
	atoms = rule.map {|a| unparse_atom(a) }.join(' ')
	"<#{name}> = #{atoms};"
    end
    public_rule_array = @public_rules.map do |(name, rule)|
	atoms = rule.map {|a| unparse_atom(a) }.join(' ')
	"public <#{name}> = #{atoms};"
    end

    [header, grammar_header, *public_rule_array, *private_rule_array].join("\n")
end

#write(file) ⇒ Object

Write the JSGF::Grammar to a file or an IO stream

Parameters:

  • file (String, IO)

    a filename, or an IO stream, to write to



85
86
87
88
89
90
91
# File 'lib/jsgf/grammar.rb', line 85

def write(file)
    if file.is_a?(String)
	File.write(file, self.to_s)
    else
	file.write(self.to_s)
    end
end