Commits

Kirill Simonov  committed 143b6d9

Refactor internal and external API.

  • Participants
  • Parent commits 7a1c556

Comments (0)

Files changed (11)

File include/yaml.h

     YAML_FOLDED_SCALAR_STYLE
 } yaml_scalar_style_t;
 
-
 /** Sequence styles. */
 typedef enum {
     YAML_ANY_SEQUENCE_STYLE,
     YAML_ANY_MAPPING_STYLE,
 
     YAML_BLOCK_MAPPING_STYLE,
-    YAML_FLOW_MAPPING_STYLE
+    YAML_FLOW_MAPPING_STYLE,
+    YAML_FLOW_SET_MAPPING_STYLE
 } yaml_mapping_style_t;
 
 /** @} */
 
 /** Token types. */
 typedef enum {
+    YAML_NO_TOKEN,
+
     YAML_STREAM_START_TOKEN,
     YAML_STREAM_END_TOKEN,
 
         struct {
             /** The tag handle. */
             yaml_char_t *handle;
-
             /** The tag suffix. */
             yaml_char_t *suffix;
         } tag;
 
         /** The scalar value (for @c YAML_SCALAR_TOKEN). */
         struct {
-
             /** The scalar value. */
             yaml_char_t *value;
-
             /** The length of the scalar value. */
             size_t length;
-
             /** The scalar style. */
             yaml_scalar_style_t style;
         } scalar;
         struct {
             /** The major version number. */
             int major;
-
             /** The minor version number. */
             int minor;
         } version_directive;
         struct {
             /** The tag handle. */
             yaml_char_t *handle;
-
             /** The tag prefix. */
             yaml_char_t *prefix;
         } tag_directive;
+
     } data;
 
     /** The beginning of the token. */
     yaml_mark_t start_mark;
-
     /** The end of the token. */
     yaml_mark_t end_mark;
 
 } yaml_token_t;
 
 /**
- * Create a new token without assigning any data.
- *
- * This function can be used for constructing indicator tokens:
- * @c YAML_DOCUMENT_START, @c YAML_DOCUMENT_END,
- * @c YAML_BLOCK_SEQUENCE_START_TOKEN, @c YAML_BLOCK_MAPPING_START_TOKEN,
- * @c YAML_BLOCK_END_TOKEN,
- * @c YAML_FLOW_SEQUENCE_START_TOKEN, @c YAML_FLOW_SEQUENCE_END_TOKEN,
- * @c YAML_FLOW_MAPPING_START_TOKEN, @c YAML_FLOW_MAPPING_END_TOKEN,
- * @c YAML_BLOCK_ENTRY_TOKEN, @c YAML_FLOW_ENTRY_TOKEN,
- * @c YAML_KEY_TOKEN, @c YAML_VALUE_TOKEN.
- *
- * @param[in]   type        The token type.
- * @param[in]   start_mark  The beginning of the token.
- * @param[in]   end_mark    The end of the token.
- *
- * @returns A new token object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_token_new(yaml_token_type_t type,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_STREAM_START_TOKEN token with the specified encoding.
- *
- * @param[in]   encoding    The stream encoding.
- * @param[in]   start_mark  The beginning of the token.
- * @param[in]   end_mark    The end of the token.
- *
- * @returns A new token object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_stream_start_token_new(yaml_encoding_t encoding,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_STREAM_END_TOKEN token.
- *
- * @param[in]   start_mark  The beginning of the token.
- * @param[in]   end_mark    The end of the token.
- *
- * @returns A new token object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_stream_end_token_new(yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_VERSION_DIRECTIVE_TOKEN token with the specified
- * version numbers.
- *
- * @param[in]   major       The major version number.
- * @param[in]   minor       The minor version number.
- * @param[in]   start_mark  The beginning of the token.
- * @param[in]   end_mark    The end of the token.
- *
- * @returns A new token object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_version_directive_token_new(int major, int minor,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_TAG_DIRECTIVE_TOKEN token with the specified tag
- * handle and prefix.
- *
- * Note that the @a handle and the @a prefix pointers will be freed by
- * the token descructor.
- *
- * @param[in]   handle      The tag handle.
- * @param[in]   prefix      The tag prefix.
- * @param[in]   start_mark  The beginning of the token.
- * @param[in]   end_mark    The end of the token.
- *
- * @returns A new token object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_tag_directive_token_new(yaml_char_t *handle, yaml_char_t *prefix,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_ALIAS_TOKEN token with the specified anchor.
- *
- * Note that the @a anchor pointer will be freed by the token descructor.
- *
- * @param[in]   anchor      The anchor.
- * @param[in]   start_mark  The beginning of the token.
- * @param[in]   end_mark    The end of the token.
- *
- * @returns A new token object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_alias_token_new(yaml_char_t *anchor,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_ANCHOR_TOKEN token with the specified anchor.
- *
- * Note that the @a anchor pointer will be freed by the token descructor.
- *
- * @param[in]   anchor      The anchor.
- * @param[in]   start_mark  The beginning of the token.
- * @param[in]   end_mark    The end of the token.
- *
- * @returns A new token object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_anchor_token_new(yaml_char_t *anchor,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_TAG_TOKEN token with the specified tag handle and
- * suffix.
- *
- * Note that the @a handle and the @a suffix pointers will be freed by
- * the token descructor.
- *
- * @param[in]   handle      The tag handle.
- * @param[in]   suffix      The tag suffix.
- * @param[in]   start_mark  The beginning of the token.
- * @param[in]   end_mark    The end of the token.
- *
- * @returns A new token object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_tag_token_new(yaml_char_t *handle, yaml_char_t *suffix,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_SCALAR_TOKEN token with the specified scalar value,
- * length, and style.
- *
- * Note that the scalar value may contain the @c NUL character, therefore
- * the value length is also required.  The scalar value always ends with
- * @c NUL.
- *
- * Note that the @a value pointer will be freed by the token descructor.
- *
- * @param[in]   value       The scalar value.
- * @param[in]   length      The value length.
- * @param[in]   style       The scalar style.
- * @param[in]   start_mark  The beginning of the token.
- * @param[in]   end_mark    The end of the token.
- *
- * @returns A new token object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_scalar_token_new(yaml_char_t *value, size_t length,
-        yaml_scalar_style_t style,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Destroy a token object.
+ * Free any memory allocated for a token object.
  *
  * @param[in]   token   A token object.
  */
 
 /** Event types. */
 typedef enum {
+    YAML_NO_EVENT,
+
     YAML_STREAM_START_EVENT,
     YAML_STREAM_END_EVENT,
 
         struct {
             /** The version directive. */
             yaml_version_directive_t *version_directive;
+
             /** The list of tag directives. */
-            yaml_tag_directive_t **tag_directives;
+            struct {
+                /** The beginning of the tag directives list. */
+                yaml_tag_directive_t *start;
+                /** The end of the tag directives list. */
+                yaml_tag_directive_t *end;
+            } tag_directives;
+
             /** Is the document indicator implicit? */
             int implicit;
         } document_start;
 
     /** The beginning of the token. */
     yaml_mark_t start_mark;
-
     /** The end of the token. */
     yaml_mark_t end_mark;
+
 } yaml_event_t;
 
 /**
- * Create a new @c YAML_STREAM_START_EVENT event.
- *
- * @param[in]   encoding    The stream encoding.
- * @param[in]   start_mark  The beginning of the event.
- * @param[in]   end_mark    The end of the event.
- *
- * @returns A new event object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_stream_start_event_new(yaml_encoding_t encoding,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_STREAM_END_TOKEN event.
- *
- * @param[in]   start_mark  The beginning of the event.
- * @param[in]   end_mark    The end of the event.
- *
- * @returns A new event object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_stream_end_event_new(yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_DOCUMENT_START_EVENT event.
- *
- * @param[in]   version_directive   The version directive or @c NULL.
- * @param[in]   tag_directives      A list of tag directives or @c NULL.
- * @param[in]   implicit            Is the document indicator present?
- * @param[in]   start_mark          The beginning of the event.
- * @param[in]   end_mark            The end of the event.
- *
- * @returns A new event object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_document_start_event_new(yaml_version_directive_t *version_directive,
-        yaml_tag_directive_t **tag_directives, int implicit,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_DOCUMENT_END_EVENT event.
- *
- * @param[in]   implicit    Is the document end indicator present?
- * @param[in]   start_mark  The beginning of the event.
- * @param[in]   end_mark    The end of the event.
- *
- * @returns A new event object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_document_end_event_new(int implicit,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_ALIAS_EVENT event.
- *
- * @param[in]   anchor      The anchor value.
- * @param[in]   start_mark  The beginning of the event.
- * @param[in]   end_mark    The end of the event.
- *
- * @returns A new event object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_alias_event_new(yaml_char_t *anchor,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_SCALAR_EVENT event.
- *
- * @param[in]   anchor          The anchor value or @c NULL.
- * @param[in]   tag             The tag value or @c NULL.
- * @param[in]   value           The scalar value.
- * @param[in]   length          The length of the scalar value.
- * @param[in]   plain_implicit  Is the tag optional for the plain style?
- * @param[in]   quoted_implicit Is the tag optional for any non-plain style?
- * @param[in]   style           The scalar style.
- * @param[in]   start_mark      The beginning of the event.
- * @param[in]   end_mark        The end of the event.
- *
- * @returns A new event object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_scalar_event_new(yaml_char_t *anchor, yaml_char_t *tag,
-        yaml_char_t *value, size_t length,
-        int plain_implicit, int quoted_implicit,
-        yaml_scalar_style_t style,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_SEQUENCE_START_EVENT event.
- *
- * @param[in]   anchor      The anchor value or @c NULL.
- * @param[in]   tag         The tag value or @c NULL.
- * @param[in]   implicit    Is the tag optional?
- * @param[in]   style       The sequence style.
- * @param[in]   start_mark  The beginning of the event.
- * @param[in]   end_mark    The end of the event.
- *
- * @returns A new event object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_sequence_start_event_new(yaml_char_t *anchor, yaml_char_t *tag,
-        int implicit, yaml_sequence_style_t style,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_SEQUENCE_END_EVENT event.
- *
- * @param[in]   start_mark  The beginning of the event.
- * @param[in]   end_mark    The end of the event.
- *
- * @returns A new event object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_sequence_end_event_new(yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_MAPPING_START_EVENT event.
- *
- * @param[in]   anchor      The anchor value or @c NULL.
- * @param[in]   tag         The tag value or @c NULL.
- * @param[in]   implicit    Is the tag optional?
- * @param[in]   style       The mapping style.
- * @param[in]   start_mark  The beginning of the event.
- * @param[in]   end_mark    The end of the event.
- *
- * @returns A new event object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_mapping_start_event_new(yaml_char_t *anchor, yaml_char_t *tag,
-        int implicit, yaml_mapping_style_t style,
-        yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Create a new @c YAML_MAPPING_END_EVENT event.
- *
- * @param[in]   start_mark  The beginning of the event.
- * @param[in]   end_mark    The end of the event.
- *
- * @returns A new event object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_mapping_end_event_new(yaml_mark_t start_mark, yaml_mark_t end_mark);
-
-/**
- * Destroy an event object.
+ * Free any memory allocated for an event object.
  *
  * @param[in]   event   An event object.
  */
         size_t *size_read);
 
 /**
- * This structure holds a string input specified by
- * @c yaml_parser_set_input_string.
- */
-
-typedef struct {
-    /** The string start pointer. */
-    unsigned char *start;
-
-    /** The string end pointer. */
-    unsigned char *end;
-
-    /** The string current position. */
-    unsigned char *current;
-} yaml_string_input_t;
-
-/**
  * This structure holds information about a potential simple key.
  */
 
 typedef struct {
+    /** Is a simple key possible? */
+    int possible;
+
     /** Is a simple key required? */
     int required;
 
     /** The number of the token. */
     size_t token_number;
 
-    /** The position index. */
-    size_t index;
-
-    /** The position line. */
-    size_t line;
-
-    /** The position column. */
-    size_t column;
-
     /** The position mark. */
     yaml_mark_t mark;
 } yaml_simple_key_t;
  * The states of the parser.
  */
 typedef enum {
-    YAML_PARSE_END_STATE,
     YAML_PARSE_STREAM_START_STATE,
     YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE,
     YAML_PARSE_DOCUMENT_START_STATE,
     YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE,
     YAML_PARSE_FLOW_MAPPING_KEY_STATE,
     YAML_PARSE_FLOW_MAPPING_VALUE_STATE,
-    YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE
+    YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE,
+    YAML_PARSE_END_STATE
 } yaml_parser_state_t;
 
 /**
 
     /** Error type. */
     yaml_error_type_t error;
