Index: trunk/Makefile
===================================================================
--- trunk/Makefile	(revision 3)
+++ trunk/Makefile	(revision 4)
@@ -1,4 +1,4 @@
 
-.PHONY: default build install test clean
+.PHONY: default build force install test clean
 
 PYTHON=/usr/bin/python
@@ -10,9 +10,12 @@
 	${PYTHON} setup.py build
 
+force:
+	${PYTHON} setup.py build -f
+
 install: build
 	${PYTHON} setup.py install
 
 test: build
-	${PYTHON} tests/test_build.py ${TEST}
+	${PYTHON} tests/test_build.py -v ${TEST}
 
 clean:
Index: trunk/sandbox/syck-parser/test_error.yml
===================================================================
--- trunk/sandbox/syck-parser/test_error.yml	(revision 4)
+++ trunk/sandbox/syck-parser/test_error.yml	(revision 4)
@@ -0,0 +1,2 @@
+ - invalid
+- document
Index: trunk/sandbox/syck-parser/test_typing.yml
===================================================================
--- trunk/sandbox/syck-parser/test_typing.yml	(revision 4)
+++ trunk/sandbox/syck-parser/test_typing.yml	(revision 4)
@@ -0,0 +1,12 @@
+---
+- 123
+- '123'
+- abcdefg
+- |-
+  123
+- true
+- false
+- 1.2345
+- 16-07-2005
+- {}
+- []
Index: trunk/sandbox/syck-parser/test_my_typing.yml
===================================================================
--- trunk/sandbox/syck-parser/test_my_typing.yml	(revision 4)
+++ trunk/sandbox/syck-parser/test_my_typing.yml	(revision 4)
@@ -0,0 +1,9 @@
+
+- !int '123'
+- !yamltype 'foo'
+- !python/type 'bar'
+- !domain.tld,2002/type 'baz'
+- !!private 'private'
+- !map {}
+- !seq []
+
Index: trunk/sandbox/syck-parser/test.yml
===================================================================
--- trunk/sandbox/syck-parser/test.yml	(revision 4)
+++ trunk/sandbox/syck-parser/test.yml	(revision 4)
@@ -0,0 +1,18 @@
+- Mark McGwire
+- Sammy Sosa
+- Ken Griffey
+---
+1: simple string
+2: 42
+3: '1 Single Quoted String'
+4: "YAML's Double \\\"Quoted\\\" String"
+5: |
+  A block
+    with several
+      lines.
+6: |-
+  A "chomped" block
+7: >
+  A
+  folded
+   string
Index: trunk/sandbox/syck-parser/syck-parser.c
===================================================================
--- trunk/sandbox/syck-parser/syck-parser.c	(revision 2)
+++ trunk/sandbox/syck-parser/syck-parser.c	(revision 4)
@@ -41,13 +41,13 @@
         m->type_id = strdup(n->type_id);
     }
