source: libyaml/trunk/src/loader.c @ 263

Revision 263, 11.1 KB checked in by xi, 7 years ago (diff)

Completed the first phase of API refactoring.

Line 
1
2#include "yaml_private.h"
3
4#if 0
5
6/*
7 * API functions.
8 */
9
10YAML_DECLARE(int)
11yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
12
13/*
14 * Error handling.
15 */
16
17static int
18yaml_parser_set_composer_error(yaml_parser_t *parser,
19        const char *problem, yaml_mark_t problem_mark);
20
21static int
22yaml_parser_set_composer_error_context(yaml_parser_t *parser,
23        const char *context, yaml_mark_t context_mark,
24        const char *problem, yaml_mark_t problem_mark);
25
26
27/*
28 * Alias handling.
29 */
30
31static int
32yaml_parser_register_anchor(yaml_parser_t *parser,
33        int index, yaml_char_t *anchor);
34
35/*
36 * Clean up functions.
37 */
38
39static void
40yaml_parser_delete_aliases(yaml_parser_t *parser);
41
42/*
43 * Composer functions.
44 */
45
46static int
47yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event);
48
49static int
50yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event);
51
52static int
53yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event);
54
55static int
56yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event);
57
58static int
59yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event);
60
61static int
62yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event);
63
64/*
65 * Load the next document of the stream.
66 */
67
68YAML_DECLARE(int)
69yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document)
70{
71    yaml_event_t event;
72
73    assert(parser);     /* Non-NULL parser object is expected. */
74    assert(document);   /* Non-NULL document object is expected. */
75
76    memset(document, 0, sizeof(yaml_document_t));
77    if (!STACK_INIT(parser, document->nodes, INITIAL_STACK_SIZE))
78        goto error;
79
80    if (!parser->stream_start_produced) {
81        if (!yaml_parser_parse(parser, &event)) goto error;
82        assert(event.type == YAML_STREAM_START_EVENT);
83                        /* STREAM-START is expected. */
84    }
85
86    if (parser->stream_end_produced) {
87        return 1;
88    }
89
90    if (!yaml_parser_parse(parser, &event)) goto error;
91    if (event.type == YAML_STREAM_END_EVENT) {
92        return 1;
93    }
94
95    if (!STACK_INIT(parser, parser->aliases, INITIAL_STACK_SIZE))
96        goto error;
97
98    parser->document = document;
99
100    if (!yaml_parser_load_document(parser, &event)) goto error;
101
102    yaml_parser_delete_aliases(parser);
103    parser->document = NULL;
104
105    return 1;
106
107error:
108
109    yaml_parser_delete_aliases(parser);
110    yaml_document_delete(document);
111    parser->document = NULL;
112
113    return 0;
114}
115
116/*
117 * Set composer error.
118 */
119
120static int
121yaml_parser_set_composer_error(yaml_parser_t *parser,
122        const char *problem, yaml_mark_t problem_mark)
123{
124    parser->error = YAML_COMPOSER_ERROR;
125    parser->problem = problem;
126    parser->problem_mark = problem_mark;
127
128    return 0;
129}
130
131/*
132 * Set composer error with context.
133 */
134
135static int
136yaml_parser_set_composer_error_context(yaml_parser_t *parser,
137        const char *context, yaml_mark_t context_mark,
138        const char *problem, yaml_mark_t problem_mark)
139{
140    parser->error = YAML_COMPOSER_ERROR;
141    parser->context = context;
142    parser->context_mark = context_mark;
143    parser->problem = problem;
144    parser->problem_mark = problem_mark;
145
146    return 0;
147}
148
149/*
150 * Delete the stack of aliases.
151 */
152
153static void
154yaml_parser_delete_aliases(yaml_parser_t *parser)
155{
156    while (!STACK_EMPTY(parser, parser->aliases)) {
157        yaml_free(POP(parser, parser->aliases).anchor);
158    }
159    STACK_DEL(parser, parser->aliases);
160}
161
162/*
163 * Compose a document object.
164 */
165
166static int
167yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event)
168{
169    yaml_event_t event;
170
171    assert(first_event->type == YAML_DOCUMENT_START_EVENT);
172                        /* DOCUMENT-START is expected. */
173
174    parser->document->version_directive
175        = first_event->data.document_start.version_directive;
176    parser->document->tag_directives.start
177        = first_event->data.document_start.tag_directives.start;
178    parser->document->tag_directives.end
179        = first_event->data.document_start.tag_directives.end;
180    parser->document->start_implicit
181        = first_event->data.document_start.implicit;
182    parser->document->start_mark = first_event->start_mark;
183
184    if (!yaml_parser_parse(parser, &event)) return 0;
185
186    if (!yaml_parser_load_node(parser, &event)) return 0;
187
188    if (!yaml_parser_parse(parser, &event)) return 0;
189    assert(event.type == YAML_DOCUMENT_END_EVENT);
190                        /* DOCUMENT-END is expected. */
191
192    parser->document->end_implicit = event.data.document_end.implicit;
193    parser->document->end_mark = event.end_mark;
194
195    return 1;
196}
197
198/*
199 * Compose a node.
200 */
201
202static int
203yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event)
204{
205    switch (first_event->type) {
206        case YAML_ALIAS_EVENT:
207            return yaml_parser_load_alias(parser, first_event);
208        case YAML_SCALAR_EVENT:
209            return yaml_parser_load_scalar(parser, first_event);
210        case YAML_SEQUENCE_START_EVENT:
211            return yaml_parser_load_sequence(parser, first_event);
212        case YAML_MAPPING_START_EVENT:
213            return yaml_parser_load_mapping(parser, first_event);
214        default:
215            assert(0);  /* Could not happen. */
216            return 0;
217    }
218
219    return 0;
220}
221
222/*
223 * Add an anchor.
224 */
225
226static int
227yaml_parser_register_anchor(yaml_parser_t *parser,
228        int index, yaml_char_t *anchor)
229{
230    yaml_alias_data_t data = { anchor, index, { 0, 0, 0 } };
231    yaml_alias_data_t *alias_data;
232
233    if (!anchor) return 1;
234
235    data.mark = parser->document->nodes.start[index-1].start_mark;
236
237    for (alias_data = parser->aliases.start;
238            alias_data != parser->aliases.top; alias_data ++) {
239        if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
240            yaml_free(anchor);
241            return yaml_parser_set_composer_error_context(parser,
242                    "found duplicate anchor; first occurence",
243                    alias_data->mark, "second occurence", data.mark);
244        }
245    }
246
247    if (!PUSH(parser, parser->aliases, data)) {
248        yaml_free(anchor);
249        return 0;
250    }
251
252    return 1;
253}
254
255/*
256 * Compose a node corresponding to an alias.
257 */
258
259static int
260yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event)
261{
262    yaml_char_t *anchor = first_event->data.alias.anchor;
263    yaml_alias_data_t *alias_data;
264
265    for (alias_data = parser->aliases.start;
266            alias_data != parser->aliases.top; alias_data ++) {
267        if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
268            yaml_free(anchor);
269            return alias_data->index;
270        }
271    }
272
273    yaml_free(anchor);
274    return yaml_parser_set_composer_error(parser, "found undefined alias",
275            first_event->start_mark);
276}
277
278/*
279 * Compose a scalar node.
280 */
281
282static int
283yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
284{
285    yaml_node_t node;
286    int index;
287    yaml_char_t *tag = first_event->data.scalar.tag;
288
289    if (!tag || strcmp((char *)tag, "!") == 0) {
290        yaml_free(tag);
291        tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
292        if (!tag) goto error;
293    }
294
295    SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
296            first_event->data.scalar.length, first_event->data.scalar.style,
297            first_event->start_mark, first_event->end_mark);
298
299    if (!PUSH(parser, parser->document->nodes, node)) goto error;
300
301    index = parser->document->nodes.top - parser->document->nodes.start;
302
303    if (!yaml_parser_register_anchor(parser, index,
304                first_event->data.scalar.anchor)) return 0;
305
306    return index;
307
308error:
309    yaml_free(tag);
310    yaml_free(first_event->data.scalar.anchor);
311    yaml_free(first_event->data.scalar.value);
312    return 0;
313}
314
315/*
316 * Compose a sequence node.
317 */
318
319static int
320yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
321{
322    yaml_event_t event;
323    yaml_node_t node;
324    struct {
325        yaml_node_item_t *start;
326        yaml_node_item_t *end;
327        yaml_node_item_t *top;
328    } items = { NULL, NULL, NULL };
329    int index, item_index;
330    yaml_char_t *tag = first_event->data.sequence_start.tag;
331
332    if (!tag || strcmp((char *)tag, "!") == 0) {
333        yaml_free(tag);
334        tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
335        if (!tag) goto error;
336    }
337
338    if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error;
339
340    SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
341            first_event->data.sequence_start.style,
342            first_event->start_mark, first_event->end_mark);
343
344    if (!PUSH(parser, parser->document->nodes, node)) goto error;
345
346    index = parser->document->nodes.top - parser->document->nodes.start;
347
348    if (!yaml_parser_register_anchor(parser, index,
349                first_event->data.sequence_start.anchor)) return 0;
350
351    if (!yaml_parser_parse(parser, &event)) return 0;
352
353    while (event.type != YAML_SEQUENCE_END_EVENT) {
354        item_index = yaml_parser_load_node(parser, &event);
355        if (!item_index) return 0;
356        if (!PUSH(parser,
357                    parser->document->nodes.start[index-1].data.sequence.items,
358                    item_index)) return 0;
359        if (!yaml_parser_parse(parser, &event)) return 0;
360    }
361
362    parser->document->nodes.start[index-1].end_mark = event.end_mark;
363
364    return index;
365
366error:
367    yaml_free(tag);
368    yaml_free(first_event->data.sequence_start.anchor);
369    return 0;
370}
371
372/*
373 * Compose a mapping node.
374 */
375
376static int
377yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
378{
379    yaml_event_t event;
380    yaml_node_t node;
381    struct {
382        yaml_node_pair_t *start;
383        yaml_node_pair_t *end;
384        yaml_node_pair_t *top;
385    } pairs = { NULL, NULL, NULL };
386    int index;
387    yaml_node_pair_t pair;
388    yaml_char_t *tag = first_event->data.mapping_start.tag;
389
390    if (!tag || strcmp((char *)tag, "!") == 0) {
391        yaml_free(tag);
392        tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
393        if (!tag) goto error;
394    }
395
396    if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error;
397
398    MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
399            first_event->data.mapping_start.style,
400            first_event->start_mark, first_event->end_mark);
401
402    if (!PUSH(parser, parser->document->nodes, node)) goto error;
403
404    index = parser->document->nodes.top - parser->document->nodes.start;
405
406    if (!yaml_parser_register_anchor(parser, index,
407                first_event->data.mapping_start.anchor)) return 0;
408
409    if (!yaml_parser_parse(parser, &event)) return 0;
410
411    while (event.type != YAML_MAPPING_END_EVENT) {
412        pair.key = yaml_parser_load_node(parser, &event);
413        if (!pair.key) return 0;
414        if (!yaml_parser_parse(parser, &event)) return 0;
415        pair.value = yaml_parser_load_node(parser, &event);
416        if (!pair.value) return 0;
417        if (!PUSH(parser,
418                    parser->document->nodes.start[index-1].data.mapping.pairs,
419                    pair)) return 0;
420        if (!yaml_parser_parse(parser, &event)) return 0;
421    }
422
423    parser->document->nodes.start[index-1].end_mark = event.end_mark;
424
425    return index;
426
427error:
428    yaml_free(tag);
429    yaml_free(first_event->data.mapping_start.anchor);
430    return 0;
431}
432
433#endif
434
Note: See TracBrowser for help on using the repository browser.