-
     /** Error description. */
     const char *problem;
-
     /** The byte about which the problem occured. */
     size_t problem_offset;
-
     /** The problematic value (@c -1 is none). */
     int problem_value;
-
     /** The problem position. */
     yaml_mark_t problem_mark;
-
     /** The error context. */
     const char *context;
-
     /** The context position. */
     yaml_mark_t context_mark;
 
     /** A pointer for passing to the read handler. */
     void *read_handler_data;
 
+    /** Standard (string or file) input data. */
+    union {
+        /** String input data. */
+        struct {
+            /** The string start pointer. */
+            unsigned char *start;
+            /** The string end pointer. */
+            unsigned char *end;
+            /** The string current position. */
+            unsigned char *current;
+        } string;
+
+        /** File input data. */
+        FILE *file;
+    } input;
+
     /** EOF flag */
     int eof;
 
-    /** The pointer to the beginning of the working buffer. */
-    yaml_char_t *buffer;
+    /** The working buffer. */
+    struct {
+        /* The beginning of the buffer. */
+        yaml_char_t *start;
+        /* The end of the buffer. */
+        yaml_char_t *end;
+        /* The current position of the buffer. */
+        yaml_char_t *pointer;
+        /* The last filled position of the buffer. */
+        yaml_char_t *last;
+    } buffer;
 
-    /** The pointer to the end of the working buffer. */
-    yaml_char_t *buffer_end;
-
-    /** The pointer to the current character in the working buffer. */
-    yaml_char_t *pointer;
-
-    /** The number of unread characters in the working buffer. */
+    /* The number of unread characters in the buffer. */
     size_t unread;
 
-    /** The pointer to the beginning of the raw buffer. */
-    unsigned char *raw_buffer;
-
-    /** The pointer to the current character in the raw buffer. */
-    unsigned char *raw_pointer;
-
-    /** The number of unread bytes in the raw buffer. */
-    size_t raw_unread;
+    /** The raw buffer. */
+    struct {
+        /** The beginning of the buffer. */
+        unsigned char *start;
+        /** The end of the buffer. */
+        unsigned char *end;
+        /** The current position of the buffer. */
+        unsigned char *pointer;
+        /** The last filled position of the buffer. */
+        unsigned char *last;
+    } raw_buffer;
 
     /** The input encoding. */
     yaml_encoding_t encoding;
     /** The offset of the current position (in bytes). */
     size_t offset;
 
-    /** The index of the current position (in characters). */
-    size_t index;
-
-    /** The line of the current position (starting from @c 0). */
-    size_t line;
-
-    /** The column of the current position (starting from @c 0). */
-    size_t column;
-
-    /* String input structure. */
-    yaml_string_input_t string_input;
+    /** The mark of the current position. */
+    yaml_mark_t mark;
 
     /**
      * @}
     /** The number of unclosed '[' and '{' indicators. */
     int flow_level;
 
