=begin
= class Node
Node is a parent class for classes of parse tree node.
This is not expected to be instanciated directly.
=end
class Node
def initialize(*args)
raise "#{self.class} is virtual."
end
def to_s(*args)
raise "#{self.class}#to_s is virtual."
end
=begin
--- pow other
simply constructs a PowNode object.
No reduction is performed.
=end
def pow(other)
PowNode.new(self, other)
end
=begin
--- mul other
simply constructs a MulNode object.
No reduction is performed.
=end
def mul(other)
other = NumberNode.new(other) if Numeric === other
MulNode.new(self, other)
end
=begin
--- divide other
simply constructs a MulNode object.
No reduction is performed.
=end
def divide(other)
MulNode.new(self, PowNode.new(other, NumberNode.new(-1)))
end
=begin
--- shift other
simply constructs a ShiftNode object.
No reduction is performed.
=end
def shift(other)
ShiftNode.new(self, other)
end
=begin
--- pow_eval other
similar to ((<pow other>)), but reduces PowNode[PowNode[...]] into
single PowNode[...], so overriden at PowNode class.
=end
def pow_eval(other)
pow(other)
end
=begin
--- inspect
=end
def inspect2; "#{self.class}[#{to_s}]"; end
def inspect; inspect2.gsub(/Units::/, '').gsub(/NumRu::/, '').gsub(/Node\[/, '['); end
=begin
--- trim
in most subclasses, "trim" is redirected into "trim2".
=end
def trim
trim2
end
=begin
--- flatten
in most subclasses, "flatten" is redirected into "flatten2".
=end
def flatten
flatten2
end
=begin
--- sort
=end
def sort
raise "#{self.class}#sort is virtual: call after flatten"
end
=begin
--- reduce1
--- reduce2
--- reduce3
--- reduce4
--- reduce5
=end
def reduce1
self
end
def reduce2
trim
end
def reduce3
trim.flatten
end
def reduce4
# unalias(Hash.new).trim.flatten.sort
foldnumber(nil).trim.flatten.sort
end
def reduce5
expand(Hash.new).trim.flatten.sort
end
=begin
--- ref
to be overriden at ShiftNode
--- deref
to be overriden at ShiftNode
=end
def ref
NumberNode::ZERO
end
def deref
self
end
end
class ErrorNode < Node
def initialize(string)
@a = string
end
def to_s; @a; end
end
class ContainerNode < Node
def trim2
x = []
for child in self
x.push child.trim2
end
self.class.new(*x)
end
def inspect2
a = []
for child in self
a.push child.inspect2
end
"#{self.class}[#{a.join(', ')}]"
end
end
module BinaryNode
def each
yield @lhs
yield @rhs
end
def expand(stopper)
self.class.new(@lhs.expand(stopper), @rhs.expand(stopper))
end
def unalias(stopper)
self.class.new(@lhs.unalias(stopper), @rhs.unalias(stopper))
end
def foldnumber(stopper)
self.class.new(@lhs.foldnumber(stopper), @rhs.foldnumber(stopper))
end
end
class TerminalNode < Node
def trim2; self; end
def flatten2; self; end
def expand(stopper); self; end
alias :unalias :expand
alias :foldnumber :expand
def sort; self; end
end
syntax highlighted by Code2HTML, v. 0.9.1