Index: /branches/pyyaml3000/tests/test_structure.py
===================================================================
--- /branches/pyyaml3000/tests/test_structure.py	(revision 54)
+++ /branches/pyyaml3000/tests/test_structure.py	(revision 55)
@@ -7,4 +7,5 @@
 from yaml.composer import *
 from yaml.resolver import *
+from yaml.constructor import *
 from yaml.nodes import *
 
@@ -138,9 +139,50 @@
         elif isinstance(node1, MappingNode):
             self.failUnlessEqual(len(node1.value), len(node2.value))
-            for (key1, value1), (key2, value2) in zip(node1.value, node2.value):
+            items1 = node1.value.items()
+            items1.sort(lambda (k1,v1), (k2,v2): cmp((k1.tag,k1.value,v1.tag,v1.value),
+                                                    (k2.tag,k2.value,v2.tag,v2.value)))
+            items2 = node2.value.items()
+            items2.sort(lambda (k1,v1), (k2,v2): cmp((k1.tag,k1.value,v1.tag,v1.value),
+                                                    (k2.tag,k2.value,v2.tag,v2.value)))
+            for (key1, value1), (key2, value2) in zip(items1, items2):
                 self._compare(key1, key2)
                 self._compare(value1, value2)
 
 TestResolver.add_tests('testResolver', '.data', '.canonical')
+
+class MyConstructor(Constructor):
+
+    def construct_sequence(self, node):
+        return tuple(Constructor.construct_sequence(self, node))
+
+    def construct_mapping(self, node):
+        pairs = self.construct_pairs(node)
+        pairs.sort()
+        return pairs
+
+class TestConstructor(test_appliance.TestAppliance):
+
+    def _testConstructor(self, test_name, data_filename, canonical_filename):
+        natives1 = None
+        natives2 = None
+        try:
+            constructor1 = MyConstructor(Resolver(Composer(Parser(Scanner(Reader(file(data_filename, 'rb')))))))
+            natives1 = list(iter(constructor1))
+            canonical = test_appliance.CanonicalParser(file(canonical_filename, 'rb').read())
+            canonical.parse()
+            constructor2 = MyConstructor(Resolver(Composer(canonical)))
+            natives2 = list(iter(constructor2))
+            self.failUnlessEqual(natives1, natives2)
+        except:
+            print
+            print "DATA1:"
+            print file(data_filename, 'rb').read()
+            print "DATA2:"
+            print file(canonical_filename, 'rb').read()
+            print "NATIVES1:", natives1
+            print "NATIVES2:", natives2
+            raise
+
+TestConstructor.add_tests('testConstructor', '.data', '.canonical')
 
 class TestParserOnCanonical(test_appliance.TestAppliance):
Index: /branches/pyyaml3000/tests/test_yaml.py
===================================================================
--- /branches/pyyaml3000/tests/test_yaml.py	(revision 52)
+++ /branches/pyyaml3000/tests/test_yaml.py	(revision 55)
@@ -8,4 +8,5 @@
 from test_structure import *
 from test_errors import *
+from test_detector import *
 from test_syck import *
 