-    /** The tokens queue, which contains the current produced tokens. */
-    yaml_token_t **tokens;
+    /** The tokens queue. */
+    struct {
+        /** The beginning of the tokens queue. */
+        yaml_token_t *start;
+        /** The end of the tokens queue. */
+        yaml_token_t *end;
+        /** The head of the tokens queue. */
+        yaml_token_t *head;
+        /** The tail of the tokens queue. */
+        yaml_token_t *tail;
+    } tokens;
 
-    /** The size of the tokens queue. */
-    size_t tokens_size;
-
-    /** The head of the tokens queue. */
-    size_t tokens_head;
-
-    /** The tail of the tokens queue. */
-    size_t tokens_tail;
-
-    /** The number of tokens fetched from the tokens queue. */
+    /** The number of tokens fetched from the queue. */
     size_t tokens_parsed;
 
-    /** The stack of indentation levels. */
-    int *indents;
+    /* Does the tokens queue contain a token ready for dequeueing. */
+    int token_available;
 
-    /** The size of the indents stack. */
-    size_t indents_size;
-
-    /** The number of items in the indents stack. */
-    size_t indents_length;
+    /** The indentation levels stack. */
+    struct {
+        /** The beginning of the stack. */
+        int *start;
+        /** The end of the stack. */
+        int *end;
+        /** The top of the stack. */
+        int *top;
+    } indents;
 
     /** The current indentation level. */
     int indent;
     /** May a simple key occur at the current position? */
     int simple_key_allowed;
 
-    /** The stack of potential simple keys. */
-    yaml_simple_key_t **simple_keys;
-
-    /** The size of the simple keys stack. */
-    size_t simple_keys_size;
+    /** The stack of simple keys. */
+    struct {
+        /** The beginning of the stack. */
+        yaml_simple_key_t *start;
+        /** The end of the stack. */
+        yaml_simple_key_t *end;
+        /** The top of the stack. */
+        yaml_simple_key_t *top;
+    } simple_keys;
 
     /**
      * @}
      */
 
     /** The parser states stack. */
-    yaml_parser_state_t *states;
-
-    /** The size of the parser states stack. */
-    size_t states_size;
-
-    /** The number of items in the parser states stack. */
-    size_t states_length;
+    struct {
+        /** The beginning of the stack. */
+        yaml_parser_state_t *start;
+        /** The end of the stack. */
+        yaml_parser_state_t *end;
+        /** The top of the stack. */
+        yaml_parser_state_t *top;
+    } states;
 
     /** The current parser state. */
     yaml_parser_state_t state;
 
     /** The stack of marks. */
-    yaml_mark_t *marks;
-
-    /** The size of the marks stack. */
-    size_t marks_size;
-
-    /** The number of items in the marks stack. */
-    size_t marks_length;
-
-    /** The current event. */
-    yaml_event_t *current_event;
-
-    /** The YAML version directive. */
-    yaml_version_directive_t *version_directive;
+    struct {
+        /** The beginning of the stack. */
+        yaml_mark_t *start;
+        /** The end of the stack. */
+        yaml_mark_t *end;
+        /** The top of the stack. */
+        yaml_mark_t *top;
+    } marks;
 
     /** The list of TAG directives. */
-    yaml_tag_directive_t **tag_directives;
-
-    /** The size of the TAG directives list. */
-    size_t tag_directives_size;
-
-    /** The number of items in the TAG directives list. */
-    size_t tag_directives_length;
+    struct {
+        /** The beginning of the list. */
+        yaml_tag_directive_t *start;
+        /** The end of the list. */
+        yaml_tag_directive_t *end;
+        /** The top of the list. */
+        yaml_tag_directive_t *top;
+    } tag_directives;
 
     /**
      * @}
 } yaml_parser_t;
 
 /**
- * Create a new parser.
+ * Initialize a parser.
  *
  * This function creates a new parser object.  An application is responsible
  * for destroying the object using the @c yaml_parser_delete function.
  *
- * @returns A new parser object; @c NULL on error.
+ * @param[in]   parser  An empty parser object.
+ *
+ * @returns #c 1 if the function succeeded, @c 0 on error.
  */
 
-YAML_DECLARE(yaml_parser_t *)
-yaml_parser_new(void);
+YAML_DECLARE(int)
+yaml_parser_initialize(yaml_parser_t *parser);
 
 /**
  * Destroy a parser.
 yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding);
 
 /**
- * Get the next token.
+ * Scan the input stream and produce the next token.
  *
- * The token is removed from the internal token queue and the application is
- * responsible for destroing the token object.
+ * Call the function subsequently to produce a sequence of tokens corresponding
+ * to the input stream.  The initial token has the type
+ * @c YAML_STREAM_START_TOKEN while the ending token has the type
+ * @c YAML_STREAM_END_TOKEN.
+ *
+ * An application is responsible for freeing any buffers associated with the
+ * produced token object using the @c yaml_token_delete function.
+ *
+ * An application must not alternate the calls of @c yaml_parser_scan with the
+ * calls of @c yaml_parser_parse. Doing this will break the parser.
  *
  * @param[in]   parser      A parser object.
+ * @param[in]   token       An empty token object.
  *
- * @returns A token object, or @c NULL on error.
+ * @returns @c 1 if the function succeeded, @c 0 on error.
  */
 
-YAML_DECLARE(yaml_token_t *)
-yaml_parser_get_token(yaml_parser_t *parser);
+YAML_DECLARE(int)
+yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token);
 
 /**
- * Peek the next token.
+ * Parse the input stream and produce the next parsing event.
  *
- * The token is not removed from the internal token queue and will be returned
- * again on a subsequent call of @c yaml_parser_get_token or
- * @c yaml_parser_peek_token. The application should not destroy the token
- * object.
+ * Call the function subsequently to produce a sequence of events corresponding
+ * to the input stream.  The initial event has the type
+ * @c YAML_STREAM_START_EVENT while the ending event has the type
+ * @c YAML_STREAM_END_EVENT.
+ *
+ * An application is responsible for freeing any buffers associated with the
+ * produced event object using the @c yaml_event_delete function.
+ *
+ * An application must not alternate the calls of @c yaml_parser_scan with the
+ * calls of @c yaml_parser_parse. Doing this will break the parser.
  *
  * @param[in]   parser      A parser object.
+ * @param[in]   event       An empty event object.
  *
- * @returns A token object, or @c NULL on error.
+ * @returns @c 1 if the function succeeded, @c 0 on error.
  */
 
-YAML_DECLARE(yaml_token_t *)
-yaml_parser_peek_token(yaml_parser_t *parser);
-
-/**
- * Get the next event.
- *
- * The application is responsible for destroing the event object.
- *
- * @param[in]   parser      A parser object.
- *
- * @returns An event object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_parser_get_event(yaml_parser_t *parser);
-
-/**
- * Peek the next event.
- *
- * The event will be returned again on a subsequent call of
- * @c yaml_parser_get_event or @c yaml_parser_peek_event.  The application
- * should not destroy the event object.
- *
- * @param[in]   parser      A parser object.
- *
- * @returns An event object, or @c NULL on error.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_parser_peek_event(yaml_parser_t *parser);
+YAML_DECLARE(int)
+yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event);
 
 /** @} */
 
 /*
 typedef struct {
 } yaml_emitter_t;
-*/
-
-/**
- * @defgroup internal Internal Definitions
- * @{
- */
-
-/**
- * Allocate a dynamic memory block.
- *
- * @param[in]   size    Size of a memory block, \c 0 is valid.
- *
- * @returns @c yaml_malloc returns a pointer to a newly allocated memory block,
- * or @c NULL if it failed.
- */
-
-YAML_DECLARE(void *)
-yaml_malloc(size_t size);
-
-/**
- * Reallocate a dynamic memory block.
- *
- * @param[in]   ptr     A pointer to an existing memory block, \c NULL is
- *                      valid.
- * @param[in]   size    A size of a new block, \c 0 is valid.
- *
- * @returns @c yaml_realloc returns a pointer to a reallocated memory block,
- * or @c NULL if it failed.
- */
-
-YAML_DECLARE(void *)
-yaml_realloc(void *ptr, size_t size);
-
-/**
- * Free a dynamic memory block.
- *
- * @param[in]   ptr     A pointer to an existing memory block, \c NULL is
- *                      valid.
- */
-
-YAML_DECLARE(void)
-yaml_free(void *ptr);
-
-/** The initial size for various buffers. */
-
-#define YAML_DEFAULT_SIZE   16
-
-/** The size of the raw buffer. */
-
-#define YAML_RAW_BUFFER_SIZE 16384
-
-/**
- * The size of the buffer.
- *
- * We allocate enough space for decoding the whole raw buffer.
- */
-
-#define YAML_BUFFER_SIZE    (YAML_RAW_BUFFER_SIZE*3)
-
-/**
- * Ensure that the buffer contains at least @a length characters.
- *
- * @param[in]   parser  A parser object.
- * @param[in]   length  The number of characters in the buffer.
- *
- * @returns @c 1 on success, @c 0 on error.
- */
 
 YAML_DECLARE(int)
-yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
+yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event);
 
-/** @} */
+YAML_DECLARE(int)
+yaml_emitter_emit_stream_start(yaml_emitter_t *emitter,
+        yaml_encoding_t encoding);
 
+*/
 
 #ifdef __cplusplus
 }
 
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "yaml_private.h"
 
-#include <yaml.h>
-
-#include <assert.h>
+/*
+ * Get the library version.
+ */
 
 YAML_DECLARE(const char *)
 yaml_get_version_string(void)
     return YAML_VERSION_STRING;
 }
 
+/*
+ * Get the library version numbers.
+ */
+
 YAML_DECLARE(void)
 yaml_get_version(int *major, int *minor, int *patch)
 {
 }
 
 /*
+ * Duplicate a string.
+ */
+
+YAML_DECLARE(char *)
+yaml_strdup(const char *str)
+{
+    return strdup(str);
+}
+
+/*
+ * Extend a string.
+ */
+
+YAML_DECLARE(int)
+yaml_string_extend(yaml_char_t **start,
+        yaml_char_t **pointer, yaml_char_t **end)
+{
+    void *new_start = yaml_realloc(*start, (*end - *start)*2);
+
+    if (!new_start) return 0;
+
+    memset(new_start + (*end - *start), 0, *end - *start);
+
+    *pointer = new_start + (*pointer - *start);
+    *end = new_start + (*end - *start)*2;
+    *start = new_start;
+
+    return 1;
+}
+
+/*
+ * Append a string B to a string A.
+ */
+
+YAML_DECLARE(int)
+yaml_string_join(
+        yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
+        yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end)
+{
+    if (*b_start == *b_pointer)
+        return 1;
+
+    while (*a_end - *a_pointer <= *b_pointer - *b_start) {
+        if (!yaml_string_extend(a_start, a_pointer, a_end))
+            return 0;
+    }
+
+    memcpy(*a_pointer, *b_start, *b_pointer - *b_start);
+    *a_pointer += *b_pointer - *b_start;
+
+    return 1;
+}
+
+/*
+ * Extend a stack.
+ */
+
+YAML_DECLARE(int)
+yaml_stack_extend(void **start, void **top, void **end)
+{
+    void *new_start = yaml_realloc(*start, (*end - *start)*2);
+
+    if (!new_start) return 0;
+
+    *top = new_start + (*top - *start);
+    *end = new_start + (*end - *start)*2;
+    *start = new_start;
+
+    return 1;
+}
+
+/*
+ * Extend or move a queue.
+ */
+
+YAML_DECLARE(int)
+yaml_queue_extend(void **start, void **head, void **tail, void **end)
+{
+    /* Check if we need to resize the queue. */
+
+    if (*start == *head && *tail == *end) {
+        void *new_start = yaml_realloc(*start, (*end - *start)*2);
+
+        if (!new_start) return 0;
+
+        *head = new_start + (*head - *start);
+        *tail = new_start + (*tail - *start);
+        *end = new_start + (*end - *start)*2;
+        *start = new_start;
+    }
+
+    /* Check if we need to move the queue at the beginning of the buffer. */
+
+    if (*tail == *end) {
+        if (*head != *tail) {
+            memmove(*start, *head, *tail - *head);
+        }
+        *tail -= *head - *start;
+        *head = *start;
+    }
+
+    return 1;
+}
+
+
+/*
  * Create a new parser object.
  */
 
-YAML_DECLARE(yaml_parser_t *)
-yaml_parser_new(void)
+YAML_DECLARE(int)
+yaml_parser_initialize(yaml_parser_t *parser)
 {
-    yaml_parser_t *parser;
-
-    /* Allocate the parser structure. */
-
-    parser = yaml_malloc(sizeof(yaml_parser_t));
-    if (!parser) goto error;
+    assert(parser);     /* Non-NULL parser object expected. */
 
     memset(parser, 0, sizeof(yaml_parser_t));
+    if (!BUFFER_INIT(parser, parser->raw_buffer, RAW_BUFFER_SIZE))
+        goto error;
+    if (!BUFFER_INIT(parser, parser->buffer, BUFFER_SIZE))
+        goto error;
+    if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE))
+        goto error;
+    if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_SIZE))
+        goto error;
+    if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_SIZE))
+        goto error;
+    if (!STACK_INIT(parser, parser->states, INITIAL_STACK_SIZE))
+        goto error;
+    if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_SIZE))
+        goto error;
+    if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_SIZE))
+        goto error;
 
-    /* Allocate the raw buffer. */
-
-    parser->raw_buffer = yaml_malloc(YAML_RAW_BUFFER_SIZE);
-    if (!parser->raw_buffer) goto error;
-    memset(parser->raw_buffer, 0, YAML_RAW_BUFFER_SIZE);
-
-    parser->raw_pointer = parser->raw_buffer;
-    parser->raw_unread = 0;
-
-    /* Allocate the character buffer. */
-
-    parser->buffer = yaml_malloc(YAML_BUFFER_SIZE);
-    if (!parser->buffer) goto error;
-    memset(parser->buffer, 0, YAML_BUFFER_SIZE);
-
-    parser->buffer_end = parser->buffer;
-    parser->pointer = parser->buffer;
-    parser->unread = 0;
-
-    /* Allocate the tokens queue. */
-
-    parser->tokens = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(yaml_token_t *));
-    if (!parser->tokens) goto error;
-    memset(parser->tokens, 0, YAML_DEFAULT_SIZE*sizeof(yaml_token_t *));
-
-    parser->tokens_size = YAML_DEFAULT_SIZE;
-    parser->tokens_head = 0;
-    parser->tokens_tail = 0;
-    parser->tokens_parsed = 0;
-
-    /* Allocate the indents stack. */
-
-    parser->indents = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(int));
-    if (!parser->indents) goto error;
-    memset(parser->indents, 0, YAML_DEFAULT_SIZE*sizeof(int));
-
-    parser->indents_size = YAML_DEFAULT_SIZE;
-    parser->indents_length = 0;
-
-    /* Allocate the stack of potential simple keys. */
-
-    parser->simple_keys = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(yaml_simple_key_t *));
-    if (!parser->simple_keys) goto error;
-    memset(parser->simple_keys, 0, YAML_DEFAULT_SIZE*sizeof(yaml_simple_key_t *));
-
-    parser->simple_keys_size = YAML_DEFAULT_SIZE;
-
-    /* Allocate the stack of parser states. */
-
-    parser->states = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(yaml_parser_state_t));
-    if (!parser->states) goto error;
-    memset(parser->states, 0, YAML_DEFAULT_SIZE*sizeof(yaml_parser_state_t));
-
-    parser->states_size = YAML_DEFAULT_SIZE;
-
-    /* Set the initial state. */
-
-    parser->state = YAML_PARSE_STREAM_START_STATE;
-
-    /* Allocate the stack of marks. */
-
-    parser->marks = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(yaml_mark_t));
-    if (!parser->marks) goto error;
-    memset(parser->marks, 0, YAML_DEFAULT_SIZE*sizeof(yaml_mark_t));
-
-    parser->marks_size = YAML_DEFAULT_SIZE;
-
-    /* Allocate the list of TAG directives. */
-
-    parser->tag_directives = yaml_malloc(YAML_DEFAULT_SIZE*sizeof(yaml_tag_directive_t *));
-    if (!parser->tag_directives) goto error;
-    memset(parser->tag_directives, 0, YAML_DEFAULT_SIZE*sizeof(yaml_tag_directive_t *));
-
-    parser->tag_directives_size = YAML_DEFAULT_SIZE;
-
-    /* Done. */
-
-    return parser;
-
-    /* On error, free allocated buffers. */
+    return 1;
 
 error:
 
