summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-07-06 03:16:46 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-07-06 03:16:46 +0000
commit56fe47de3a8e9ef2dff934dbdfc695d9817a102c (patch)
treeef9409330f11a763a9982a8ad28087a0719ac73c
parent976bfae03be67236543367aef7b8a22df02cd37b (diff)
* test/ruby/sentgen.rb: new file.
* test/ruby/test_assignment.rb: tests implemeneted using assignment generator and emulator. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12709 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog7
-rw-r--r--test/ruby/sentgen.rb54
-rw-r--r--test/ruby/test_assignment.rb185
3 files changed, 246 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index f9c2fda602..38977679ed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Fri Jul 6 12:15:01 2007 Tanaka Akira <akr@fsij.org>
+
+ * test/ruby/sentgen.rb: new file.
+
+ * test/ruby/test_assignment.rb: tests implemeneted using assignment
+ generator and emulator.
+
Fri Jul 6 03:06:58 2007 Koichi Sasada <ko1@atdot.net>
* insns.def: remove unused code.
diff --git a/test/ruby/sentgen.rb b/test/ruby/sentgen.rb
new file mode 100644
index 0000000000..29388e91d5
--- /dev/null
+++ b/test/ruby/sentgen.rb
@@ -0,0 +1,54 @@
+# sentence generator
+
+class SentGen
+ def initialize(syntax)
+ @syntax = syntax
+ end
+
+ def each_tree(sym, limit)
+ generate_from_sym(sym, limit) {|_, tree|
+ yield tree
+ }
+ nil
+ end
+
+ def each_string(sym, limit)
+ generate_from_sym(sym, limit) {|_, tree|
+ yield [tree].join('')
+ }
+ nil
+ end
+
+ def generate_from_sym(sym, limit, &b)
+ return if limit < 0
+ if String === sym
+ yield limit, sym
+ else
+ rules = @syntax[sym]
+ rules.each {|rhs|
+ if rhs.length == 1 || rules.length == 1
+ limit1 = limit
+ else
+ limit1 = limit-1
+ end
+ generate_from_rhs(rhs, limit1, &b)
+ }
+ end
+ nil
+ end
+
+ def generate_from_rhs(rhs, limit)
+ return if limit < 0
+ if rhs.empty?
+ yield limit, []
+ else
+ generate_from_sym(rhs[0], limit) {|limit1, child|
+ generate_from_rhs(rhs[1..-1], limit1) {|limit2, arr|
+ yield limit2, [child, *arr]
+ }
+ }
+ end
+ nil
+ end
+end
+
diff --git a/test/ruby/test_assignment.rb b/test/ruby/test_assignment.rb
index 966757bc98..1a07575f94 100644
--- a/test/ruby/test_assignment.rb
+++ b/test/ruby/test_assignment.rb
@@ -489,3 +489,188 @@ class TestAssignment < Test::Unit::TestCase
assert_equal [3,4], [a,b]
end
end
+
+require 'sentgen'
+class TestAssignmentGen < Test::Unit::TestCase
+ Syntax = {
+ :exp => [["0"],
+ ["nil"],
+ ["false"],
+ ["[]"],
+ ["[",:exps,"]"]],
+ :exps => [[:exp],
+ [:exp,",",:exps]],
+ :arg => [[:exp]],
+ :mrhs => [[:args,",",:arg],
+ [:args,",","*",:arg],
+ ["*",:arg]],
+ :args => [[:arg],
+ ["*",:arg],
+ [:args,",",:arg],
+ [:args,",","*",:arg]],
+ :mlhs => [[:mlhs_basic],
+ ["(",:mlhs_inner,")"]],
+ :mlhs_inner => [[:mlhs_basic],
+ ["(",:mlhs_inner,")"]],
+ :mlhs_basic => [[:mlhs_head],
+ [:mlhs_head,:mlhs_item],
+ [:mlhs_head,"*",:mlhs_node],
+ [:mlhs_head,"*",:mlhs_node,",",:mlhs_post],
+ [:mlhs_head,"*"],
+ [:mlhs_head,"*",",", :mlhs_post],
+ [ "*",:mlhs_node],
+ [ "*",:mlhs_node,",",:mlhs_post],
+ [ "*"],
+ [ "*",",", :mlhs_post]],
+ :mlhs_head => [[:mlhs_item,","],
+ [:mlhs_head,:mlhs_item,","]],
+ :mlhs_post => [[:mlhs_item],
+ [:mlhs_post,",",:mlhs_item]],
+ :mlhs_item => [[:mlhs_node],
+ ["(",:mlhs_inner,")"]],
+ :mlhs_node => [["var"]],
+ :xassign => [["var"," = ",:exp],
+ ["var"," = ",:mrhs],
+ [:mlhs," = ",:exp],
+ [:mlhs," = ",:mrhs]],
+ }
+
+ def rename_var(obj, nbox=[0])
+ if obj.respond_to? :to_ary
+ a = []
+ obj.each {|e| a << rename_var(e, nbox) }
+ a
+ elsif obj == 'var'
+ n = nbox[0]
+ nbox[0] += 1
+ "v#{n}"
+ else
+ obj
+ end
+ end
+
+ def expand_except_paren(obj, r=[])
+ if obj.respond_to? :to_ary
+ if (obj[0] == '(' && obj[-1] == ')') || (obj[0] == '[' && obj[-1] == ']')
+ a = []
+ obj[1...-1].each {|o|
+ expand_except_paren(o, a)
+ }
+ r << a
+ else
+ obj.each {|o|
+ expand_except_paren(o, r)
+ }
+ end
+ else
+ r << obj
+ end
+ r
+ end
+
+ def extract_single_element(ary)
+ raise "not a single element array: #{ary.inspect}" if ary.length != 1
+ ary[0]
+ end
+
+ def emu_assign_ary(lhs, rv, h)
+ rv = rv.respond_to?(:to_ary) ? rv : [rv]
+ rv = rv.dup
+ a = [[]]
+ lhs.each {|e|
+ if e == ','
+ a << []
+ else
+ a.last << e
+ end
+ }
+ a.pop if a.last == []
+ pre = []
+ star = post = nil
+ a.each {|e|
+ if post
+ post << e
+ elsif e[0] == '*'
+ star = e
+ post = []
+ else
+ pre << e
+ end
+ }
+
+ until pre.empty?
+ emu_assign_single(extract_single_element(pre.shift), rv.shift, h)
+ end
+
+ if post
+ if rv.length < post.length
+ until post.empty?
+ emu_assign_single(extract_single_element(post.shift), rv.shift, h)
+ end
+ else
+ until post.empty?
+ emu_assign_single(extract_single_element(post.pop), rv.pop, h)
+ end
+ end
+ end
+
+ if star && 1 < star.length
+ emu_assign_single(extract_single_element(star[1..-1]), rv, h)
+ end
+ end
+
+ def emu_assign_single(lhs, rv, h={})
+ if lhs.respond_to? :to_str
+ if /\A[a-z0-9]+\z/ =~ lhs
+ h[lhs] = rv
+ else
+ raise "unexpected lhs string: #{lhs.inspect}"
+ end
+ elsif lhs.respond_to? :to_ary
+ emu_assign_ary(lhs, rv, h)
+ else
+ raise "unexpected lhs: #{lhs.inspect}"
+ end
+ h
+ end
+
+ def emu_assign(assign)
+ lhs = expand_except_paren(assign[0])
+ rhs = expand_except_paren(assign[2])
+ lopen = lhs.any? {|e| e == '*' || e == ',' }
+ ropen = rhs.any? {|e| e == '*' || e == ',' }
+ lhs = extract_single_element(lhs) if !lopen
+ rhs = ["(",rhs,")"] if ropen
+ begin
+ rv = eval((ropen ? ["[",assign[2],"]"] : assign[2]).join(''))
+ rescue Exception
+ rv = $!.message
+ end
+ emu_assign_single(lhs, rv)
+ end
+
+ def do_assign(assign)
+ assign = assign.join('')
+ vars = []
+ vars = assign.scan(/v[0-9]+/)
+ code = "#{assign}; [#{vars.join(",")}]"
+ begin
+ vals = eval(code)
+ rescue Exception
+ return {:ex=>$!.message}
+ end
+ h = {}
+ [vars, vals].transpose.each {|k,v| h[k] = v }
+ h
+ end
+
+ def test_assignment
+ SentGen.new(Syntax).each_tree(:xassign, 3) {|assign|
+ assign[0] = rename_var(assign[0])
+ sent = [assign].join('')
+ bruby = do_assign(assign).to_a.sort
+ bemu = emu_assign(assign).to_a.sort
+ assert_equal(bemu, bruby, sent)
+ }
+ end
+end