]> andersk Git - libyaml.git/commitdiff
Start working on the parser.
authorKirill Simonov <xi@resolvent.net>
Tue, 4 Jul 2006 19:39:56 +0000 (19:39 +0000)
committerKirill Simonov <xi@resolvent.net>
Tue, 4 Jul 2006 19:39:56 +0000 (19:39 +0000)
include/yaml.h
src/Makefile.am
src/api.c
src/parser.c [new file with mode: 0644]

index 7ca4a9bb47b3dc79003ddc4d0e2cf375afc3f885..0a2bab07f1f8f1efa0a36e0ee4c6f0f75d37cf85 100644 (file)
@@ -789,6 +789,36 @@ typedef struct {
     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_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.
  *
@@ -939,6 +969,51 @@ typedef struct {
      * @}
      */
 
+    /**
+     * @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;
 
 /**
@@ -1044,6 +1119,34 @@ yaml_parser_get_token(yaml_parser_t *parser);
 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);
+
 /** @} */
 
 /*
index c8797dc09a83843130362cf34fc814f67de6647b..c7f6da2ab9cf94bac16c4b6f15a88ae15eda4329 100644 (file)
@@ -1,4 +1,4 @@
 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)
index 304775362bfb3d8c375a0d856340768252d614ac..51a1b31f9776eef65abd7c6c90d42635208ee08f 100644 (file)
--- a/src/api.c
+++ b/src/api.c
@@ -114,6 +114,26 @@ yaml_parser_new(void)
 
     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;
@@ -124,6 +144,8 @@ error:
 
     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);
@@ -144,6 +166,8 @@ yaml_parser_delete(yaml_parser_t *parser)
 {
     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);
diff --git a/src/parser.c b/src/parser.c
new file mode 100644 (file)
index 0000000..6928193
--- /dev/null
@@ -0,0 +1,237 @@
+
+/*
+ * 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);
+}
+
This page took 0.106433 seconds and 5 git commands to generate.