-    if (!parser) return NULL;
+    BUFFER_DEL(parser, parser->raw_buffer);
+    BUFFER_DEL(parser, parser->buffer);
+    QUEUE_DEL(parser, parser->tokens);
+    STACK_DEL(parser, parser->indents);
+    STACK_DEL(parser, parser->simple_keys);
+    STACK_DEL(parser, parser->states);
+    STACK_DEL(parser, parser->marks);
+    STACK_DEL(parser, parser->tag_directives);
 
-    yaml_free(parser->tag_directives);
-    yaml_free(parser->marks);
-    yaml_free(parser->states);
-    yaml_free(parser->simple_keys);
-    yaml_free(parser->indents);
-    yaml_free(parser->tokens);
-    yaml_free(parser->buffer);
-    yaml_free(parser->raw_buffer);
-
-    yaml_free(parser);
-
-    return NULL;
+    return 0;
 }
 
 /*
 {
     assert(parser); /* Non-NULL parser object expected. */
 
-    /*yaml_free(parser->tag_directives);*/
-    yaml_free(parser->marks);
-    yaml_free(parser->states);
-    yaml_free(parser->simple_keys);
-    yaml_free(parser->indents);
-    yaml_free(parser->tokens);
-    yaml_free(parser->buffer);
-    yaml_free(parser->raw_buffer);
+    BUFFER_DEL(parser, parser->raw_buffer);
+    BUFFER_DEL(parser, parser->buffer);
+    while (!QUEUE_EMPTY(parser, parser->tokens)) {
+        yaml_token_delete(&DEQUEUE(parser, parser->tokens));
+    }
+    QUEUE_DEL(parser, parser->tokens);
+    STACK_DEL(parser, parser->indents);
+    STACK_DEL(parser, parser->simple_keys);
+    STACK_DEL(parser, parser->states);
+    STACK_DEL(parser, parser->marks);
+    while (!STACK_EMPTY(parser, parser->tag_directives)) {
+        yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
+        yaml_free(tag_directive.handle);
+        yaml_free(tag_directive.prefix);
+    }
+    STACK_DEL(parser, parser->tag_directives);
 
     memset(parser, 0, sizeof(yaml_parser_t));
-
-    yaml_free(parser);
 }
 
 /*
 yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
         size_t *size_read)
 {
-    yaml_string_input_t *input = data;
+    yaml_parser_t *parser = data;
 
-    if (input->current == input->end) {
+    if (parser->input.string.current == parser->input.string.end) {
         *size_read = 0;
         return 1;
     }
 
-    if (size > (input->end - input->current)) {
-        size = input->end - input->current;
+    if (size > (parser->input.string.end - parser->input.string.current)) {
+        size = parser->input.string.end - parser->input.string.current;
     }
 
-    memcpy(buffer, input->current, size);
-    input->current += size;
+    memcpy(buffer, parser->input.string.current, size);
+    parser->input.string.current += size;
     *size_read = size;
     return 1;
 }
 yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
         size_t *size_read)
 {
-    *size_read = fread(buffer, 1, size, (FILE *)data);
-    return !ferror((FILE *)data);
+    yaml_parser_t *parser = data;
+
+    *size_read = fread(buffer, 1, size, parser->input.file);
+    return !ferror(parser->input.file);
 }
 
 /*
     assert(!parser->read_handler);  /* You can set the source only once. */
     assert(input);  /* Non-NULL input string expected. */
 
-    parser->string_input.start = input;
-    parser->string_input.current = input;
-    parser->string_input.end = input+size;
+    parser->read_handler = yaml_string_read_handler;
+    parser->read_handler_data = parser;
 
-    parser->read_handler = yaml_string_read_handler;
-    parser->read_handler_data = &parser->string_input;
+    parser->input.string.start = input;
+    parser->input.string.current = input;
+    parser->input.string.end = input+size;
 }
 
 /*
     assert(file);   /* Non-NULL file object expected. */
 
     parser->read_handler = yaml_file_read_handler;
-    parser->read_handler_data = file;
+    parser->read_handler_data = parser;
+
+    parser->input.file = file;
 }
 
 /*
 }
 
 /*
- * Create a token.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_token_new(yaml_token_type_t type,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_token_t *token = yaml_malloc(sizeof(yaml_token_t));
-
-    if (!token) return NULL;
-
-    memset(token, 0, sizeof(yaml_token_t));
-
-    token->type = type;
-    token->start_mark = start_mark;
-    token->end_mark = end_mark;
-
-    return token;
-}
-
-/*
- * Create a STREAM-START token.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_stream_start_token_new(yaml_encoding_t encoding,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_token_t *token = yaml_token_new(YAML_STREAM_START_TOKEN,
-            start_mark, end_mark);
-
-    if (!token) return NULL;
-
-    token->data.stream_start.encoding = encoding;
-
-    return token;
-}
-
-/*
- * Create a STREAM-END token.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_stream_end_token_new(yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_token_t *token = yaml_token_new(YAML_STREAM_END_TOKEN,
-            start_mark, end_mark);
-
-    if (!token) return NULL;
-
-    return token;
-}
-
-/*
- * Create a VERSION-DIRECTIVE token.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_version_directive_token_new(int major, int minor,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_token_t *token = yaml_token_new(YAML_VERSION_DIRECTIVE_TOKEN,
-            start_mark, end_mark);
-
-    if (!token) return NULL;
-
-    token->data.version_directive.major = major;
-    token->data.version_directive.minor = minor;
-
-    return token;
-}
-
-/*
- * Create a TAG-DIRECTIVE token.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_tag_directive_token_new(yaml_char_t *handle, yaml_char_t *prefix,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_token_t *token = yaml_token_new(YAML_TAG_DIRECTIVE_TOKEN,
-            start_mark, end_mark);
-
-    if (!token) return NULL;
-
-    token->data.tag_directive.handle = handle;
-    token->data.tag_directive.prefix = prefix;
-
-    return token;
-}
-
-/*
- * Create an ALIAS token.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_alias_token_new(yaml_char_t *anchor,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_token_t *token = yaml_token_new(YAML_ALIAS_TOKEN,
-            start_mark, end_mark);
-
-    if (!token) return NULL;
-
-    token->data.alias.value = anchor;
-
-    return token;
-}
-
-/*
- * Create an ANCHOR token.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_anchor_token_new(yaml_char_t *anchor,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_token_t *token = yaml_token_new(YAML_ANCHOR_TOKEN,
-            start_mark, end_mark);
-
-    if (!token) return NULL;
-
-    token->data.anchor.value = anchor;
-
-    return token;
-}
-
-/*
- * Create a TAG token.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_tag_token_new(yaml_char_t *handle, yaml_char_t *suffix,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_token_t *token = yaml_token_new(YAML_TAG_TOKEN,
-            start_mark, end_mark);
-
-    if (!token) return NULL;
-
-    token->data.tag.handle = handle;
-    token->data.tag.suffix = suffix;
-
-    return token;
-}
-
-/*
- * Create a SCALAR token.
- */
-
-YAML_DECLARE(yaml_token_t *)
-yaml_scalar_token_new(yaml_char_t *value, size_t length,
-        yaml_scalar_style_t style,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_token_t *token = yaml_token_new(YAML_SCALAR_TOKEN,
-            start_mark, end_mark);
-
-    if (!token) return NULL;
-
-    token->data.scalar.value = value;
-    token->data.scalar.length = length;
-    token->data.scalar.style = style;
-
-    return token;
-}
-
-/*
  * Destroy a token object.
  */
 
     }
 
     memset(token, 0, sizeof(yaml_token_t));
