diff options
Diffstat (limited to 'src/parser.c')
-rw-r--r-- | src/parser.c | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000..6928193 --- /dev/null +++ b/src/parser.c @@ -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); +} + |