=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 (()), 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