-
-    yaml_free(token);
-}
-
-/*
- * Create an event.
- */
-
-static yaml_event_t *
-yaml_event_new(yaml_event_type_t type,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_event_t *event = yaml_malloc(sizeof(yaml_event_t));
-
-    if (!event) return NULL;
-
-    memset(event, 0, sizeof(yaml_event_t));
-
-    event->type = type;
-    event->start_mark = start_mark;
-    event->end_mark = end_mark;
-
-    return event;
-}
-
-/*
- * Create a STREAM-START event.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_stream_start_event_new(yaml_encoding_t encoding,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_event_t *event = yaml_event_new(YAML_STREAM_START_EVENT,
-            start_mark, end_mark);
-
-    if (!event) return NULL;
-
-    event->data.stream_start.encoding = encoding;
-
-    return event;
-}
-
-/*
- * Create a STREAM-END event.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_stream_end_event_new(yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    return yaml_event_new(YAML_STREAM_END_EVENT, start_mark, end_mark);
-}
-
-/*
- * Create a DOCUMENT-START event.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_document_start_event_new(yaml_version_directive_t *version_directive,
-        yaml_tag_directive_t **tag_directives, int implicit,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_event_t *event = yaml_event_new(YAML_DOCUMENT_START_EVENT,
-            start_mark, end_mark);
-
-    if (!event) return NULL;
-
-    event->data.document_start.version_directive = version_directive;
-    event->data.document_start.tag_directives = tag_directives;
-    event->data.document_start.implicit = implicit;
-
-    return event;
-}
-
-/*
- * Create a DOCUMENT-END event.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_document_end_event_new(int implicit,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_event_t *event = yaml_event_new(YAML_DOCUMENT_END_EVENT,
-            start_mark, end_mark);
-
-    if (!event) return NULL;
-
-    event->data.document_end.implicit = implicit;
-
-    return event;
-}
-
-/*
- * Create an ALIAS event.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_alias_event_new(yaml_char_t *anchor,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_event_t *event = yaml_event_new(YAML_ALIAS_EVENT,
-            start_mark, end_mark);
-
-    if (!event) return NULL;
-
-    event->data.alias.anchor = anchor;
-
-    return event;
-}
-
-/*
- * Create a SCALAR event.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_scalar_event_new(yaml_char_t *anchor, yaml_char_t *tag,
-        yaml_char_t *value, size_t length,
-        int plain_implicit, int quoted_implicit,
-        yaml_scalar_style_t style,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_event_t *event = yaml_event_new(YAML_SCALAR_EVENT,
-            start_mark, end_mark);
-
-    if (!event) return NULL;
-
-    event->data.scalar.anchor = anchor;
-    event->data.scalar.tag = tag;
-    event->data.scalar.value = value;
-    event->data.scalar.length = length;
-    event->data.scalar.plain_implicit = plain_implicit;
-    event->data.scalar.quoted_implicit = quoted_implicit;
-    event->data.scalar.style = style;
-
-    return event;
-}
-
-/*
- * Create a SEQUENCE-START event.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_sequence_start_event_new(yaml_char_t *anchor, yaml_char_t *tag,
-        int implicit, yaml_sequence_style_t style,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_event_t *event = yaml_event_new(YAML_SEQUENCE_START_EVENT,
-            start_mark, end_mark);
-
-    if (!event) return NULL;
-
-    event->data.sequence_start.anchor = anchor;
-    event->data.sequence_start.tag = tag;
-    event->data.sequence_start.implicit = implicit;
-    event->data.sequence_start.style = style;
-
-    return event;
-}
-
-/*
- * Create a SEQUENCE-END event.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_sequence_end_event_new(yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    return yaml_event_new(YAML_SEQUENCE_END_EVENT, start_mark, end_mark);
-}
-
-/*
- * Create a MAPPING-START event.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_mapping_start_event_new(yaml_char_t *anchor, yaml_char_t *tag,
-        int implicit, yaml_mapping_style_t style,
-        yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    yaml_event_t *event = yaml_event_new(YAML_MAPPING_START_EVENT,
-            start_mark, end_mark);
-
-    if (!event) return NULL;
-
-    event->data.mapping_start.anchor = anchor;
-    event->data.mapping_start.tag = tag;
-    event->data.mapping_start.implicit = implicit;
-    event->data.mapping_start.style = style;
-
-    return event;
-}
-
-/*
- * Create a MAPPING-END event.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_mapping_end_event_new(yaml_mark_t start_mark, yaml_mark_t end_mark)
-{
-    return yaml_event_new(YAML_MAPPING_END_EVENT, start_mark, end_mark);
 }
 
 /*
 YAML_DECLARE(void)
 yaml_event_delete(yaml_event_t *event)
 {
+    yaml_tag_directive_t *tag_directive;
+
     assert(event);  /* Non-NULL event object expected. */
 
     switch (event->type)
     {
         case YAML_DOCUMENT_START_EVENT:
-            /*yaml_free(event->data.document_start.version_directive);
-            if (event->data.document_start.tag_directives) {
-                yaml_tag_directive_t **tag_directive;
-                for (tag_directive = event->data.document_start.tag_directives;
-                        *tag_directive; tag_directive++) {
-                    yaml_free((*tag_directive)->handle);
-                    yaml_free((*tag_directive)->prefix);
-                    yaml_free(*tag_directive);
-                }
-                yaml_free(event->data.document_start.tag_directives);
-            }*/
+            yaml_free(event->data.document_start.version_directive);
+            for (tag_directive = event->data.document_start.tag_directives.start;
+                    tag_directive != event->data.document_start.tag_directives.end;
+                    tag_directive++) {
+                yaml_free(tag_directive->handle);
+                yaml_free(tag_directive->prefix);
+            }
+            yaml_free(event->data.document_start.tag_directives.start);
             break;
 
         case YAML_ALIAS_EVENT:
     }
 
     memset(event, 0, sizeof(yaml_event_t));
-
-    yaml_free(event);
 }
 

File src/parser.c

  * flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
  */
 
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "yaml_private.h"
 
-#include <yaml.h>
+/*
+ * Event initializers.
+ */
 
