Commits

Kirill Simonov committed a8eb95b

Start working on the parser.

Comments (0)

Files changed (4)

 } 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_DOCUMENT_CONTENT_STATE,
+    YAML_PARSE_DOCUMENT_END_STATE,
+    YAML_PARSE_BLOCK_NODE_STATE,
+    YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE,
+    YAML_PARSE_FLOW_NODE_STATE,
+    YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE,
+    YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE,
+    YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE,
+    YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE,
+    YAML_PARSE_BLOCK_MAPPING_KEY_STATE,
+    YAML_PARSE_BLOCK_MAPPING_VALUE_STATE,
+    YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE,
+    YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE,
+    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE,
+    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE,
+    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_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_parser_state_t;
+
+/**
  * The parser structure.
  *
  * All members are internal.  Manage the structure using the @c yaml_parser_
      * @}
      */
 
+    /**
+     * @name Parser stuff
+     * @{
+     */
+
+    /** 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;
+
+    /** 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;
+
+    /** 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;
+
+    /**
+     * @}
+     */
+
 } yaml_parser_t;
 
 /**
 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);
+
 /** @} */
 
 /*
 AM_CPPFLAGS = -I$(top_srcdir)/include
 lib_LTLIBRARIES = libyaml.la
-libyaml_la_SOURCES = api.c reader.c scanner.c
+libyaml_la_SOURCES = api.c reader.c scanner.c parser.c
 libyaml_la_LDFLAGS = -release $(YAML_LT_RELEASE) -version-info $(YAML_LT_CURRENT):$(YAML_LT_REVISION):$(YAML_LT_AGE)
 
     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 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;
 
     if (!parser) return NULL;
 
+    yaml_free(parser->tag_directives);
+    yaml_free(parser->states);
     yaml_free(parser->simple_keys);
     yaml_free(parser->indents);
     yaml_free(parser->tokens);
 {
     assert(parser); /* Non-NULL parser object expected. */
 
+    yaml_free(parser->tag_directives);
+    yaml_free(parser->states);
     yaml_free(parser->simple_keys);
     yaml_free(parser->indents);
     yaml_free(parser->tokens);
