module Sfp module Visitor # An example of class Visitor which can be used to traverse from one node to # another node (bread first). This is based on 'Visitor' pattern. class Default def visit(name, value, parent); end end class ConformantVariables attr_reader :var_values def initialize @var_values = {} end def visit(name, value, parent) if value.is_a?(Hash) and value.iseither ref = parent.ref.push(name) @var_values[ref] = value['_values'] end return true if value.is_a?(Hash) and value.isobject false end end # eliminate '_parent' key/value from a Hash object to avoid cyclic references class ParentEliminator def visit(name, value, parent) value.delete('_parent') if value.is_a?(Hash) and value.has_key?('_parent') return true end end class ParentGenerator def visit(name, value, parent) value['_parent'] = parent if value.is_a?(Hash) return true end end class ProcedureEliminator def visit(name, value, parent) if value.is_a?(Hash) and value.isprocedure parent.delete(name) return false end true end end class PrettyStateGenerator def visit(name, value, parent) if name[0,1] == '_' parent.delete(name) elsif value.is_a?(Hash) if value.isnull parent[name] = nil return false else parent.delete(name) if value['_context'] == 'procedure' or value['_context'] == 'constraint' end end true end end class SfpGenerator def initialize(root) @root = root end def visit(name, value, parent) if value.is_a?(Hash) value['_parent'] = parent value['_self'] = name if not value.has_key?('_context') value['_context'] = 'object' if value.has_key?('_isa') else value['_isa'] = '$.Object' end end Sfp::Helper.expand_object(value, @root) if value.isobject end return true end end class ReferenceModifier def visit(name, value, parent) if value.is_a?(String) and value.isref and parent.isobject if value.length >= 8 and value[0,8] == '$.parent' _, _, rest = value.split('.', 3) if parent.has_key?('_parent') val = parent['_parent'].ref val << ".#{rest}" if not rest.nil? parent[name] = val else raise Exception end elsif value.length >= 6 and value[0,6] == '$.this' _, _, rest = value.split('.', 3) val = parent.ref val << ".#{rest}" if not rest.nil? parent[name] = val end end true end end class SetModifier def visit(name, value, parent) return false if value.is_a?(Hash) and value.isprocedure if value.is_a?(Hash) and value.isset parent[name] = [] return false end true end end class NullModifier def visit(name, value, parent) return false if value.is_a?(Hash) and value.isprocedure if value.is_a?(Hash) and value.isnull parent[name] = nil return false end true end end end end