-#include <assert.h>
+#define EVENT_INIT(event,event_type,event_start_mark,event_end_mark)            \
+    (memset(&(event), 0, sizeof(yaml_event_t)),                                 \
+     (event).type = (event_type),                                               \
+     (event).start_mark = (event_start_mark),                                   \
+     (event).end_mark = (event_end_mark))
+
+#define STREAM_START_EVENT_INIT(event,event_encoding,start_mark,end_mark)       \
+    (EVENT_INIT((event),YAML_STREAM_START_EVENT,(start_mark),(end_mark)),       \
+     (event).data.stream_start.encoding = (event_encoding))
+
+#define STREAM_END_EVENT_INIT(event,start_mark,end_mark)                        \
+    (EVENT_INIT((event),YAML_STREAM_END_EVENT,(start_mark),(end_mark)))
+
+#define DOCUMENT_START_EVENT_INIT(event,event_version_directive,                \
+        event_tag_directives_start,event_tag_directives_end,event_implicit,start_mark,end_mark) \
+    (EVENT_INIT((event),YAML_DOCUMENT_START_EVENT,(start_mark),(end_mark)),     \
+     (event).data.document_start.version_directive = (event_version_directive), \
+     (event).data.document_start.tag_directives.start = (event_tag_directives_start),   \
+     (event).data.document_start.tag_directives.end = (event_tag_directives_end),   \
+     (event).data.document_start.implicit = (event_implicit))
+
+#define DOCUMENT_END_EVENT_INIT(event,event_implicit,start_mark,end_mark)       \
+    (EVENT_INIT((event),YAML_DOCUMENT_END_EVENT,(start_mark),(end_mark)),       \
+     (event).data.document_end.implicit = (event_implicit))
+
+#define ALIAS_EVENT_INIT(event,event_anchor,start_mark,end_mark)                \
+    (EVENT_INIT((event),YAML_ALIAS_EVENT,(start_mark),(end_mark)),              \
+     (event).data.alias.anchor = (event_anchor))
+
+#define SCALAR_EVENT_INIT(event,event_anchor,event_tag,event_value,event_length,    \
+        event_plain_implicit, event_quoted_implicit,event_style,start_mark,end_mark)    \
+    (EVENT_INIT((event),YAML_SCALAR_EVENT,(start_mark),(end_mark)),             \
+     (event).data.scalar.anchor = (event_anchor),                               \
+     (event).data.scalar.tag = (event_tag),                                     \
+     (event).data.scalar.value = (event_value),                                 \
+     (event).data.scalar.length = (event_length),                               \
+     (event).data.scalar.plain_implicit = (event_plain_implicit),               \
+     (event).data.scalar.quoted_implicit = (event_quoted_implicit),             \
+     (event).data.scalar.style = (event_style))
+
+#define SEQUENCE_START_EVENT_INIT(event,event_anchor,event_tag,                 \
+        event_implicit,event_style,start_mark,end_mark)                         \
+    (EVENT_INIT((event),YAML_SEQUENCE_START_EVENT,(start_mark),(end_mark)),     \
+     (event).data.sequence_start.anchor = (event_anchor),                       \
+     (event).data.sequence_start.tag = (event_tag),                             \
+     (event).data.sequence_start.implicit = (event_implicit),                   \
+     (event).data.sequence_start.style = (event_style))
+
+#define SEQUENCE_END_EVENT_INIT(event,start_mark,end_mark)                      \
+    (EVENT_INIT((event),YAML_SEQUENCE_END_EVENT,(start_mark),(end_mark)))
+
+#define MAPPING_START_EVENT_INIT(event,event_anchor,event_tag,                  \
+        event_implicit,event_style,start_mark,end_mark)                         \
+    (EVENT_INIT((event),YAML_MAPPING_START_EVENT,(start_mark),(end_mark)),      \
+     (event).data.mapping_start.anchor = (event_anchor),                        \
+     (event).data.mapping_start.tag = (event_tag),                              \
+     (event).data.mapping_start.implicit = (event_implicit),                    \
+     (event).data.mapping_start.style = (event_style))
+
+#define MAPPING_END_EVENT_INIT(event,start_mark,end_mark)                       \
+    (EVENT_INIT((event),YAML_MAPPING_END_EVENT,(start_mark),(end_mark)))
+
+/*
+ * Peek the next token in the token queue.
+ */
+
+#define PEEK_TOKEN(parser)                                                      \
+    ((parser->token_available || yaml_parser_fetch_more_tokens(parser)) ?       \
+        parser->tokens.head : NULL)
+
+/*
+ * Remove the next token from the queue (must be called after PEEK_TOKEN).
+ */
+
+#define SKIP_TOKEN(parser)                                                      \
+    (parser->token_available = 0,                                               \
+     parser->tokens_parsed ++,                                                  \
+     parser->stream_end_produced =                                              \
+        (parser->tokens.head->type == YAML_STREAM_END_TOKEN),                   \
+     parser->tokens.head ++)
 
 /*
  * Public API declarations.
  */
 
-YAML_DECLARE(yaml_event_t *)
-yaml_parser_get_event(yaml_parser_t *parser);
-
-YAML_DECLARE(yaml_event_t *)
-yaml_parser_peek_event(yaml_parser_t *parser);
+YAML_DECLARE(int)
+yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event);
 
 /*
  * Error handling.
         const char *problem, yaml_mark_t problem_mark);
 
 /*
- * Buffers and lists.
+ * State functions.
  */
 
 static int
-yaml_parser_resize_list(yaml_parser_t *parser, void **buffer, size_t *size,
-        size_t item_size);
+yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event);
 
 static int
-yaml_parser_append_tag_directive(yaml_parser_t *parser,
-        yaml_tag_directive_t *tag_directive);
+yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event);
 
 static int
-yaml_parser_append_state(yaml_parser_t *parser, yaml_parser_state_t state);
+yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event,
+        int implicit);
 
 static int
-yaml_parser_append_mark(yaml_parser_t *parser, yaml_mark_t mark);
+yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event);
 
-/*
- * State functions.
- */
+static int
+yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event);
 
-static yaml_event_t *
-yaml_parser_state_machine(yaml_parser_t *parser);
-
-static yaml_event_t *
-yaml_parser_parse_stream_start(yaml_parser_t *parser);
-
-static yaml_event_t *
-yaml_parser_parse_document_start(yaml_parser_t *parser, int implicit);
-
-static yaml_event_t *
-yaml_parser_parse_document_content(yaml_parser_t *parser);
-
-static yaml_event_t *
-yaml_parser_parse_document_end(yaml_parser_t *parser);
-
-static yaml_event_t *
-yaml_parser_parse_node(yaml_parser_t *parser,
+static int
+yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event,
         int block, int indentless_sequence);
 
-static yaml_event_t *
-yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser, int first);
+static int
+yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser,
+        yaml_event_t *event, int first);
 
-static yaml_event_t *
-yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser);
+static int
+yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser,
+        yaml_event_t *event);
 
-static yaml_event_t *
-yaml_parser_parse_block_mapping_key(yaml_parser_t *parser, int first);
+static int
+yaml_parser_parse_block_mapping_key(yaml_parser_t *parser,
+        yaml_event_t *event, int first);
 
-static yaml_event_t *
-yaml_parser_parse_block_mapping_value(yaml_parser_t *parser);
+static int
+yaml_parser_parse_block_mapping_value(yaml_parser_t *parser,
+        yaml_event_t *event);
 
-static yaml_event_t *
-yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser, int first);
+static int
+yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser,
+        yaml_event_t *event, int first);
 
-static yaml_event_t *
-yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser);
+static int
+yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser,
+        yaml_event_t *event);
 
-static yaml_event_t *
-yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser);
+static int
+yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser,
+        yaml_event_t *event);
 
-static yaml_event_t *
-yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser);
+static int
+yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser,
+        yaml_event_t *event);
 
-static yaml_event_t *
-yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser, int first);
+static int
+yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser,
+        yaml_event_t *event, int first);
 
-static yaml_event_t *
-yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser, int empty);
+static int
+yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser,
+        yaml_event_t *event, int empty);
 
 /*
  * Utility functions.
  */
 
-static yaml_event_t *
-yaml_parser_process_empty_scalar(yaml_parser_t *parser, yaml_mark_t mark);
+static int
+yaml_parser_process_empty_scalar(yaml_parser_t *parser,
+        yaml_event_t *event, yaml_mark_t mark);
 
 static int
-yaml_parser_process_directives(yaml_parser_t *parser);
+yaml_parser_process_directives(yaml_parser_t *parser,
+        yaml_version_directive_t **version_directive_ref,
+        yaml_tag_directive_t **tag_directives_start_ref,
+        yaml_tag_directive_t **tag_directives_end_ref);
+
+static int
+yaml_parser_append_tag_directive(yaml_parser_t *parser,
+        yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark);
 
 /*
- * Get the next event and advance the parser.
+ * Get the next event.
  */
 