-    else {
+/*    else {
         m->type_id = strdup("");
-    }
+    }*/
     if (n->anchor) {
         m->anchor = strdup(n->anchor);
     }
-    else {
+/*    else {
         m->anchor = strdup("");
-    }
+    }*/
 
     return m;
@@ -173,5 +173,5 @@
 
     syck_parser_handler(p, node_handler);
-    syck_parser_error_handler(p, error_handler);
+//    syck_parser_error_handler(p, error_handler);
     syck_parser_bad_anchor_handler(p, bad_anchor_handler);
 
Index: trunk/ext/_syckmodule.c
===================================================================
--- trunk/ext/_syckmodule.c	(revision 3)
+++ trunk/ext/_syckmodule.c	(revision 4)
@@ -3,16 +3,556 @@
 #include <syck.h>
 
-static PyMethodDef _syck_methods[] = {
+/* Global objects. */
+
+static PyObject *_syck_Error;
+
+static PyObject *_syck_ScalarKind;
+static PyObject *_syck_SeqKind;
+static PyObject *_syck_MapKind;
+
+/* Node type. */
+
+typedef struct {
+    PyObject_HEAD
+    PyObject *kind;
+    PyObject *type_id;
+    PyObject *value;
+} _syck_Node;
+
+static void
+_syck_Node_dealloc(_syck_Node *self)
+{
+    Py_XDECREF(self->kind);
+    Py_XDECREF(self->type_id);
+    Py_XDECREF(self->value);
+    PyObject_Del(self);
+}
+
+static PyObject *
+_syck_Node_getattr(_syck_Node *self, char *name)
+{
+    PyObject *value;
+
+    if (strcmp(name, "kind") == 0)
+        value = self->kind;
+    else if (strcmp(name, "type_id") == 0)
+        value = self->type_id;
+    else if (strcmp(name, "value") == 0)
+        value = self->value;
+    else {
+        PyErr_SetString(PyExc_AttributeError, name);
+        return NULL;
+    }
+
+    Py_INCREF(value);
+    return value;
+}
+
+static char _syck_Node_doc[] =
+    "Node object\n"
+    "\n"
+    "Attributes of the Node object:\n\n"
+    "kind -- 'scalar', 'seq', or 'map'.\n"
+    "type_id -- the tag of the node.\n"
+    "value -- the value of the node, a string, list or dict object.\n";
+
+static PyTypeObject _syck_NodeType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                                  /* ob_size */
+    "_syck.Node",                       /* tp_name */
+    sizeof(_syck_Node),                 /* tp_basicsize */
+    0,                                  /* tp_itemsize */
+    (destructor)_syck_Node_dealloc,     /* tp_dealloc */
+    0,                                  /* tp_print */
+    (getattrfunc)_syck_Node_getattr,    /* tp_getattr */
+    0,                                  /* tp_setattr */
+    0,                                  /* tp_compare */
+    0,                                  /* tp_repr */
+    0,                                  /* tp_as_number */
+    0,                                  /* tp_as_sequence */
+    0,                                  /* tp_as_mapping */
+    0,                                  /* tp_hash */
+    0,                                  /* tp_call */
+    0,                                  /* tp_str */
+    0,                                  /* tp_getattro */
+    0,                                  /* tp_setattro */
+    0,                                  /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
+    _syck_Node_doc,                     /* tp_doc */
+};
+
+static PyObject *
+_syck_NewNode(PyObject *self, PyObject *args)
+{
+    if (!PyArg_ParseTuple(args, ":_syck.Node"))
+        return NULL;
+
+    PyErr_SetString(PyExc_TypeError, "Node object cannot be created explicitly. Use _syck.Parser.parse() instead.");
+    return NULL;
+}
+
+static char _syck_NewNode_doc[] =
+    "Node object cannot be created explicitly. Use _syck.Parser.parse() instead.";
+
+static PyObject *
+_syck_NewNode_FromValue(char *type_id, PyObject *value) /* Note: steals the reference to the value. */
+{
+    _syck_Node *self;
+    PyObject *kind;
+
+    self = PyObject_NEW(_syck_Node, &_syck_NodeType);
+    if (!self) {
+        Py_XDECREF(value);
+        return NULL;
+    }
+
+    self->value = value;
+
+    if (PyList_Check(value))
+        kind = _syck_SeqKind;
+    else if (PyDict_Check(value))
+        kind = _syck_MapKind;
+    else
+        kind = _syck_ScalarKind;
+    Py_INCREF(kind);
+    self->kind = kind;
+
+    if (type_id) {
+        self->type_id = PyString_FromString(type_id);
+        if (!self->type_id) {
+            Py_DECREF(self);
+            return NULL;
+        }
+    }
+    else {
+        Py_INCREF(Py_None);
+        self->type_id = Py_None;
+    }
+
+    return (PyObject *)self;
+}
+
+/* Parser type. */
+
+typedef struct {
+    PyObject_HEAD
+    PyObject *source;
+    PyObject *resolver;
+    PyObject *symbols;
+    int error_state;
+    int mark;
+    SyckParser *parser;
+} _syck_Parser;
+
+static PyObject *
+_syck_Parser_parse(_syck_Parser *self, PyObject *args)
+{
+    SYMID index;
+    PyObject *value;
+
+    if (!PyArg_ParseTuple(args, ":parse"))
+        return NULL;
+
+    if (!self->parser) {
+        PyErr_SetString(PyExc_TypeError, "Parser object is closed");
+        return NULL;
+    }
+
+    self->symbols = PyList_New(0);
+    if (!self->symbols) {
+        return NULL;
+    }
+
+    index = syck_parse(self->parser);
+    if (!self->error_state && !self->parser->eof) {
+        value = PyList_GetItem(self->symbols, index-1);
+    }
+
+    Py_DECREF(self->symbols);
+
+    if (self->error_state) {
+        self->error_state = 0;
+        return NULL;
+    }
+
+    if (self->parser->eof) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+    
+    return value;
+}
+
+static char _syck_Parser_parse_doc[] =
+    "Parses the next document in the YAML stream, return the root Node object or None on EOF.";
+
+static PyObject *
+_syck_Parser_parse_documents(_syck_Parser *self, PyObject *args)
+{
+    SYMID index;
+    PyObject *value = NULL;
+    PyObject *result = NULL;
+
+    if (!PyArg_ParseTuple(args, ":parse_document"))
+        return NULL;
+
+    if (!self->parser) {
+        PyErr_SetString(PyExc_TypeError, "Parser object is closed");
+        return NULL;
+    }
+
+    result = PyList_New(0);
+    if (!result) return NULL;
+
+    while (1) {
+
+        self->symbols = PyList_New(0);
+        if (!self->symbols) {
+            Py_DECREF(result);
+            return NULL;
+        };
+
+        index = syck_parse(self->parser);
+
+        if (!self->error_state && !self->parser->eof) {
+            value = PyList_GetItem(self->symbols, index-1);
+            if (!value) {
+                Py_DECREF(self->symbols);
+                Py_DECREF(result);
+                return NULL;
+            }
+            if (PyList_Append(result, value) < 0) {
+                Py_DECREF(self->symbols);
+                Py_DECREF(value);
+                Py_DECREF(result);
+                return NULL;
+            }
+            Py_DECREF(value);
+        }
+
+        Py_DECREF(self->symbols);
+
+        if (self->error_state) {
+            self->error_state = 0;
+            Py_DECREF(result);
+            return NULL;
+        }
+
+        if (self->parser->eof) break;
+    }
+
+    return result;
+}
+
+static char _syck_Parser_parse_documents_doc[] =
+    "Parses the entire YAML stream and returns list of documents.";
+
+static PyObject *
+_syck_Parser_close(_syck_Parser *self, PyObject *args)
+{
+    if (!PyArg_ParseTuple(args, ":close"))
+        return NULL;
+
+    Py_XDECREF(self->source);
+    self->source = NULL;
+
+    if (self->parser) {
+        syck_free_parser(self->parser);
+    }
+    self->parser = NULL;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static char _syck_Parser_close_doc[] =
+    "Closes the parser and frees memory";
+
+static PyMethodDef _syck_Parser_methods[] = {
+    {"parse",  (PyCFunction)_syck_Parser_parse, METH_VARARGS, _syck_Parser_parse_doc},
+    {"parse_documents",  (PyCFunction)_syck_Parser_parse_documents, METH_VARARGS, _syck_Parser_parse_documents_doc},
+    {"close",  (PyCFunction)_syck_Parser_close, METH_VARARGS, _syck_Parser_close_doc},
     {NULL}  /* Sentinel */
 };
 
+static void
+_syck_Parser_dealloc(_syck_Parser *self)
+{
+    Py_XDECREF(self->source);
+    if (self->parser) {
+        syck_free_parser(self->parser);
+    }
+    PyObject_Del(self);
+}
+
+static PyObject *
+_syck_Parser_getattr(_syck_Parser *self, char *name)
+{
+    return Py_FindMethod(_syck_Parser_methods, (PyObject *)self, name);
+}
+
+static char _syck_Parser_doc[] =
+    "_syck.Parser(yaml_string_or_file, implicit_typing=True, taguri_expansion=True) -> Parser object\n"
+    "\n"
+    "Methods of the Parser object:\n\n"
+    "parse() -- Parses the next document in the YAML stream, return the root Node object or None on EOF.\n"
+    "parse_documents() -- Parses the entire YAML stream and returns list of documents.\n"
+    "close() -- Closes the parser and frees memory.\n";
+
+static PyTypeObject _syck_ParserType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                                  /* ob_size */
+    "_syck.Parser",                     /* tp_name */
+    sizeof(_syck_Parser),               /* tp_basicsize */
+    0,                                  /* tp_itemsize */
+    (destructor)_syck_Parser_dealloc,   /* tp_dealloc */
+    0,                                  /* tp_print */
+    (getattrfunc)_syck_Parser_getattr,  /* tp_getattr */
+    0,                                  /* tp_setattr */
+    0,                                  /* tp_compare */
+    0,                                  /* tp_repr */
+    0,                                  /* tp_as_number */
+    0,                                  /* tp_as_sequence */
+    0,                                  /* tp_as_mapping */
+    0,                                  /* tp_hash */
+    0,                                  /* tp_call */
+    0,                                  /* tp_str */
+    0,                                  /* tp_getattro */
+    0,                                  /* tp_setattro */
+    0,                                  /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
+    _syck_Parser_doc,                   /* tp_doc */
+};
+
+static long
+_syck_Parser_io_file_read(char *buf, SyckIoFile *file, long max_size, long skip)
+{
+    _syck_Parser *runtime = (_syck_Parser *)file->ptr;
+
+    PyObject *value;
+
+    char *str;
+    int length;
+
+    buf[skip] = '\0';
+
+    if (runtime->error_state) {
+        return skip;
+    }
+    
+    max_size -= skip;
+
+    value = PyObject_CallMethod(runtime->source, "read", "(i)", max_size);
+    if (!value) {
+        runtime->error_state = 1;
+        return skip;
+    }
+
+    if (!PyString_Check(value)) {
+        Py_DECREF(value);
+        PyErr_SetString(PyExc_TypeError, "file-like object should return a string");
+        runtime->error_state = 1;
+        
+        return skip;
+    }
+
+    str = PyString_AS_STRING(value);
+    length = PyString_GET_SIZE(value);
+    if (!length) {
+        Py_DECREF(value);
+        return skip;
+    }
+
+    if (length > max_size) {
+        Py_DECREF(value);
+        PyErr_SetString(PyExc_ValueError, "read returns an overly long string");
+        runtime->error_state = 1;
+        return skip;
+    }
+
+    memcpy(buf+skip, str, length);
+    length += skip;
+    buf[length] = '\0';
+
+    Py_DECREF(value);
+
+    return length;
+}
+
+static SYMID
+_syck_Parser_node_handler(SyckParser *parser, SyckNode *node)
+{
+    _syck_Parser *runtime = (_syck_Parser *)parser->bonus;
+
+    SYMID index;
+    PyObject *object = NULL;
+
+    PyObject *key, *value, *item;
+    int k;
+
+    if (runtime->error_state)
+        return 0;
+
+    switch (node->kind) {
+
+        case syck_str_kind:
+            object = PyString_FromStringAndSize(node->data.str->ptr,
+                    node->data.str->len);
+            if (!object) goto error;
+            break;
+
+        case syck_seq_kind:
+            object = PyList_New(node->data.list->idx);
+            if (!object) goto error;
+            for (k = 0; k < node->data.list->idx; k++) {
+                index = syck_seq_read(node, k);
+                item = PyList_GetItem(runtime->symbols, index-1);
+                if (!item) goto error;
+                Py_INCREF(item);
+                PyList_SET_ITEM(object, k, item);
+            }
+            break;
+
+        case syck_map_kind:
+            object = PyDict_New();
+            if (!object) goto error;
+            for (k = 0; k < node->data.pairs->idx; k++)
+            {
+                index = syck_map_read(node, map_key, k);
+                key = PyList_GetItem(runtime->symbols, index-1);
+                if (!key) goto error;
+                index = syck_map_read(node, map_value, k);
+                value = PyList_GetItem(runtime->symbols, index-1);
+                if (!value) goto error;
+                if (PyDict_SetItem(object, key, value) < 0)
+                    goto error;
+            }
+            break;
+    }
+
+    object = _syck_NewNode_FromValue(node->type_id, object);
+    if (!object) goto error;
+
+    if (PyList_Append(runtime->symbols, object) < 0)
+        goto error;
+
+    index = PyList_Size(runtime->symbols);
+    return index;
+
+error:
+    Py_XDECREF(object);
+    runtime->error_state = 1;
+    return 0;
+}
+
+static void
+_syck_Parser_error_handler(SyckParser *parser, char *str)
+{
+    _syck_Parser *runtime = (_syck_Parser *)parser->bonus;
+    PyObject *value;
+
+    if (runtime->error_state) return;
+
+    runtime->error_state = 1;
+
+    value = Py_BuildValue("(sii)", str, parser->linect, parser->cursor-parser->lineptr);
+    if (value) {
+        PyErr_SetObject(_syck_Error, value);
+    }
+}
+
+static PyObject *
+_syck_NewParser(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    _syck_Parser *parser;
+    PyObject *source;
+    int implicit_typing = 1;
+    int taguri_expansion = 1;
+
+    static char *kwdlist[] = {"source", "implicit_typing", "taguri_expansion", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ii", kwdlist,
+                &source, &implicit_typing, &taguri_expansion))
+        return NULL;
+
+    parser = PyObject_NEW(_syck_Parser, &_syck_ParserType);
+    if (!parser)
+        return NULL;
+
+    Py_INCREF(source);
+    parser->source = source;
+    parser->error_state = 0;
+
+    parser->parser = syck_new_parser();
+    parser->parser->bonus = parser;
+
+    if (PyString_Check(source)) {
+        syck_parser_str_auto(parser->parser, PyString_AS_STRING(source), NULL);
+    }
+    else {
+        syck_parser_file(parser->parser, (FILE *)parser, _syck_Parser_io_file_read);
+    }
+    syck_parser_implicit_typing(parser->parser, implicit_typing);
+    syck_parser_taguri_expansion(parser->parser, taguri_expansion);
+
+    syck_parser_handler(parser->parser, _syck_Parser_node_handler);
+    syck_parser_error_handler(parser->parser, _syck_Parser_error_handler);
+    /*
+    syck_parser_bad_anchor_handler(parser, _syck_Parser_bad_anchor_handler);
+    */
+
+    return (PyObject *)parser;
+}
+
+static char _syck_NewParser_doc[] =
+    "Creates a new Parser object.";
+
+/* The module definitions. */
+
+static PyMethodDef _syck_methods[] = {
+    {"Node",  (PyCFunction)_syck_NewNode, METH_VARARGS, _syck_NewNode_doc},
+    {"Parser",  (PyCFunction)_syck_NewParser, METH_VARARGS|METH_KEYWORDS, _syck_NewParser_doc},
+    {NULL}  /* Sentinel */
+};
+
 static char _syck_doc[] =
     "This module provides low-level access to the Syck parser and emitter.\n"
-    "Do not use this module directly, use the module 'syck' instead.\n";
+    "Do not use this module directly, use the package 'syck' instead.\n";
 
 PyMODINIT_FUNC
 init_syck(void)
 {
-    Py_InitModule3("_syck", _syck_methods, _syck_doc);
-}
-
+    PyObject *m;
+
+    _syck_NodeType.ob_type = &PyType_Type;
+    _syck_ParserType.ob_type = &PyType_Type;
+
+    _syck_Error = PyErr_NewException("_syck.error", NULL, NULL);
+    if (!_syck_Error)
+        return;
+
+    _syck_ScalarKind = PyString_FromString("scalar");
+    if (!_syck_ScalarKind)
+        return;
+    _syck_SeqKind = PyString_FromString("seq");
+    if (!_syck_SeqKind)
+        return;
+    _syck_MapKind = PyString_FromString("map");
+    if (!_syck_MapKind)
+        return;
+
+    m = Py_InitModule3("_syck", _syck_methods, _syck_doc);
+
+    Py_INCREF(_syck_Error);
+    if (!PyModule_AddObject(m, "error", _syck_Error) < 0)
+        return;
+
+    Py_INCREF(&_syck_NodeType);
+    if (PyModule_AddObject(m, "NodeType", (PyObject *)&_syck_NodeType) < 0)
+        return;
+
+    Py_INCREF(&_syck_ParserType);
+    if (PyModule_AddObject(m, "ParserType", (PyObject *)&_syck_ParserType) < 0)
+        return;
+}
+
Index: trunk/tests/test_syck.py
===================================================================
--- trunk/tests/test_syck.py	(revision 3)
+++ trunk/tests/test_syck.py	(revision 4)
@@ -1,17 +1,303 @@
 
 import unittest
