module Kakezan
def flatten2
r = MultiNode.new()
each do |child|
case child
when MultiNode
r.append child
when MulNode
r.append child.flatten2
when ContainerNode
r.append child.flatten2
else
r.append child
end
end
r
end
def name
n = nil
for c in @children
next if NumberNode === c
na = c.name
if n.nil?
n = na
else
raise "multiple names found" if na != n
end
end
n = "1" if n.nil?
n
end
def factor
f = 1
for c in @children
f *= c.factor
end
f
end
end
class MulNode < ContainerNode
include BinaryNode
include Kakezan
def initialize(lhs, rhs)
@lhs, @rhs = lhs, rhs
end
def to_s
lhs = @lhs.to_s
rhs = @rhs.to_s
if (/\d$/ =~ lhs && /^\w/ =~ rhs) then
"#{lhs} #{rhs}"
else
"#{lhs}.#{rhs}"
end
end
end
class MultiNode < ContainerNode
include Kakezan
def initialize(*children)
@children = children
for c in @children
raise "# MultiNode.new(#{children.inspect})" unless Node === c
end
end
def to_s
s = @children.join(';')
s.gsub(/\d;\w/) { |dsw| dsw.sub(/;/, ' ') }.gsub(/;/, '.')
end
def each
@children.each {|child| yield child }
end
attr_reader :children
def append(other)
case other
when MultiNode
@children += other.children
else
@children.push other
end
end
def sort
table = {}
for child in self
name = child.name
if (table.include?(name)) then
table[name] = table[name].mul_eval(child)
else
table[name] = child
end
end
list = []
for name in table.keys.sort
candi = table[name]
if PowNode === candi and NumberNode === candi.lhs then
v = candi.value
list.push NumberNode.new(v) unless v == 1
next
end
next if candi.power.value == 0
list.push candi
end
if list.length > 1
list.delete(NumberNode::UNITY)
end
self.class.new(*list)
end
def collect_hash(stopper, op)
list = []
for child in self
list.push(child.send(op, stopper))
end
self.class.new(*list).flatten2
end
def expand(stopper)
collect_hash(stopper, :expand)
end
def unalias(stopper)
collect_hash(stopper, :unalias)
end
def foldnumber(stopper)
collect_hash(stopper, :foldnumber)
end
def value
raise "this is dimensional units" if (@children.size > 1)
@children.first ? @children.first.value : NumberNode::UNITY.value
end
end
syntax highlighted by Code2HTML, v. 0.9.1