Index: /branches/pyyaml3000/tests/data/int.data
===================================================================
--- /branches/pyyaml3000/tests/data/int.data	(revision 55)
+++ /branches/pyyaml3000/tests/data/int.data	(revision 55)
@@ -0,0 +1,6 @@
+- 685230
+- +685_230
+- 02472256
+- 0x_0A_74_AE
+- 0b1010_0111_0100_1010_1110
+- 190:20:30
Index: /branches/pyyaml3000/tests/data/str.detect
===================================================================
--- /branches/pyyaml3000/tests/data/str.detect	(revision 55)
+++ /branches/pyyaml3000/tests/data/str.detect	(revision 55)
@@ -0,0 +1,1 @@
+tag:yaml.org,2002:str
Index: /branches/pyyaml3000/tests/data/str.data
===================================================================
--- /branches/pyyaml3000/tests/data/str.data	(revision 55)
+++ /branches/pyyaml3000/tests/data/str.data	(revision 55)
@@ -0,0 +1,1 @@
+- abcd
Index: /branches/pyyaml3000/tests/data/null.data
===================================================================
--- /branches/pyyaml3000/tests/data/null.data	(revision 55)
+++ /branches/pyyaml3000/tests/data/null.data	(revision 55)
@@ -0,0 +1,3 @@
+-
+- ~
+- null
Index: /branches/pyyaml3000/tests/data/timestamp.data
===================================================================
--- /branches/pyyaml3000/tests/data/timestamp.data	(revision 55)
+++ /branches/pyyaml3000/tests/data/timestamp.data	(revision 55)
@@ -0,0 +1,5 @@
+- 2001-12-15T02:59:43.1Z
+- 2001-12-14t21:59:43.10-05:00
+- 2001-12-14 21:59:43.10 -5
+- 2001-12-15 2:59:43.10
+- 2002-12-14
Index: /branches/pyyaml3000/tests/data/int.detect
===================================================================
--- /branches/pyyaml3000/tests/data/int.detect	(revision 55)
+++ /branches/pyyaml3000/tests/data/int.detect	(revision 55)
@@ -0,0 +1,1 @@
+tag:yaml.org,2002:int
Index: /branches/pyyaml3000/tests/data/float.data
===================================================================
--- /branches/pyyaml3000/tests/data/float.data	(revision 55)
+++ /branches/pyyaml3000/tests/data/float.data	(revision 55)
@@ -0,0 +1,6 @@
+- 6.8523015e+5
+- 685.230_15e+03
+- 685_230.15
+- 190:20:30.15
+- -.inf
+- .NaN
Index: /branches/pyyaml3000/tests/data/value.data
===================================================================
--- /branches/pyyaml3000/tests/data/value.data	(revision 55)
+++ /branches/pyyaml3000/tests/data/value.data	(revision 55)
@@ -0,0 +1,1 @@
+- =
Index: /branches/pyyaml3000/tests/data/null.detect
===================================================================
--- /branches/pyyaml3000/tests/data/null.detect	(revision 55)
+++ /branches/pyyaml3000/tests/data/null.detect	(revision 55)
@@ -0,0 +1,1 @@
+tag:yaml.org,2002:null
Index: /branches/pyyaml3000/tests/data/duplicate-mapping-key.error-message
===================================================================
--- /branches/pyyaml3000/tests/data/duplicate-mapping-key.error-message	(revision 55)
+++ /branches/pyyaml3000/tests/data/duplicate-mapping-key.error-message	(revision 55)
@@ -0,0 +1,6 @@
+---
+&anchor foo:
+    foo: bar
+    *anchor: duplicate key
+    baz: bat
+    *anchor: duplicate key
Index: /branches/pyyaml3000/tests/data/merge.detect
===================================================================
--- /branches/pyyaml3000/tests/data/merge.detect	(revision 55)
+++ /branches/pyyaml3000/tests/data/merge.detect	(revision 55)
@@ -0,0 +1,1 @@
+tag:yaml.org,2002:merge
Index: /branches/pyyaml3000/tests/data/timestamp.detect
===================================================================
--- /branches/pyyaml3000/tests/data/timestamp.detect	(revision 55)
+++ /branches/pyyaml3000/tests/data/timestamp.detect	(revision 55)
@@ -0,0 +1,1 @@
+tag:yaml.org,2002:timestamp
Index: /branches/pyyaml3000/tests/data/bool.data
===================================================================
--- /branches/pyyaml3000/tests/data/bool.data	(revision 55)
+++ /branches/pyyaml3000/tests/data/bool.data	(revision 55)
@@ -0,0 +1,4 @@
+- y
+- NO
+- True
+- on
Index: /branches/pyyaml3000/tests/data/merge.data
===================================================================
--- /branches/pyyaml3000/tests/data/merge.data	(revision 55)
+++ /branches/pyyaml3000/tests/data/merge.data	(revision 55)
@@ -0,0 +1,1 @@
+- <<
Index: /branches/pyyaml3000/tests/data/value.detect
===================================================================
--- /branches/pyyaml3000/tests/data/value.detect	(revision 55)
+++ /branches/pyyaml3000/tests/data/value.detect	(revision 55)
@@ -0,0 +1,1 @@
+tag:yaml.org,2002:value
Index: /branches/pyyaml3000/tests/data/float.detect
===================================================================
--- /branches/pyyaml3000/tests/data/float.detect	(revision 55)
+++ /branches/pyyaml3000/tests/data/float.detect	(revision 55)
@@ -0,0 +1,1 @@
+tag:yaml.org,2002:float
Index: /branches/pyyaml3000/tests/data/bool.detect
===================================================================
--- /branches/pyyaml3000/tests/data/bool.detect	(revision 55)
+++ /branches/pyyaml3000/tests/data/bool.detect	(revision 55)
@@ -0,0 +1,1 @@
+tag:yaml.org,2002:bool
Index: /branches/pyyaml3000/tests/test_detector.py
===================================================================
--- /branches/pyyaml3000/tests/test_detector.py	(revision 55)
+++ /branches/pyyaml3000/tests/test_detector.py	(revision 55)
@@ -0,0 +1,36 @@
+
+import test_appliance
+
+from yaml.reader import Reader
+from yaml.scanner import Scanner
+from yaml.parser import *
+from yaml.composer import *
+from yaml.resolver import *
+from yaml.nodes import *
+
+class TestDetector(test_appliance.TestAppliance):
+
+    def _testDetector(self, test_name, data_filename, detect_filename):
+        node = None
+        correct_tag = None
+        try:
+            correct_tag = file(detect_filename, 'rb').read().strip()
+            resolver = Resolver(Composer(Parser(Scanner(Reader(file(data_filename, 'rb'))))))
+            node = list(iter(resolver))[0]
+            self.failUnless(isinstance(node, SequenceNode))
+            for scalar in node.value:
+                self.failUnless(isinstance(scalar, ScalarNode))
+                self.failUnlessEqual(scalar.tag, correct_tag)
+        except:
+            print
+            print "DATA:"
+            print file(data_filename, 'rb').read()
+            print "CORRECT_TAG:"
+            print file(detect_filename, 'rb').read()
+            print "ROOT NODE:", node
+            print "SCALAR NODES:", node.value
+            raise
+
+TestDetector.add_tests('testDetector', '.data', '.detect')
+
+
Index: /branches/pyyaml3000/lib/yaml/__init__.py
===================================================================
--- /branches/pyyaml3000/lib/yaml/__init__.py	(revision 53)
+++ /branches/pyyaml3000/lib/yaml/__init__.py	(revision 55)
@@ -6,12 +6,9 @@
 from composer import Composer
 from resolver import Resolver