+
+/*
+ * The parser implements the following grammar:
+ *
+ * stream               ::= STREAM-START implicit_document? explicit_document* STREAM-END
+ * implicit_document    ::= block_node DOCUMENT-END*
+ * explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+ * block_node_or_indentless_sequence    ::=
+ *                          ALIAS
+ *                          | properties (block_content | indentless_block_sequence)?
+ *                          | block_content
+ *                          | indentless_block_sequence
+ * block_node           ::= ALIAS
+ *                          | properties block_content?
+ *                          | block_content
+ * flow_node            ::= ALIAS
+ *                          | properties flow_content?
+ *                          | flow_content
+ * properties           ::= TAG ANCHOR? | ANCHOR TAG?
+ * block_content        ::= block_collection | flow_collection | SCALAR
+ * flow_content         ::= flow_collection | SCALAR
+ * block_collection     ::= block_sequence | block_mapping
+ * flow_collection      ::= flow_sequence | flow_mapping
+ * block_sequence       ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+ * indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
+ * block_mapping        ::= BLOCK-MAPPING_START
+ *                          ((KEY block_node_or_indentless_sequence?)?
+ *                          (VALUE block_node_or_indentless_sequence?)?)*
+ *                          BLOCK-END
+ * flow_sequence        ::= FLOW-SEQUENCE-START
+ *                          (flow_sequence_entry FLOW-ENTRY)*
+ *                          flow_sequence_entry?
+ *                          FLOW-SEQUENCE-END
+ * flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ * flow_mapping         ::= FLOW-MAPPING-START
+ *                          (flow_mapping_entry FLOW-ENTRY)*
+ *                          flow_mapping_entry?
+ *                          FLOW-MAPPING-END
+ * flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <yaml.h>
+
+#include <assert.h>
+
+/*
+ * 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);
+
+/*
+ * State functions.
+ */
+
+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,
+        int block, int indentless_sequence);
+
+static yaml_event_t *
+yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser, int first);
+
+static yaml_event_t *
+yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser);
+
+static yaml_event_t *
+yaml_parser_parse_block_mapping_key(yaml_parser_t *parser, int first);
+
+static yaml_event_t *
+yaml_parser_parse_block_mapping_value(yaml_parser_t *parser);
+
+static yaml_event_t *
+yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser, int first);
+
+static yaml_event_t *
+yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser);
+
+static yaml_event_t *
+yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser);
+
+static yaml_event_t *
+yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser);
+
+static yaml_event_t *
+yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser, int first);
+
+static yaml_event_t *
+yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser, int empty);
+
+/*
+ * Get the next event and advance the parser.
+ */
+
+YAML_DECLARE(yaml_event_t *)
+yaml_parser_get_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 and clear the current 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;
+}
+
+/*
+ * State dispatcher.
+ */
+
+static yaml_event_t *
+yaml_parser_state_machine(yaml_parser_t *parser)
+{
+    assert (parser->state != YAML_PARSE_END_STATE);
+
+    switch (parser->state)
+    {
+        case YAML_PARSE_STREAM_START_STATE:
+            return yaml_parser_parse_stream_start(parser);
+
+        case YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+            return yaml_parser_parse_document_start(parser, 1);
+
+        case YAML_PARSE_DOCUMENT_START_STATE:
+            return yaml_parser_parse_document_start(parser, 0);
+
+        case YAML_PARSE_DOCUMENT_CONTENT_STATE:
+            return yaml_parser_parse_document_content(parser);
+
+        case YAML_PARSE_DOCUMENT_END_STATE:
+            return yaml_parser_parse_document_end(parser);
+
+        case YAML_PARSE_BLOCK_NODE_STATE:
+            return yaml_parser_parse_node(parser, 1, 0);
+
+        case YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+            return yaml_parser_parse_node(parser, 1, 1);
+
+        case YAML_PARSE_FLOW_NODE_STATE:
+            return yaml_parser_parse_node(parser, 0, 0);
+
+        case YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+            return yaml_parser_parse_block_sequence_entry(parser, 1);
+
+        case YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+            return yaml_parser_parse_block_sequence_entry(parser, 0);
+
+        case YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+            return yaml_parser_parse_indentless_sequence_entry(parser);
+
+        case YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+            return yaml_parser_parse_block_mapping_key(parser, 1);
+
+        case YAML_PARSE_BLOCK_MAPPING_KEY_STATE:
+            return yaml_parser_parse_block_mapping_key(parser, 0);
+
+        case YAML_PARSE_BLOCK_MAPPING_VALUE_STATE:
+            return yaml_parser_parse_block_mapping_value(parser);
+
+        case YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+            return yaml_parser_parse_flow_sequence_entry(parser, 1);
+
+        case YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+            return yaml_parser_parse_flow_sequence_entry(parser, 0);
+
+        case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+            return yaml_parser_parse_flow_sequence_entry_mapping_key(parser);
+
+        case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+            return yaml_parser_parse_flow_sequence_entry_mapping_value(parser);
+
+        case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+            return yaml_parser_parse_flow_sequence_entry_mapping_end(parser);
+
+        case YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+            return yaml_parser_parse_flow_mapping_key(parser, 1);
+
+        case YAML_PARSE_FLOW_MAPPING_KEY_STATE:
+            return yaml_parser_parse_flow_mapping_key(parser, 0);
+
+        case YAML_PARSE_FLOW_MAPPING_VALUE_STATE:
+            return yaml_parser_parse_flow_mapping_value(parser, 0);
+
+        case YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+            return yaml_parser_parse_flow_mapping_value(parser, 1);
+    }
+    assert(1);
+}
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.