[TableOfContents]

Out of date

2006-03-15. The rest of this page is quite out of date.

More information is available here:

What is Syck?

The Speedy YAML Cobble-Yourself-a-Slick-Little-Parser Kit. Created by WhyTheLuckyStiff.

Syck is a YAML parser written in C with the sole purpose of importing symbols into a scripting language's symbol table.

See the Syck HomePage for more.

How far along is Syck?

As of 2003 Oct 14, Syck 0.42 has been released and is in active development. Inlines, anchors, aliases, single-quoted, double-quoted, plain strings and transfer methods are working. Indentation is quite good, most features work great at this point.

Extensions for Ruby, Python and PHP are working.

Where can I check it out?

SourceForge CVS: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/yaml4r/syck/

Syck 0.42:

http://prdownloads.sourceforge.net/yaml4r/syck-0.42.tar.gz?download

CVS:

cvs -d:pserver:anonymous@rubyforge.org:/var/cvs/syck login
cvs -z3 -d:pserver:anonymous@rubyforge.org:/var/cvs/syck co syck

How does it work?

The parser simply builds SyckNodes. The parser passes these nodes to a handler function, designated in the wrapper code. The handler returns a SYMID (an unsigned long), which references an entry in the language's symbol table.

In Ruby, the SYMID is identical to the VALUE id used internally. In Python and PHP (which I have extensions for), Syck uses a temporary symbol table which links SYMIDs to PyObject pointers or PHP's zval pointers. I imagine Perl would have SV pointers.

What about LibYaml?

This work is not meant to compete with libyaml. Libyaml is just too big of a project for me to dig my claws into. I've tried looking at the code, but it's currently in an unbuildable state and I'm not sure where Neil left off.

Plus, the idea behind Syck is to keep it all small footprint. As SyckNodes are handled by the scripting language, the nodes are freed. The strings and pointers that comprised the node become housed by the scripting language. It's bloody fast, I'm telling you.

How do I install?

From CVS:

cvs co syck
cd syck
sh bootstrap
./configure
make
make check
sudo make install

You don't need to have syck installed to install the Ruby module, but it does have to be `make'd. Since the syck Ruby module uses Ruby's own symbol table directly, the `extconf.rb' script copies only the pertinent source files and build the module from that:

cd syck/ext/ruby
ruby install.rb config
ruby install.rb setup
sudo ruby install.rb install

Python requires libsyck installed:

cd syck/ext/python
python setup.py build
sudo python setup.py install

PHP requires libsyck and commandline PHP installed:

cd syck/ext/php
sh make_module.sh
sudo make install

Each of these extensions only has the `load' method, which accepts a YAML string.

Interfacing with Syck in C

Creating a New Parser

SyckParser *parser;
parser = syck_new_parser();

/* Parse here */

syck_free_parser(parser);

Setting Parser Options

// Implicit typing on? (0 = NO; 1 = YES)
syck_parser_implicit_typing(parser, 1);

// Taguri expansion? (0 = NO; 1 = YES)
syck_parser_taguri_expansion(parser, 0);

// Node handler: SYMID my_node_loader( SyckParser *, SyckNode * );
syck_parser_handler(parser, my_node_loader);

// Error handler: void my_syck_error( SyckParser *, char * );
syck_parser_error_handler(parser, my_syck_error);

// Set FILE handle and read callback ( NULL for default callback ).
syck_parser_file(parser, fp, NULL);

// Set string IO and read callback ( NULL for default callback ).
syck_parser_str(parser, str, len, my_string_read);

// Parse, returning root symbol.
root = syck_parse(parser);

The SyckNode Struct

typedef struct _syck_node SyckNode;
struct _syck_node {
    // Symbol table ID
    SYMID id;
    // Underlying kind
    enum syck_kind_tag kind;
    // Fully qualified tag-uri for type
    char *type_id;
    // Anchor name
    char *anchor;
    union {
        // Storage for map data
        struct SyckMap {
            SYMID *keys;
            SYMID *values;
            long capa;
            long idx;
        } *pairs;
        // Storage for sequence data
        struct SyckSeq {
            SYMID *items;
            long capa;
            long idx;
        } *list;
        // Storage for string data
        struct SyckStr {
            char *ptr;
            long len;
        } *str;
    } data;
};