+from constructor import Constructor
 
 from tokens import *
 from events import *
-
-def scan(data, Reader=Reader, Scanner=Scanner):
-    reader = Reader(data)
-    scanner = Scanner(reader)
-    return iter(scanner)
+from nodes import *
 
 def parse(data, Reader=Reader, Scanner=Scanner, Parser=Parser):
@@ -19,22 +16,8 @@
     scanner = Scanner(reader)
     parser = Parser(scanner)
-    return iter(parser)
+    return parser
 
-def compose(data, Reader=Reader, Scanner=Scanner, Parser=Parser,
-        Composer=Composer):
-    reader = Reader(data)
-    scanner = Scanner(reader)
-    parser = Parser(scanner)
-    composer = Composer(parser)
-    return iter(composer)
-
-def compose_document(*args, **kwds):
-    try:
-        return compose(*args, **kwds).next()
-    except StopIteration:
-        return None
-
-def resolve(data, Reader=Reader, Scanner=Scanner, Parser=Parser,
-        Composer=Composer, Resolver=Resolver):
+def load(data, Reader=Reader, Scanner=Scanner, Parser=Parser,
+        Composer=Composer, Resolver=Resolver, Constructor=Constructor):
     reader = Reader(data)
     scanner = Scanner(reader)
@@ -42,10 +25,9 @@
     composer = Composer(parser)
     resolver = Resolver(composer)