-YAML_DECLARE(yaml_event_t *)
-yaml_parser_get_event(yaml_parser_t *parser)
+YAML_DECLARE(int)
+yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event)
 {
-    yaml_event_t *value;
+    assert(parser);     /* Non-NULL parser object is expected. */
+    assert(event);      /* Non-NULL event object is expected. */
 
-    /* Update the current event if needed. */
-    
-    if (!parser->current_event) {
-        parser->current_event = yaml_parser_state_machine(parser);
+    /* No events after the end of the stream or error. */
+
+    if (parser->stream_end_produced || parser->error ||
+            parser->state == YAML_PARSE_END_STATE) {
+        memset(event, 0, sizeof(yaml_event_t));
+
+        return 1;
     }
 
-    /* Return and clear the current event. */
+    /* Generate the next event. */
 
-    value = parser->current_event;
-    parser->current_event = NULL;
-    return value;
-}
-
-/*
- * Peek the next event.
- */
-
-YAML_DECLARE(yaml_event_t *)
-yaml_parser_peek_event(yaml_parser_t *parser)
-{
-    yaml_event_t *value;
-
-    /* Update the current event if needed. */
-    
-    if (!parser->current_event) {
-        parser->current_event = yaml_parser_state_machine(parser);
-    }
-
-    /* Return the current event. */
-
-    return parser->current_event;
+    return yaml_parser_state_machine(parser, event);
 }
 
 /*
     return 0;
 }
 
-/*
- * Double a list.
- */
-
-static int
-yaml_parser_resize_list(yaml_parser_t *parser, void **buffer, size_t *size,
-        size_t item_size)
-{
-    void *new_buffer = yaml_realloc(*buffer, item_size*(*size)*2);
-
-    if (!new_buffer) {
-        parser->error = YAML_MEMORY_ERROR;
-        return 0;
-    }
-
-    memset(new_buffer+item_size*(*size), 0, item_size*(*size));
-
-    *buffer = new_buffer;
-    *size *= 2;
-
-    return 1;
-}
-
-/*
- * Push a tag directive to the directive list.
- */
-
-static int
-yaml_parser_append_tag_directive(yaml_parser_t *parser,
-        yaml_tag_directive_t *tag_directive)
-{
-    if (parser->tag_directives_length == parser->tag_directives_size-1) {
-        if (!yaml_parser_resize_list(parser, (void **)&parser->tag_directives,
-                    &parser->tag_directives_size, sizeof(yaml_tag_directive_t)))
-            return 0;
-    }
-
-    parser->tag_directives[parser->tag_directives_length++] = tag_directive;
-    parser->tag_directives[parser->tag_directives_length] = NULL;
-    return 1;
-}
-
-/*
- * Push a state to the state stack.
- */
-
-static int
-yaml_parser_append_state(yaml_parser_t *parser, yaml_parser_state_t state)
-{
-    if (parser->states_length == parser->states_size-1) {
-        if (!yaml_parser_resize_list(parser, (void **)&parser->states,
-                    &parser->states_size, sizeof(yaml_parser_state_t)))
-            return 0;
-    }
-
-    parser->states[parser->states_length++] = state;
-    return 1;
-}
-
-/*
- * Push a mark to the mark stack.
- */
-
-static int
-yaml_parser_append_mark(yaml_parser_t *parser, yaml_mark_t mark)
-{
-    if (parser->marks_length == parser->marks_size-1) {
-        if (!yaml_parser_resize_list(parser, (void **)&parser->marks,
-                    &parser->marks_size, sizeof(yaml_mark_t)))
-            return 0;
-    }
-
-    parser->marks[parser->marks_length++] = mark;
-    return 1;
-}
 
 /*
  * State dispatcher.
  */
 
-static yaml_event_t *
-yaml_parser_state_machine(yaml_parser_t *parser)
+static int
+yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event)
 {
-    assert (parser->state != YAML_PARSE_END_STATE);
-
     switch (parser->state)
     {
         case YAML_PARSE_STREAM_START_STATE:
-            return yaml_parser_parse_stream_start(parser);
+            return yaml_parser_parse_stream_start(parser, event);
 
         case YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE:
-            return yaml_parser_parse_document_start(parser, 1);
+            return yaml_parser_parse_document_start(parser, event, 1);
 
         case YAML_PARSE_DOCUMENT_START_STATE:
-            return yaml_parser_parse_document_start(parser, 0);
+            return yaml_parser_parse_document_start(parser, event, 0);
 
         case YAML_PARSE_DOCUMENT_CONTENT_STATE:
-            return yaml_parser_parse_document_content(parser);
+            return yaml_parser_parse_document_content(parser, event);
 
         case YAML_PARSE_DOCUMENT_END_STATE:
-            return yaml_parser_parse_document_end(parser);
+            return yaml_parser_parse_document_end(parser, event);
 
         case YAML_PARSE_BLOCK_NODE_STATE:
-            return yaml_parser_parse_node(parser, 1, 0);
+            return yaml_parser_parse_node(parser, event, 1, 0);
 
         case YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
-            return yaml_parser_parse_node(parser, 1, 1);
+            return yaml_parser_parse_node(parser, event, 1, 1);
 
         case YAML_PARSE_FLOW_NODE_STATE:
-            return yaml_parser_parse_node(parser, 0, 0);
+            return yaml_parser_parse_node(parser, event, 0, 0);
 
         case YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
-            return yaml_parser_parse_block_sequence_entry(parser, 1);
+            return yaml_parser_parse_block_sequence_entry(parser, event, 1);
 
         case YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
-            return yaml_parser_parse_block_sequence_entry(parser, 0);
+            return yaml_parser_parse_block_sequence_entry(parser, event, 0);
 
         case YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
-            return yaml_parser_parse_indentless_sequence_entry(parser);
+            return yaml_parser_parse_indentless_sequence_entry(parser, event);
 
         case YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
-            return yaml_parser_parse_block_mapping_key(parser, 1);
+            return yaml_parser_parse_block_mapping_key(parser, event, 1);
 
         case YAML_PARSE_BLOCK_MAPPING_KEY_STATE:
-            return yaml_parser_parse_block_mapping_key(parser, 0);
+            return yaml_parser_parse_block_mapping_key(parser, event, 0);
 
         case YAML_PARSE_BLOCK_MAPPING_VALUE_STATE:
-            return yaml_parser_parse_block_mapping_value(parser);
+            return yaml_parser_parse_block_mapping_value(parser, event);
 
         case YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
-            return yaml_parser_parse_flow_sequence_entry(parser, 1);
+            return yaml_parser_parse_flow_sequence_entry(parser, event, 1);
 
         case YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
-            return yaml_parser_parse_flow_sequence_entry(parser, 0);
+            return yaml_parser_parse_flow_sequence_entry(parser, event, 0);
 
         case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
-            return yaml_parser_parse_flow_sequence_entry_mapping_key(parser);
+            return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event);
 
         case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
-            return yaml_parser_parse_flow_sequence_entry_mapping_value(parser);
+            return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event);
 
         case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
-            return yaml_parser_parse_flow_sequence_entry_mapping_end(parser);
+            return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event);
 
         case YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
-            return yaml_parser_parse_flow_mapping_key(parser, 1);
+            return yaml_parser_parse_flow_mapping_key(parser, event, 1);
 
         case YAML_PARSE_FLOW_MAPPING_KEY_STATE:
-            return yaml_parser_parse_flow_mapping_key(parser, 0);
+            return yaml_parser_parse_flow_mapping_key(parser, event, 0);
 
         case YAML_PARSE_FLOW_MAPPING_VALUE_STATE:
-            return yaml_parser_parse_flow_mapping_value(parser, 0);
+            return yaml_parser_parse_flow_mapping_value(parser, event, 0);
 
         case YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
-            return yaml_parser_parse_flow_mapping_value(parser, 1);
+            return yaml_parser_parse_flow_mapping_value(parser, event, 1);
+
+        default:
+            assert(1);      /* Invalid state. */
     }
-    assert(1);