lib/sgf/node.rb in SgfParser-1.0.0 vs lib/sgf/node.rb in SgfParser-2.0.0

- old
+ new

@@ -1,51 +1,98 @@ module SGF + #Your basic node. It holds information about itself, its parent, and its children. class Node attr_accessor :parent, :children, :properties # Creates a new node. Arguments which can be passed in are: # :parent => parent_node (nil by default) - # :children => [list, of, children] (empty array by default) - # :properties => {hash_of => properties} (empty hash by default) + # :children => [list, of, children] (empty array if nothing is passed) + # :properties => {hash_of => properties} (empty hash if nothing is passed) def initialize args={} @parent = args[:parent] @children = [] add_children args[:children] if args[:children] @properties = Hash.new - @properties.merge! args[:properties] if args[:properties] + add_properties args[:properties] if args[:properties] end + #Takes an arbitrary number of child nodes, adds them to the list of children, and make this node their parent. def add_children *nodes nodes.flatten! raise "Non-node child given!" if nodes.any? { |node| node.class != Node } - nodes.each { |node| node.parent = self } - @children.concat nodes + nodes.each do |node| + node.parent = self + @children << node + end end + #Takes a hash {identity => property} and adds those to the current node. + #If a property already exists, it will append to it. def add_properties hash - hash.each do |key, value| - @properties[key] ||= "" - @properties[key].concat value + hash.each do |identity, property| + @properties[identity] ||= property.class.new + @properties[identity].concat property end + update_human_readable_methods end + #Iterate through each child. Yields a child node, if one exists. def each_child @children.each { |child| yield child } end + #Compare to another node. def == other_node @properties == other_node.properties end - def comments - @properties["C"] + #Syntactic sugar for node.properties["XX"] + def [] identity + identity = identity.to_s + @properties[identity] end - alias :comment :comments + def to_s + out = "#<#{self.class}:#{self.object_id}, " + out << (@parent ? "Has a parent, " : "Has no parent, ") + out << "#{@children.size} Children, " + out << "#{@properties.keys.size} Properties" + out << ">" + end + alias :inspect :to_s + + def to_str(indent = 0) + properties = [] + @properties.each do |identity, property| + properties << stringify_identity_and_property(identity, property) + end + whitespace = leading_whitespace(indent) + "#{whitespace};#{properties.join("\n#{whitespace}")}" + end + + def stringify_identity_and_property(identity, property) + new_property = property.instance_of?(Array) ? property.join("][") : property + new_property = new_property.gsub("]", "\\]") if identity == "C" + "#{identity.to_s}[#{new_property}]" + end + private + + def update_human_readable_methods + SGF::Node::PROPERTIES.each do |human_readable_method, sgf_identity| + next if defined? human_readable_method.to_sym + define_method(human_readable_method.to_sym) do + @properties[sgf_identity] ? @properties[sgf_identity] : raise(SGF::NoIdentityError) + end + end + end + + def leading_whitespace(indent) + "#{" " * indent}" + end def method_missing method_name, *args property = method_name.to_s.upcase if property[/(.*?)=$/] @properties[$1] = args[0] \ No newline at end of file