summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-07-13 08:40:09 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-07-13 08:40:09 +0000
commita309f1047548bafcde65ef66143854f289926bab (patch)
tree83c84c2ccc04b9089e7d84f6c1b74fbd94e8ed84
parent53d317b9acf2827c1cad06f64f27e406493d75d8 (diff)
sentence generator updated.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12762 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--test/ruby/sentgen.rb193
-rw-r--r--test/ruby/test_assignment.rb3
2 files changed, 195 insertions, 1 deletions
diff --git a/test/ruby/sentgen.rb b/test/ruby/sentgen.rb
index 29388e91d5..94cffdad7a 100644
--- a/test/ruby/sentgen.rb
+++ b/test/ruby/sentgen.rb
@@ -1,10 +1,202 @@
# sentence generator
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)
@syntax = syntax
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)
generate_from_sym(sym, limit) {|_, tree|
yield tree
@@ -25,6 +217,7 @@ class SentGen
yield limit, sym
else
rules = @syntax[sym]
+ raise "undefined rule: #{sym}" if !rules
rules.each {|rhs|
if rhs.length == 1 || rules.length == 1
limit1 = limit
diff --git a/test/ruby/test_assignment.rb b/test/ruby/test_assignment.rb
index 1a07575f94..33c0be027c 100644
--- a/test/ruby/test_assignment.rb
+++ b/test/ruby/test_assignment.rb
@@ -665,7 +665,8 @@ class TestAssignmentGen < Test::Unit::TestCase
end
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])
sent = [assign].join('')
bruby = do_assign(assign).to_a.sort