-    return iter(resolver)
+    constructor = Constructor(resolver)
+    return constructor
 
-def resolve_document(*args, **kwds):
-    try:
-        return resolve(*args, **kwds).next()
-    except StopIteration:
-        return None
+def load_document(*args, **kwds):
+    for document in load(*args, **kwds):
+        return document
 
Index: /branches/pyyaml3000/lib/yaml/resolver.py
===================================================================
--- /branches/pyyaml3000/lib/yaml/resolver.py	(revision 54)
+++ /branches/pyyaml3000/lib/yaml/resolver.py	(revision 55)
@@ -1,4 +1,6 @@
 
 from nodes import *
+
+import re
 
 class BaseResolver:
@@ -40,10 +42,10 @@
             self.resolve_sequence(path, node)
             for index in range(len(node.value)):
-                self.resolve_node(path+[node, index], node.value[index])
+                self.resolve_node(path+[(node, index)], node.value[index])
         elif isinstance(node, MappingNode):
             self.resolve_mapping(path, node)
-            for key, value in node.value:
+            for key in node.value:
                 self.resolve_node(path+[node, None], key)
-                self.resolve_node(path+[node, key], value)
+                self.resolve_node(path+[node, key], node.value[key])
 
     def resolve_scalar(self, path, node):
@@ -62,7 +64,73 @@
 
     def detect_scalar(self, value):
-        return None
+        if value == u'':
+            detectors = self.yaml_detectors.get(u'', [])
+        else:
+            detectors = self.yaml_detectors.get(value[0], [])
+        detectors += self.yaml_detectors.get(None, [])
+        for tag, regexp in detectors:
+            if regexp.match(value):
+                return tag
+
+    def add_detector(cls, tag, regexp, first):
+        if not 'yaml_detectors' in cls.__dict__:
+            cls.yaml_detectors = cls.yaml_detectors.copy()
+        for ch in first:
+            cls.yaml_detectors.setdefault(ch, []).append((tag, regexp))
+    add_detector = classmethod(add_detector)
+
+    yaml_detectors = {}
 
 class Resolver(BaseResolver):
     pass
 
+Resolver.add_detector(
+        u'tag:yaml.org,2002:bool',
+        re.compile(ur'''^(?:y|Y|yes|Yes|YES|n|N|no|No|NO
+                    |true|True|TRUE|false|False|FALSE
+                    |on|On|ON|off|Off|OFF)$''', re.X),
+        list(u'yYnNtTfFoO'))
+
+Resolver.add_detector(
+        u'tag:yaml.org,2002:float',
+        re.compile(ur'''^(?:[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*(?:[eE][-+][0-9]+)?
+                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*
+                    |[-+]?\.(?:inf|Inf|INF)
+                    |\.(?:nan|NaN|NAN))$''', re.X),
+        list(u'-+0123456789.'))
+
+Resolver.add_detector(
+        u'tag:yaml.org,2002:int',
+        re.compile(ur'''^(?:[-+]?0b[0-1_]+
+                    |[-+]?0[0-7_]+
+                    |[-+]?(?:0|[1-9][0-9_]*)
+                    |[-+]?0x[0-9a-fA-F_]+
+                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$''', re.X),
+        list(u'-+0123456789'))
+
+Resolver.add_detector(
+        u'tag:yaml.org,2002:merge',
+        re.compile(ur'^(?:<<)$'),
+        ['<'])
+
+Resolver.add_detector(
+        u'tag:yaml.org,2002:null',
+        re.compile(ur'''^(?: ~
+                    |null|Null|NULL
+                    | )$''', re.X),
+        [u'~', u'n', u'N', u''])
+
+Resolver.add_detector(
+        u'tag:yaml.org,2002:timestamp',
+        re.compile(ur'''^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]
+                    |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]?
+                     (?:[Tt]|[ \t]+)[0-9][0-9]?
+                     :[0-9][0-9] :[0-9][0-9] (?:\.[0-9]*)?
+                     (?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$''', re.X),
+        list(u'0123456789'))
+
+Resolver.add_detector(
+        u'tag:yaml.org,2002:value',
+        re.compile(ur'^(?:=)$'),
+        ['='])
+
Index: /branches/pyyaml3000/lib/yaml/constructor.py
===================================================================
--- /branches/pyyaml3000/lib/yaml/constructor.py	(revision 55)
+++ /branches/pyyaml3000/lib/yaml/constructor.py	(revision 55)
@@ -0,0 +1,254 @@
+
+from error import *
+from nodes import *
+
+try:
+    import datetime
+    datetime_available = True
+except ImportError:
+    datetime_available = False
+
+try:
+    set
+except NameError:
+    from sets import Set as set
+
+import binascii
+
+class ConstructorError(MarkedYAMLError):
+    pass
+
+class BaseConstructor:
+
+    def __init__(self, resolver):
+        self.resolver = resolver
+        self.constructed_objects = {}
+
+    def check(self):
+        # If there are more documents available?
+        return self.resolver.check()
+
+    def get(self):
+        # Construct and return the next document.
+        if self.resolver.check():
+            return self.construct_document(self.resolver.get())
+
+    def __iter__(self):
+        # Iterator protocol.
+        while self.resolver.check():
+            yield self.construct_document(self.resolver.get())
+
+    def construct_document(self, node):
+        native = self.construct_object(node)
+        self.constructed_objects = {}
+        return native
+
+    def construct_object(self, node):
+        if node in self.constructed_objects:
+            return self.constructed_objects[node]
+        if node.tag in self.yaml_constructors:
+            native = self.yaml_constructors[node.tag](self, node)
+        elif None in self.yaml_constructors:
+            native = self.yaml_constructors[None](self, node)
+        elif isinstance(node, ScalarNode):
+            native = self.construct_scalar(node)
+        elif isinstance(node, SequenceNode):
+            native = self.construct_sequence(node)
+        elif isinstance(node, MappingNode):
+            native = self.construct_mapping(node)
+        self.constructed_objects[node] = native
+        return native
+
+    def construct_scalar(self, node):
+        if not isinstance(node, ScalarNode):
+            if isinstance(node, MappingNode):
+                for key_node in node.value:
+                    if key_node.tag == u'tag:yaml.org,2002:value':
+                        return self.construct_scalar(node.value[key_node])
+            raise ConstructorError(None, None,
+                    "expected a scalar node, but found %s" % node.id,
+                    node.start_marker)
+        return node.value
+
+    def construct_sequence(self, node):
+        if not isinstance(node, SequenceNode):
+            raise ConstructorError(None, None,
+                    "expected a sequence node, but found %s" % node.id,
+                    node.start_marker)
+        return [self.construct_object(child) for child in node.value]
+
+    def construct_mapping(self, node):
+        if not isinstance(node, MappingNode):
+            raise ConstructorError(None, None,
+                    "expected a mapping node, but found %s" % node.id,
+                    node.start_marker)
+        mapping = {}
+        for key_node in node.value:
+            key = self.construct_object(key_node)
+            try:
+                duplicate_key = key in mapping
+            except TypeError, exc:
+                raise ConstructorError("while constructing a mapping", node.start_marker,
+                        "found unacceptable key (%s)" % exc, key_node.start_marker)
+            if duplicate_key:
+                raise ConstructorError("while constructing a mapping", node.start_marker,
+                        "found duplicate key", key_node.start_marker)
+            value = self.construct_object(node.value[key_node])
+            mapping[key] = value
+        return mapping
+
+    def construct_pairs(self, node):
+        if not isinstance(node, MappingNode):
+            raise ConstructorError(None, None,
+                    "expected a mapping node, but found %s" % node.id,
+                    node.start_marker)
+        pairs = []
+        for key_node in node.value:
+            key = self.construct_object(key_node)
+            value = self.construct_object(node.value[key_node])
+            pairs.append((key, value))
+        return pairs
+
+    def add_constructor(cls, tag, constructor):
+        if not 'yaml_constructors' in cls.__dict__:
+            cls.yaml_constructors = cls.yaml_constructors.copy()
+        cls.yaml_constructors[tag] = constructor
+    add_constructor = classmethod(add_constructor)
+
+    yaml_constructors = {}
+
+class Constructor(BaseConstructor):
+
+    def construct_yaml_null(self, node):
+        self.construct_scalar(node)
+        return None
+
+    bool_values = {
+        u'y':       True,
+        u'yes':     True,
+        u'n':       False,
+        u'no':      False,
+        u'true':    True,
+        u'false':   False,
+        u'on':      True,
+        u'off':     False,
+    }
+
+    def construct_yaml_bool(self, node):
+        value = self.construct_scalar(node)
+        return self.bool_values[value.lower()]
+
+    def construct_yaml_int(self, node):
+        value = str(self.construct_scalar(node))
+        value = value.replace('_', '')
+        sign = +1
+        if value[0] == '-':
+            sign = -1
+        if value[0] in '+-':
+            value = value[1:]
+        if value == '0':
+            return 0
+        elif value.startswith('0b'):
+            return sign*int(value[2:], 2)
+        elif value.startswith('0x'):
+            return sign*int(value[2:], 16)
+        elif value[0] == '0':
+            return sign*int(value, 8)
+        elif ':' in value:
+            digits = [int(part) for part in value.split(':')]
+            digits.reverse()
+            base = 1
+            value = 0
+            for digit in digits:
+                value += digit*base
+                base *= 60
+            return sign*value
+        else:
+            return sign*int(value)
+
+    inf_value = 1e300000
+    nan_value = inf_value/inf_value
+
+    def construct_yaml_float(self, node):
+        value = str(self.construct_scalar(node))
+        value = value.replace('_', '')
+        sign = +1
+        if value[0] == '-':
+            value = -1
+        if value[0] in '+-':
+            value = value[1:]
+        if value.lower() == '.inf':
+            return sign*self.inf_value
+        elif value.lower() == '.nan':
+            return self.nan_value
+        elif ':' in value:
+            digits = [float(part) for part in value.split(':')]
+            digits.reverse()
+            base = 1
+            value = 0.0
+            for digit in digits:
+                value += digit*base
+                base *= 60
+            return sign*value
+        else:
+            return float(value)
+
+    def construct_yaml_binary(self, node):
+        value = self.construct_scalar(node)
+        try:
+            return str(value).decode('base64')
+        except (binascii.Error, UnicodeEncodeError), exc:
+            raise ConstructorError(None, None,
+                    "failed to decode base64 data: %s" % exc, node.start_mark) 
+
+    def construct_yaml_str(self, node):
+        value = self.construct_scalar(node)
+        try:
+            return str(value)
+        except UnicodeEncodeError:
+            return value
+
+Constructor.add_constructor(
+        u'tag:yaml.org,2002:null',
+        Constructor.construct_yaml_null)
+
+Constructor.add_constructor(
+        u'tag:yaml.org,2002:bool',
+        Constructor.construct_yaml_bool)
+
+Constructor.add_constructor(
+        u'tag:yaml.org,2002:int',
+        Constructor.construct_yaml_int)
+
+Constructor.add_constructor(
+        u'tag:yaml.org,2002:float',
+        Constructor.construct_yaml_float)
+
+Constructor.add_constructor(
+        u'tag:yaml.org,2002:str',
+        Constructor.construct_yaml_str)
+
+class YAMLObjectMetaclass(type):
+
+    def __init__(cls, name, bases, kwds):
+        super(YAMLObjectMetaclass, cls).__init__(name, bases, kwds)
+        if 'yaml_tag' in kwds and kwds['yaml_tag'] is not None:
+            cls.yaml_constructor_class.add_constructor(cls.yaml_tag, cls.from_yaml)
+
+class YAMLObject(object):
+
+    __metaclass__ = YAMLObjectMetaclass
+
+    yaml_constructor_class = Constructor
+
+    yaml_tag = None
+
+    def from_yaml(cls, constructor, node):
+        raise ConstructorError(None, None,
+                "found undefined constructor for the tag %r"
+                % node.tag.encode('utf-8'), node.start_marker)
+    from_yaml = classmethod(from_yaml)
+
+    def to_yaml(self):
+        assert False    # needs dumper
+
Index: /branches/pyyaml3000/lib/yaml/composer.py
===================================================================
--- /branches/pyyaml3000/lib/yaml/composer.py	(revision 53)
+++ /branches/pyyaml3000/lib/yaml/composer.py	(revision 55)
@@ -82,9 +82,13 @@
     def compose_mapping_node(self):
         start_event = self.parser.get()