-
 import _syck, syck
-
-
-class Test1(unittest.TestCase):
-
-    def testme(self):
-        pass
-
-class Test2(unittest.TestCase):
-
-    def testmetoo(self):
-        pass
+import StringIO
+
+EXAMPLE = """
+-
+  avg: 0.278
+  hr: 65
+  name: Mark McGwire
+-
+  avg: 0.288
+  hr: 63
+  name: Sammy Sosa
+"""
+
+INVALID = """
+ - invalid
+- document
+""", 2, 0
+
+COMPARE1 = """
+one: foo
+two: bar
+three: baz
+""", {
+    'one': 'foo',
+    'two': 'bar',
+    'three': 'baz',
+}
+
+COMPARE2 = """
+- Mark McGwire
+- Sammy Sosa
+- Ken Griffey
+""", [
+    'Mark McGwire',
+    'Sammy Sosa',
+    'Ken Griffey',
+]
+
+COMPARE3 = """
+american:
+  - Boston Red Sox
+  - Detroit Tigers
+  - New York Yankees
+national:
+  - New York Mets
+  - Chicago Cubs
+  - Atlanta Braves
+""", {
+    'american': [
+        'Boston Red Sox',
+        'Detroit Tigers',
+        'New York Yankees',
+    ],
+    'national': [
+        'New York Mets',
+        'Chicago Cubs',
+        'Atlanta Braves',
+    ],
+}
+
+DOCUMENTS0 = ""
+
+DOCUMENTS1 = """
+---
+Time: 2001-11-23 15:01:42 -05:00
+User: ed
+Warning: >
+  This is an error message
+  for the log file
+"""
+
+DOCUMENTS2 = """
+---
+Time: 2001-11-23 15:01:42 -05:00
+User: ed
+Warning: >
+  This is an error message
+  for the log file
+---
+Time: 2001-11-23 15:02:31 -05:00
+User: ed
+Warning: >
+  A slightly different error
+  message.
+"""
+
+DOCUMENTS3 = """
+---
+Time: 2001-11-23 15:01:42 -05:00
+User: ed
+Warning: >
+  This is an error message
+  for the log file
+---
+Time: 2001-11-23 15:02:31 -05:00
+User: ed
+Warning: >
+  A slightly different error
+  message.
+---
+Date: 2001-11-23 15:03:17 -05:00
+User: ed
+Fatal: >
+  Unknown variable "bar"
+Stack:
+  - file: TopClass.py
+    line: 23
+    code: |
+      x = MoreObject("345\\n")
+  - file: MoreClass.py
+    line: 58
+    code: |-
+      foo = bar
+"""
+
+IMPLICIT_TYPING = """
+- 'foo'
+- >-
+  bar
+- baz
+- 123
+- 3.14
+- true
+- false
+- []
+- {}
+""", [
+    ('str', True),
+    ('str', True),
+    ('str', False),
+    ('int', False),
+    ('float#fix', False),
+    ('bool#yes', False),
+    ('bool#no', False),
+    (None, False),
+    (None, False),
+]
+
+EXPLICIT_TYPING = """
+- !int '123'
+- !yamltype 'foo'
+- !python/type 'bar'
+- !domain.tld,2002/type 'baz'
+- !!private 'private'
+- !map {}
+- !seq []
+""", [
+    'tag:yaml.org,2002:int',
+    'tag:yaml.org,2002:yamltype',
+    'tag:python.yaml.org,2002:type',
+    'tag:domain.tld,2002:type',
+    'x-private:private',
+    'tag:yaml.org,2002:map',
+    'tag:yaml.org,2002:seq',
+]
+
+class TestTypes(unittest.TestCase):
+
+    def testParserType(self):
+        parser = _syck.Parser(EXAMPLE)
+        self.assertEqual(type(parser), _syck.ParserType)
+        parser.close()
+
+    def testNodeType(self):
+        parser = _syck.Parser(EXAMPLE)
+        document = parser.parse()
+        self.assertEqual(type(document), _syck.NodeType)
+        parser.close()
+
+    def testNodeType2(self):
+        self.assertRaises(TypeError, (lambda: _syck.Node()))
+
+class TestErrors(unittest.TestCase):
+
+    def testError(self):
+        parser = _syck.Parser(INVALID[0])
+        self.assertRaises(_syck.error, (lambda: parser.parse()))
+        parser.close()
+
+    def testErrorLocation(self):
+        source, line, column = INVALID
+        parser = _syck.Parser(source)
+        try:
+            parser.parse()
+            raise Exception
+        except _syck.error, e:
+            self.assertEqual(e.args[1], line)
+            self.assertEqual(e.args[2], column)
+
+class TestValuesAndSources(unittest.TestCase):
+
+    def testValues1(self):
+        self._testValues(COMPARE1)
+
+    def testValues2(self):
+        self._testValues(COMPARE2)
+
+    def testValues3(self):
+        self._testValues(COMPARE3)
+
+    def testFileValues1(self):
+        self._testFileValues(COMPARE1)
+
+    def testFileValues2(self):
+        self._testFileValues(COMPARE2)
+
+    def testFileValues3(self):
+        self._testFileValues(COMPARE3)
+
+    def testNonsense(self):
+        parser = _syck.Parser(None)
+        self.assertRaises(AttributeError, (lambda: parser.parse()))
+        parser.close()
+
+    def _testValues(self, (source, structure)):
+        parser = _syck.Parser(source)
+        document = parser.parse()
+        self.assertEqualStructure(document, structure)
+        parser.close()
+
+    def _testFileValues(self, (source, structure)):
+        parser = _syck.Parser(StringIO.StringIO(source))
+        document = parser.parse()
+        self.assertEqualStructure(document, structure)
+        parser.close()
+
+    def assertEqualStructure(self, node, structure):
+        if node.kind == 'scalar':
+            self.assertEqual(type(structure), str)
+            self.assertEqual(node.value, structure)
+        elif node.kind == 'seq':
+            self.assertEqual(type(structure), list)
+            self.assertEqual(len(node.value), len(structure))
+            for i, item in enumerate(node.value):
+                self.assertEqualStructure(item, structure[i])
+        elif node.kind == 'map':
+            self.assertEqual(type(structure), dict)
+            self.assertEqual(len(node.value), len(structure))
+            for key in node.value:
+                self.assert_(key.value in structure)
+                self.assertEqualStructure(node.value[key], structure[key.value])
+
+class TestDocuments(unittest.TestCase):
+
+    def testDocuments0(self):
+        self._testDocuments(DOCUMENTS0, 0)
+
+    def testDocuments1(self):
+        self._testDocuments(DOCUMENTS1, 1)
+
+    def testDocuments2(self):
+        self._testDocuments(DOCUMENTS2, 2)
+
+    def testDocuments3(self):
+        self._testDocuments(DOCUMENTS3, 3)
+
+    def _testDocuments(self, source, length):
+        parser = _syck.Parser(source)
+        documents = parser.parse_documents()
+        self.assertEqual(len(documents), length)
+        parser.close()
+        parser = _syck.Parser(source)
+        for k in range(length):
+            document = parser.parse()
+            self.assert_(document)
+        self.assertEqual(parser.parse(), None)
+        parser.close()
+
+class TestImplicitTyping(unittest.TestCase):
+
+    def testImplicitAndExpansionTyping(self):
+        self._testTyping(True, True)
+
+    def testImplicitTyping(self):
+        self._testTyping(True, False)
+
+    def testExpansionTyping(self):
+        self._testTyping(False, True)
+
+    def testNoTyping(self):
+        self._testTyping(False, False)
+
+    def _testTyping(self, implicit_typing, taguri_expansion):
+        parser = _syck.Parser(IMPLICIT_TYPING[0], implicit_typing, taguri_expansion)
+        for node, (type_id, explicit) in zip(parser.parse().value, IMPLICIT_TYPING[1]):
+            if type_id is not None and taguri_expansion:
+                type_id = 'tag:yaml.org,2002:%s' % type_id
+            if implicit_typing or explicit:
+                self.assertEqual(node.type_id, type_id)
+            else:
+                self.assertEqual(node.type_id, None)
+
+class TestExplicitTyping(unittest.TestCase):
+
+    def testExplicitTyping(self):
+        parser = _syck.Parser(EXPLICIT_TYPING[0])
+        for node, type_id in zip(parser.parse().value, EXPLICIT_TYPING[1]):
+            self.assertEqual(node.type_id, type_id)
 
 def main(module='__main__'):
