Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/lyaml/ext/yaml/parser.c
178615 views
1
/*
2
* parser.c, libyaml parser binding for Lua
3
* Written by Gary V. Vaughan, 2013
4
*
5
* Copyright (C) 2013-2022 Gary V. Vaughan
6
*
7
* Permission is hereby granted, free of charge, to any person obtaining a copy
8
* of this software and associated documentation files (the "Software"), to deal
9
* in the Software without restriction, including without limitation the rights
10
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
* copies of the Software, and to permit persons to whom the Software is
12
* furnished to do so, subject to the following conditions:
13
*
14
* The above copyright notice and this permission notice shall be included in
15
* all copies or substantial portions of the Software.
16
*
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
* THE SOFTWARE.
24
*/
25
26
#include "lyaml.h"
27
28
typedef struct {
29
lua_State *L;
30
yaml_parser_t parser;
31
yaml_event_t event;
32
char validevent;
33
int document_count;
34
} lyaml_parser;
35
36
37
static void
38
parser_delete_event (lyaml_parser *parser)
39
{
40
if (parser->validevent)
41
{
42
yaml_event_delete (&parser->event);
43
parser->validevent = 0;
44
}
45
}
46
47
/* With the event result table on the top of the stack, insert
48
a mark entry. */
49
static void
50
parser_set_mark (lua_State *L, const char *k, yaml_mark_t mark)
51
{
52
lua_pushstring (L, k);
53
lua_createtable (L, 0, 3);
54
#define MENTRY(_s) RAWSET_INTEGER(#_s, mark._s)
55
MENTRY( index );
56
MENTRY( line );
57
MENTRY( column );
58
#undef MENTRY
59
lua_rawset (L, -3);
60
}
61
62
/* Push a new event table, pre-populated with shared elements. */
63
static void
64
parser_push_eventtable (lyaml_parser *parser, const char *v, int n)
65
{
66
lua_State *L = parser->L;
67
68
lua_createtable (L, 0, n + 3);
69
RAWSET_STRING ("type", v);
70
#define MENTRY(_s) parser_set_mark (L, #_s, parser->event._s)
71
MENTRY( start_mark );
72
MENTRY( end_mark );
73
#undef MENTRY
74
}
75
76
static void
77
parse_STREAM_START (lyaml_parser *parser)
78
{
79
#define EVENTF(_f) (parser->event.data.stream_start._f)
80
lua_State *L = parser->L;
81
const char *encoding;
82
83
switch (EVENTF (encoding))
84
{
85
#define MENTRY(_s) \
86
case YAML_##_s##_ENCODING: encoding = #_s; break
87
88
MENTRY( ANY );
89
MENTRY( UTF8 );
90
MENTRY( UTF16LE );
91
MENTRY( UTF16BE );
92
#undef MENTRY
93
94
default:
95
lua_pushfstring (L, "invalid encoding %d", EVENTF (encoding));
96
lua_error (L);
97
}
98
99
parser_push_eventtable (parser, "STREAM_START", 1);
100
RAWSET_STRING ("encoding", encoding);
101
#undef EVENTF
102
}
103
104
/* With the tag list on the top of the stack, append TAG. */
105
static void
106
parser_append_tag (lua_State *L, yaml_tag_directive_t tag)
107
{
108
lua_createtable (L, 0, 2);
109
#define MENTRY(_s) RAWSET_STRING(#_s, tag._s)
110
MENTRY( handle );
111
MENTRY( prefix );
112
#undef MENTRY
113
lua_rawseti (L, -2, lua_objlen (L, -2) + 1);
114
}
115
116
static void
117
parse_DOCUMENT_START (lyaml_parser *parser)
118
{
119
#define EVENTF(_f) (parser->event.data.document_start._f)
120
lua_State *L = parser->L;
121
122
/* increment document count */
123
parser->document_count++;
124
125
parser_push_eventtable (parser, "DOCUMENT_START", 1);
126
RAWSET_BOOLEAN ("implicit", EVENTF (implicit));
127
128
/* version_directive = { major = M, minor = N } */
129
if (EVENTF (version_directive))
130
{
131
lua_pushliteral (L, "version_directive");
132
lua_createtable (L, 0, 2);
133
#define MENTRY(_s) RAWSET_INTEGER(#_s, EVENTF (version_directive->_s))
134
MENTRY( major );
135
MENTRY( minor );
136
#undef MENTRY
137
lua_rawset (L, -3);
138
}
139
140
/* tag_directives = { {handle = H1, prefix = P1}, ... } */
141
if (EVENTF (tag_directives.start) &&
142
EVENTF (tag_directives.end)) {
143
yaml_tag_directive_t *cur;
144
145
lua_pushliteral (L, "tag_directives");
146
lua_newtable (L);
147
for (cur = EVENTF (tag_directives.start);
148
cur != EVENTF (tag_directives.end);
149
cur = cur + 1)
150
{
151
parser_append_tag (L, *cur);
152
}
153
lua_rawset (L, -3);
154
}
155
#undef EVENTF
156
}
157
158
static void
159
parse_DOCUMENT_END (lyaml_parser *parser)
160
{
161
#define EVENTF(_f) (parser->event.data.document_end._f)
162
lua_State *L = parser->L;
163
164
parser_push_eventtable (parser, "DOCUMENT_END", 1);
165
RAWSET_BOOLEAN ("implicit", EVENTF (implicit));
166
#undef EVENTF
167
}
168
169
static void
170
parse_ALIAS (lyaml_parser *parser)
171
{
172
#define EVENTF(_f) (parser->event.data.alias._f)
173
lua_State *L = parser->L;
174
175
parser_push_eventtable (parser, "ALIAS", 1);
176
RAWSET_EVENTF (anchor);
177
#undef EVENTF
178
}
179
180
static void
181
parse_SCALAR (lyaml_parser *parser)
182
{
183
#define EVENTF(_f) (parser->event.data.scalar._f)
184
lua_State *L = parser->L;
185
const char *style;
186
187
switch (EVENTF (style))
188
{
189
#define MENTRY(_s) \
190
case YAML_##_s##_SCALAR_STYLE: style = #_s; break
191
192
MENTRY( ANY );
193
MENTRY( PLAIN );
194
MENTRY( SINGLE_QUOTED );
195
MENTRY( DOUBLE_QUOTED );
196
MENTRY( LITERAL );
197
MENTRY( FOLDED );
198
#undef MENTRY
199
200
default:
201
lua_pushfstring (L, "invalid sequence style %d", EVENTF (style));
202
lua_error (L);
203
}
204
205
206
parser_push_eventtable (parser, "SCALAR", 6);
207
RAWSET_EVENTF (anchor);
208
RAWSET_EVENTF (tag);
209
RAWSET_EVENTF (value);
210
211
RAWSET_BOOLEAN ("plain_implicit", EVENTF (plain_implicit));
212
RAWSET_BOOLEAN ("quoted_implicit", EVENTF (quoted_implicit));
213
RAWSET_STRING ("style", style);
214
#undef EVENTF
215
}
216
217
static void
218
parse_SEQUENCE_START (lyaml_parser *parser)
219
{
220
#define EVENTF(_f) (parser->event.data.sequence_start._f)
221
lua_State *L = parser->L;
222
const char *style;
223
224
switch (EVENTF (style))
225
{
226
#define MENTRY(_s) \
227
case YAML_##_s##_SEQUENCE_STYLE: style = #_s; break
228
229
MENTRY( ANY );
230
MENTRY( BLOCK );
231
MENTRY( FLOW );
232
#undef MENTRY
233
234
default:
235
lua_pushfstring (L, "invalid sequence style %d", EVENTF (style));
236
lua_error (L);
237
}
238
239
parser_push_eventtable (parser, "SEQUENCE_START", 4);
240
RAWSET_EVENTF (anchor);
241
RAWSET_EVENTF (tag);
242
RAWSET_BOOLEAN ("implicit", EVENTF (implicit));
243
RAWSET_STRING ("style", style);
244
#undef EVENTF
245
}
246
247
static void
248
parse_MAPPING_START (lyaml_parser *parser)
249
{
250
#define EVENTF(_f) (parser->event.data.mapping_start._f)
251
lua_State *L = parser->L;
252
const char *style;
253
254
switch (EVENTF (style))
255
{
256
#define MENTRY(_s) \
257
case YAML_##_s##_MAPPING_STYLE: style = #_s; break
258
259
MENTRY( ANY );
260
MENTRY( BLOCK );
261
MENTRY( FLOW );
262
#undef MENTRY
263
264
default:
265
lua_pushfstring (L, "invalid mapping style %d", EVENTF (style));
266
lua_error (L);
267
}
268
269
parser_push_eventtable (parser, "MAPPING_START", 4);
270
RAWSET_EVENTF (anchor);
271
RAWSET_EVENTF (tag);
272
RAWSET_BOOLEAN ("implicit", EVENTF (implicit));
273
RAWSET_STRING ("style", style);
274
#undef EVENTF
275
}
276
277
static void
278
parser_generate_error_message (lyaml_parser *parser)
279
{
280
yaml_parser_t *P = &parser->parser;
281
char buf[256];
282
luaL_Buffer b;
283
284
luaL_buffinit (parser->L, &b);
285
luaL_addstring (&b, P->problem ? P->problem : "A problem");
286
snprintf (buf, sizeof (buf), " at document: %d", parser->document_count);
287
luaL_addstring (&b, buf);
288
289
if (P->problem_mark.line || P->problem_mark.column)
290
{
291
snprintf (buf, sizeof (buf), ", line: %lu, column: %lu",
292
(unsigned long) P->problem_mark.line + 1,
293
(unsigned long) P->problem_mark.column + 1);
294
luaL_addstring (&b, buf);
295
}
296
luaL_addstring (&b, "\n");
297
298
if (P->context)
299
{
300
snprintf (buf, sizeof (buf), "%s at line: %lu, column: %lu\n",
301
P->context,
302
(unsigned long) P->context_mark.line + 1,
303
(unsigned long) P->context_mark.column + 1);
304
luaL_addstring (&b, buf);
305
}
306
307
luaL_pushresult (&b);
308
}
309
310
static int
311
event_iter (lua_State *L)
312
{
313
lyaml_parser *parser = (lyaml_parser *)lua_touserdata(L, lua_upvalueindex(1));
314
char *str;
315
316
parser_delete_event (parser);
317
if (yaml_parser_parse (&parser->parser, &parser->event) != 1)
318
{
319
parser_generate_error_message (parser);
320
return lua_error (L);
321
}
322
323
parser->validevent = 1;
324
325
lua_newtable (L);
326
lua_pushliteral (L, "type");
327
328
switch (parser->event.type)
329
{
330
/* First the simple events, generated right here... */
331
#define MENTRY(_s) \
332
case YAML_##_s##_EVENT: parser_push_eventtable (parser, #_s, 0); break
333
MENTRY( STREAM_END );
334
MENTRY( SEQUENCE_END );
335
MENTRY( MAPPING_END );
336
#undef MENTRY
337
338
/* ...then the complex events, generated by a function call. */
339
#define MENTRY(_s) \
340
case YAML_##_s##_EVENT: parse_##_s (parser); break
341
MENTRY( STREAM_START );
342
MENTRY( DOCUMENT_START );
343
MENTRY( DOCUMENT_END );
344
MENTRY( ALIAS );
345
MENTRY( SCALAR );
346
MENTRY( SEQUENCE_START );
347
MENTRY( MAPPING_START );
348
#undef MENTRY
349
350
case YAML_NO_EVENT:
351
lua_pushnil (L);
352
break;
353
default:
354
lua_pushfstring (L, "invalid event %d", parser->event.type);
355
return lua_error (L);
356
}
357
358
return 1;
359
}
360
361
static int
362
parser_gc (lua_State *L)
363
{
364
lyaml_parser *parser = (lyaml_parser *) lua_touserdata (L, 1);
365
366
if (parser)
367
{
368
parser_delete_event (parser);
369
yaml_parser_delete (&parser->parser);
370
}
371
return 0;
372
}
373
374
void
375
parser_init (lua_State *L)
376
{
377
luaL_newmetatable(L, "lyaml.parser");
378
lua_pushcfunction(L, parser_gc);
379
lua_setfield(L, -2, "__gc");
380
}
381
382
int
383
Pparser (lua_State *L)
384
{
385
lyaml_parser *parser;
386
const unsigned char *str;
387
388
/* requires a single string type argument */
389
luaL_argcheck (L, lua_isstring (L, 1), 1, "must provide a string argument");
390
str = (const unsigned char *) lua_tostring (L, 1);
391
392
/* create a user datum to store the parser */
393
parser = (lyaml_parser *) lua_newuserdata (L, sizeof (*parser));
394
memset ((void *) parser, 0, sizeof (*parser));
395
parser->L = L;
396
397
/* set its metatable */
398
luaL_getmetatable (L, "lyaml.parser");
399
lua_setmetatable (L, -2);
400
401
/* try to initialize the parser */
402
if (yaml_parser_initialize (&parser->parser) == 0)
403
luaL_error (L, "cannot initialize parser for %s", str);
404
yaml_parser_set_input_string (&parser->parser, str, lua_strlen (L, 1));
405
406
/* create and return the iterator function, with the loader userdatum as
407
its sole upvalue */
408
lua_pushcclosure (L, event_iter, 1);
409
return 1;
410
}
411
412