-        value = []
+        value = {}
         while not self.parser.check(CollectionEndEvent):
+            key_event = self.parser.peek()
             item_key = self.compose_node()
             item_value = self.compose_node()
-            value.append((item_key, item_value))
+            if item_key in value:
+                raise ComposerError("while composing a mapping", start_event.start_marker,
+                        "found duplicate key", key_event.start_marker)
+            value[item_key] = item_value
         end_event = self.parser.get()
         return MappingNode(start_event.tag, value,
Index: /branches/pyyaml3000/lib/yaml/nodes.py
===================================================================
--- /branches/pyyaml3000/lib/yaml/nodes.py	(revision 53)
+++ /branches/pyyaml3000/lib/yaml/nodes.py	(revision 55)
@@ -23,5 +23,5 @@
 
 class ScalarNode(Node):
-    pass
+    id = 'scalar'
 
 class CollectionNode(Node):
@@ -29,7 +29,7 @@
 
 class SequenceNode(CollectionNode):
-    pass
+    id = 'sequence'
 
 class MappingNode(CollectionNode):
-    pass
+    id = 'mapping'
 
Index: /branches/pyyaml3000/lib/yaml/scanner.py
===================================================================
--- /branches/pyyaml3000/lib/yaml/scanner.py	(revision 52)
+++ /branches/pyyaml3000/lib/yaml/scanner.py	(revision 55)
@@ -1,11 +1,23 @@
 
-# Tokens:
-# YAML-DIRECTIVE(major_version, minor_version), TAG-DIRECTIVE(handle, prefix)
-# RESERVED-DIRECTIVE(name)
-# DOCUMENT-START, DOCUMENT-END
-# BLOCK-SEQUENCE-START, BLOCK-MAPPING-START, BLOCK-END
-# FLOW-SEQUENCE-START, FLOW-MAPPING-START, FLOW-SEQUENCE-END, FLOW-MAPPING-END
-# ENTRY, KEY, VALUE
-# ALIAS(name), ANCHOR(name), TAG(value), SCALAR(value, plain)
+# Scanner produces tokens of the following types:
+# DIRECTIVE(name, value)
+# DOCUMENT-START
+# DOCUMENT-END
+# STREAM-END
+# BLOCK-SEQUENCE-START
+# BLOCK-MAPPING-START
+# BLOCK-END
+# FLOW-SEQUENCE-START
+# FLOW-MAPPING-START
+# FLOW-SEQUENCE-END
+# FLOW-MAPPING-END
+# BLOCK-ENTRY
+# FLOW-ENTRY
+# KEY
+# VALUE
+# ALIAS(value)
+# ANCHOR(value)
+# TAG(value)
+# SCALAR(value, plain)
 
 __all__ = ['Scanner', 'ScannerError']
Index: /branches/pyyaml3000/lib/yaml/parser.py
===================================================================
--- /branches/pyyaml3000/lib/yaml/parser.py	(revision 53)
+++ /branches/pyyaml3000/lib/yaml/parser.py	(revision 55)
@@ -72,5 +72,5 @@
     # Since writing an LL(1) parser is a straightforward task, we do not give
     # many comments here.
-    # Note that we use Python generators. If you rewrite the parser to another
+    # Note that we use Python generators. If you rewrite the parser in another
     # language, you may replace all 'yield'-s with event handler calls.
 
