1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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
This commit is contained in:
akr 2007-07-06 03:16:46 +00:00
parent 976bfae03b
commit 56fe47de3a
3 changed files with 246 additions and 0 deletions

View file

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

54
test/ruby/sentgen.rb Normal file
View file

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

View file

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