sentence generator updated.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12762 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
53d317b9ac
commit
a309f10475
|
@ -1,10 +1,202 @@
|
||||||
# sentence generator
|
# sentence generator
|
||||||
|
|
||||||
class SentGen
|
class SentGen
|
||||||
|
def SentGen.each_tree(syntax, sym, limit, &b)
|
||||||
|
SentGen.new(syntax).each_tree(sym, limit, &b)
|
||||||
|
end
|
||||||
|
|
||||||
|
def SentGen.each_string(syntax, sym, limit, &b)
|
||||||
|
SentGen.new(syntax).each_string(sym, limit, &b)
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(syntax)
|
def initialize(syntax)
|
||||||
@syntax = syntax
|
@syntax = syntax
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.expand_syntax(syntax)
|
||||||
|
syntax = remove_underivable_rules(syntax)
|
||||||
|
syntax = expand_justempty_rules(syntax)
|
||||||
|
syntax = remove_emptyable_rules(syntax)
|
||||||
|
syntax = expand_channel_rules(syntax)
|
||||||
|
|
||||||
|
syntax = expand_noalt_rules(syntax)
|
||||||
|
syntax = reorder_rules(syntax)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.remove_underivable_rules(syntax)
|
||||||
|
deribable_syms = {}
|
||||||
|
changed = true
|
||||||
|
while changed
|
||||||
|
changed = false
|
||||||
|
syntax.each {|sym, rules|
|
||||||
|
next if deribable_syms[sym]
|
||||||
|
rules.each {|rhs|
|
||||||
|
if rhs.all? {|e| String === e || deribable_syms[e] }
|
||||||
|
deribable_syms[sym] = true
|
||||||
|
changed = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
result = {}
|
||||||
|
syntax.each {|sym, rules|
|
||||||
|
next if !deribable_syms[sym]
|
||||||
|
rules2 = []
|
||||||
|
rules.each {|rhs|
|
||||||
|
rules2 << rhs if rhs.all? {|e| String === e || deribable_syms[e] }
|
||||||
|
}
|
||||||
|
result[sym] = rules2.uniq
|
||||||
|
}
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.expand_justempty_rules(syntax)
|
||||||
|
justempty_syms = {}
|
||||||
|
changed = true
|
||||||
|
while changed
|
||||||
|
changed = false
|
||||||
|
syntax.each {|sym, rules|
|
||||||
|
next if justempty_syms[sym]
|
||||||
|
if rules.all? {|rhs| rhs.all? {|e| justempty_syms[e] } }
|
||||||
|
justempty_syms[sym] = true
|
||||||
|
changed = true
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
result = {}
|
||||||
|
syntax.each {|sym, rules|
|
||||||
|
result[sym] = rules.map {|rhs| rhs.reject {|e| justempty_syms[e] } }.uniq
|
||||||
|
}
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.expand_emptyable_syms(rhs, emptyable_syms)
|
||||||
|
if rhs.empty?
|
||||||
|
elsif rhs.length == 1
|
||||||
|
if emptyable_syms[rhs[0]]
|
||||||
|
yield rhs
|
||||||
|
yield []
|
||||||
|
else
|
||||||
|
yield rhs
|
||||||
|
end
|
||||||
|
else
|
||||||
|
butfirst = rhs[1..-1]
|
||||||
|
if emptyable_syms[rhs[0]]
|
||||||
|
expand_emptyable_syms(butfirst, emptyable_syms) {|rhs2|
|
||||||
|
yield [rhs[0]] + rhs2
|
||||||
|
yield rhs2
|
||||||
|
}
|
||||||
|
else
|
||||||
|
expand_emptyable_syms(butfirst, emptyable_syms) {|rhs2|
|
||||||
|
yield [rhs[0]] + rhs2
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.remove_emptyable_rules(syntax)
|
||||||
|
emptyable_syms = {}
|
||||||
|
changed = true
|
||||||
|
while changed
|
||||||
|
changed = false
|
||||||
|
syntax.each {|sym, rules|
|
||||||
|
next if emptyable_syms[sym]
|
||||||
|
rules.each {|rhs|
|
||||||
|
if rhs.all? {|e| emptyable_syms[e] }
|
||||||
|
emptyable_syms[sym] = true
|
||||||
|
changed = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
result = {}
|
||||||
|
syntax.each {|sym, rules|
|
||||||
|
rules2 = []
|
||||||
|
rules.each {|rhs|
|
||||||
|
expand_emptyable_syms(rhs, emptyable_syms) {|rhs2|
|
||||||
|
rules2 << rhs2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result[sym] = rules2.uniq
|
||||||
|
}
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.expand_channel_rules(syntax)
|
||||||
|
channel_rules = {}
|
||||||
|
syntax.each {|sym, rules|
|
||||||
|
channel_rules[sym] = {sym=>true}
|
||||||
|
rules.each {|rhs|
|
||||||
|
if rhs.length == 1 && Symbol === rhs[0]
|
||||||
|
channel_rules[sym][rhs[0]] = true
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changed = true
|
||||||
|
while changed
|
||||||
|
changed = false
|
||||||
|
channel_rules.each {|sym, set|
|
||||||
|
n1 = set.size
|
||||||
|
set.keys.each {|s|
|
||||||
|
set.update(channel_rules[s])
|
||||||
|
}
|
||||||
|
n2 = set.size
|
||||||
|
changed = true if n1 < n2
|
||||||
|
}
|
||||||
|
end
|
||||||
|
result = {}
|
||||||
|
syntax.each {|sym, rules|
|
||||||
|
rules2 = []
|
||||||
|
channel_rules[sym].each_key {|s|
|
||||||
|
syntax[s].each {|rhs|
|
||||||
|
unless rhs.length == 1 && Symbol === rhs[0]
|
||||||
|
rules2 << rhs
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result[sym] = rules2.uniq
|
||||||
|
}
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.expand_noalt_rules(syntax)
|
||||||
|
noalt_syms = {}
|
||||||
|
syntax.each {|sym, rules|
|
||||||
|
if rules.length == 1
|
||||||
|
noalt_syms[sym] = true
|
||||||
|
end
|
||||||
|
}
|
||||||
|
result = {}
|
||||||
|
syntax.each {|sym, rules|
|
||||||
|
rules2 = []
|
||||||
|
rules.each {|rhs|
|
||||||
|
rhs2 = []
|
||||||
|
rhs.each {|e|
|
||||||
|
if noalt_syms[e]
|
||||||
|
rhs2.concat syntax[e][0]
|
||||||
|
else
|
||||||
|
rhs2 << e
|
||||||
|
end
|
||||||
|
}
|
||||||
|
rules2 << rhs2
|
||||||
|
}
|
||||||
|
result[sym] = rules2.uniq
|
||||||
|
}
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.reorder_rules(syntax)
|
||||||
|
result = {}
|
||||||
|
syntax.each {|sym, rules|
|
||||||
|
result[sym] = rules.sort_by {|rhs|
|
||||||
|
[rhs.find_all {|e| Symbol === e }.length, rhs.length]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
def each_tree(sym, limit)
|
def each_tree(sym, limit)
|
||||||
generate_from_sym(sym, limit) {|_, tree|
|
generate_from_sym(sym, limit) {|_, tree|
|
||||||
yield tree
|
yield tree
|
||||||
|
@ -25,6 +217,7 @@ class SentGen
|
||||||
yield limit, sym
|
yield limit, sym
|
||||||
else
|
else
|
||||||
rules = @syntax[sym]
|
rules = @syntax[sym]
|
||||||
|
raise "undefined rule: #{sym}" if !rules
|
||||||
rules.each {|rhs|
|
rules.each {|rhs|
|
||||||
if rhs.length == 1 || rules.length == 1
|
if rhs.length == 1 || rules.length == 1
|
||||||
limit1 = limit
|
limit1 = limit
|
||||||
|
|
|
@ -665,7 +665,8 @@ class TestAssignmentGen < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_assignment
|
def test_assignment
|
||||||
SentGen.new(Syntax).each_tree(:xassign, 3) {|assign|
|
syntax = SentGen.expand_syntax(Syntax)
|
||||||
|
SentGen.each_tree(syntax, :xassign, 3) {|assign|
|
||||||
assign[0] = rename_var(assign[0])
|
assign[0] = rename_var(assign[0])
|
||||||
sent = [assign].join('')
|
sent = [assign].join('')
|
||||||
bruby = do_assign(assign).to_a.sort
|
bruby = do_assign(assign).to_a.sort
|
||||||
|
|
Loading…
Reference in New Issue