Skip to content
Snippets Groups Projects
Commit 2ef9fe0210b6 authored by Kirill Simonov's avatar Kirill Simonov
Browse files

Start working on the parser.

parent bdba0c5a26a4
No related branches found
No related tags found
No related merge requests found
......@@ -790,6 +790,36 @@
} 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_
......@@ -939,6 +969,51 @@
* @}
*/
/**
* @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_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)
......@@ -114,6 +114,26 @@
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 @@
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 @@
{
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);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment