Class: RbYAML::BaseConstructor

Inherits:
Object
  • Object
show all
Defined in:
lib/rbyaml/constructor.rb

Direct Known Subclasses

SafeConstructor

Constant Summary collapse

@@yaml_constructors =
{}
@@yaml_multi_constructors =
{}
@@yaml_multi_regexps =
{}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(composer) ⇒ BaseConstructor

Returns a new instance of BaseConstructor.



36
37
38
39
40
# File 'lib/rbyaml/constructor.rb', line 36

def initialize(composer)
  @composer = composer
  @constructed_objects = {}
  @recursive_objects = {}
end

Class Method Details

.add_constructor(tag, constructor) ⇒ Object



178
179
180
# File 'lib/rbyaml/constructor.rb', line 178

def self.add_constructor(tag, constructor)
  @@yaml_constructors[tag] = constructor
end

.add_multi_constructor(tag_prefix, multi_constructor) ⇒ Object



182
183
184
185
# File 'lib/rbyaml/constructor.rb', line 182

def self.add_multi_constructor(tag_prefix, multi_constructor)
  @@yaml_multi_constructors[tag_prefix] = multi_constructor
  @@yaml_multi_regexps[tag_prefix] = Regexp.new("^"+Regexp.escape(tag_prefix))
end

Instance Method Details

#check_dataObject



42
43
44
45
# File 'lib/rbyaml/constructor.rb', line 42

def check_data
  # If there are more documents available?
  @composer.check_node
end

#construct_document(node) ⇒ Object



59
60
61
62
63
64
# File 'lib/rbyaml/constructor.rb', line 59

def construct_document(node)
  data = construct_object(node)
  @constructed_objects = {}
  @recursive_objects = {}
  data
end

#construct_mapping(node) ⇒ Object

Raises:



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/rbyaml/constructor.rb', line 132

def construct_mapping(node)
  raise ConstructorError.new(nil,nil,"expected a mapping node, but found #{node.tid}",node.start_mark) if !node.__is_mapping
  mapping = {}
  merge = nil
  for key_node,value_node in node.value
    if key_node.tag == "tag:yaml.org,2002:merge"
      raise ConstructorError.new("while constructing a mapping", node.start_mark,"found duplicate merge key", key_node.start_mark) if !merge.nil?
      if value_node.__is_mapping
        merge = [construct_mapping(value_node)]
      elsif value_node.__is_sequence
        merge = []
        for subnode in value_node.value
          if !subnode.__is_mapping
            raise ConstructorError.new("while constructing a mapping",node.start_mark,"expected a mapping for merging, but found #{subnode.tid}", subnode.start_mark)
          end
          merge.unshift(construct_mapping(subnode))
        end
      else
        raise ConstructorError.new("while constructing a mapping", node.start_mark,"expected a mapping or list of mappings for merging, but found #{value_node.tid}", value_node.start_mark)
      end
    elsif key_node.tag == "tag:yaml.org,2002:value"
      raise ConstructorError.new("while construction a mapping", node.start_mark,"found duplicate value key", key_node.start_mark) if mapping.include?("=")
      value = construct_object(value_node)
      mapping["="] = value
    else
      key = construct_object(key_node)
#          raise ConstructorError.new("while constructing a mapping", node.start_mark,"found duplicate key", key_node.start_mark) if mapping.include?(key)
    end
    value = construct_object(value_node)
    mapping[key] = value
  end
  if !merge.nil?
    merge << mapping
    mapping = {}
    for submapping in merge
      mapping.merge!(submapping)
    end
  end
  mapping
end

#construct_object(node) ⇒ Object

Raises:



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rbyaml/constructor.rb', line 66

def construct_object(node)
  return @constructed_objects[node] if @constructed_objects.include?(node)
  raise ConstructorError.new(nil,nil,"found recursive nod",node.start_mark) if @recursive_objects.include?(node)
  @recursive_objects[node] = nil
  constructor = @@yaml_constructors[node.tag]
  if !constructor
    ruby_cls = RbYAML::tagged_classes[node.tag]
    if ruby_cls && (ruby_cls.method_defined?(:yaml_initialize) || ruby_cls.respond_to?(:yaml_new))
      constructor = lambda { |node| send(:construct_ruby_object,ruby_cls,node) }
    else
      through = true
      for tag_prefix,reg in @@yaml_multi_regexps
        if reg =~ node.tag
          tag_suffix = node.tag[tag_prefix.length..-1]
          constructor = lambda { |node| @@yaml_multi_constructors[tag_prefix].__call(self,tag_suffix, node) }
          through = false
          break
        end
      end
      if through
        ctor = @@yaml_multi_constructors[nil] || @@yaml_constructors[nil]
        if ctor
          constructor = lambda { |node| ctor.__call(self,node.tag,node) }
        else
          constructor = lambda { |node| construct_primitive(node) }
        end
      end
    end
  end
  data = constructor.__call(self,node)
  @constructed_objects[node] = data
  @recursive_objects.delete(node)
  data
end

#construct_pairs(node) ⇒ Object

Raises:



173
174
175
176
# File 'lib/rbyaml/constructor.rb', line 173

def construct_pairs(node)
  raise ConstructorError.new(nil,nil,"expected a mapping node, but found #{node.tid}",node.start_mark) if !node.__is_mapping
  node.value.collect {|key_node,value_node| [construct_object(key_node), construct_object(value_node)] }
end

#construct_primitive(node) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/rbyaml/constructor.rb', line 101

def construct_primitive(node)
  if node.__is_scalar
    construct_scalar(node)
  elsif node.__is_sequence
    construct_sequence(node)
  elsif node.__is_mapping
    construct_mapping(node)
  else
    puts node.tag
  end
end

#construct_scalar(node) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/rbyaml/constructor.rb', line 113

def construct_scalar(node)
  if !node.__is_scalar
    if node.__is_mapping
      for key_node in node.value.keys
        if key_node.tag == "tag:yaml.org,2002:value"
          return construct_scalar(node.value[key_node])
        end
      end
    end
    raise ConstructorError.new(nil, nil,"expected a scalar node, but found #{node.tid}",node.start_mark)
  end
  node.value
end

#construct_sequence(node) ⇒ Object

Raises:



127
128
129
130
# File 'lib/rbyaml/constructor.rb', line 127

def construct_sequence(node)
  raise ConstructorError.new(nil,nil,"expected a sequence node, but found #{node.tid}",node.start_mark) if !node.__is_sequence
  node.value.map {|child| construct_object(child) }
end

#each_documentObject



52
53
54
55
56
57
# File 'lib/rbyaml/constructor.rb', line 52

def each_document
  # Iterator protocol.
  while @composer.check_node
    yield construct_document(@composer.get_node)
  end
end

#get_dataObject



47
48
49
50
# File 'lib/rbyaml/constructor.rb', line 47

def get_data
  # Construct and return the next document.
  construct_document(@composer.get_node) if @composer.check_node
end