1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-28 19:19:53 +00:00

Add parser/clone. (#120)

This commit is contained in:
Calvin Rose 2019-06-08 17:16:36 -04:00
parent 802a2d6b71
commit 43520ac67d
2 changed files with 72 additions and 2 deletions

View File

@ -634,6 +634,51 @@ void janet_parser_deinit(JanetParser *parser) {
free(parser->states); free(parser->states);
} }
void janet_parser_clone(JanetParser *src, JanetParser *dest) {
/* Misc fields */
dest->flag = src->flag;
dest->pending = src->pending;
dest->lookback = src->lookback;
dest->offset = src->offset;
dest->error = src->error;
/* Keep counts */
dest->argcount = src->argcount;
dest->bufcount = src->bufcount;
dest->statecount = src->statecount;
/* Capacities are equal to counts */
dest->bufcap = dest->bufcount;
dest->statecap = dest->statecount;
dest->argcap = dest->argcount;
/* Deep cloned fields */
dest->args = NULL;
dest->states = NULL;
dest->buf = NULL;
if (dest->bufcap) {
dest->buf = malloc(dest->bufcap);
if (!dest->buf) goto nomem;
}
if (dest->argcap) {
dest->args = malloc(sizeof(Janet) * dest->argcap);
if (!dest->args) goto nomem;
}
if (dest->statecap) {
dest->states = malloc(sizeof(JanetParseState) * dest->statecap);
if (!dest->states) goto nomem;
}
memcpy(dest->buf, src->buf, dest->bufcap);
memcpy(dest->args, src->args, dest->argcap * sizeof(Janet));
memcpy(dest->states, src->states, dest->statecap * sizeof(JanetParseState));
return;
nomem:
JANET_OUT_OF_MEMORY;
}
int janet_parser_has_more(JanetParser *parser) { int janet_parser_has_more(JanetParser *parser) {
return !!parser->pending; return !!parser->pending;
} }
@ -841,9 +886,19 @@ static Janet cfun_parse_state(int32_t argc, Janet *argv) {
return janet_wrap_string(str); return janet_wrap_string(str);
} }
static Janet cfun_parse_clone(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
JanetParser *src = janet_getabstract(argv, 0, &janet_parse_parsertype);
JanetParser *dest = janet_abstract(&janet_parse_parsertype, sizeof(JanetParser));
janet_parser_clone(src, dest);
return janet_wrap_abstract(dest);
}
static const JanetMethod parser_methods[] = { static const JanetMethod parser_methods[] = {
{"byte", cfun_parse_byte}, {"byte", cfun_parse_byte},
{"clone", cfun_parse_clone},
{"consume", cfun_parse_consume}, {"consume", cfun_parse_consume},
{"eof", cfun_parse_eof},
{"error", cfun_parse_error}, {"error", cfun_parse_error},
{"flush", cfun_parse_flush}, {"flush", cfun_parse_flush},
{"has-more", cfun_parse_has_more}, {"has-more", cfun_parse_has_more},
@ -852,7 +907,6 @@ static const JanetMethod parser_methods[] = {
{"state", cfun_parse_state}, {"state", cfun_parse_state},
{"status", cfun_parse_status}, {"status", cfun_parse_status},
{"where", cfun_parse_where}, {"where", cfun_parse_where},
{"eof", cfun_parse_eof},
{NULL, NULL} {NULL, NULL}
}; };
@ -867,7 +921,14 @@ static const JanetReg parse_cfuns[] = {
"parser/new", cfun_parse_parser, "parser/new", cfun_parse_parser,
JDOC("(parser/new)\n\n" JDOC("(parser/new)\n\n"
"Creates and returns a new parser object. Parsers are state machines " "Creates and returns a new parser object. Parsers are state machines "
"that can receive bytes, and generate a stream of janet values. ") "that can receive bytes, and generate a stream of janet values.")
},
{
"parser/clone", cfun_parse_clone,
JDOC("(parser/clone p)\n\n"
"Creates a deep clone of a parser that is identical to the input parser. "
"This cloned parser can be used to continue parsing from a good checkpoint "
"if parsing later fails. Returns a new parser.")
}, },
{ {
"parser/has-more", cfun_parse_has_more, "parser/has-more", cfun_parse_has_more,

View File

@ -109,4 +109,13 @@
(comment 1 2 3) (comment 1 2 3)
(comment 1 2 3 4) (comment 1 2 3 4)
# Parser clone
(def p (parser/new))
(assert (= 7 (parser/consume p "(1 2 3 ")) "parser 1")
(def p2 (parser/clone p))
(parser/consume p2 ") 1 ")
(parser/consume p ") 1 ")
(assert (deep= (parser/status p) (parser/status p2)) "parser 2")
(assert (deep= (parser/state p) (parser/state p2)) "parser 3")
(end-suite) (end-suite)