mirror of
https://github.com/janet-lang/janet
synced 2024-11-28 11:09:54 +00:00
Add parser/clone. (#120)
This commit is contained in:
parent
802a2d6b71
commit
43520ac67d
@ -634,6 +634,51 @@ void janet_parser_deinit(JanetParser *parser) {
|
||||
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) {
|
||||
return !!parser->pending;
|
||||
}
|
||||
@ -841,9 +886,19 @@ static Janet cfun_parse_state(int32_t argc, Janet *argv) {
|
||||
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[] = {
|
||||
{"byte", cfun_parse_byte},
|
||||
{"clone", cfun_parse_clone},
|
||||
{"consume", cfun_parse_consume},
|
||||
{"eof", cfun_parse_eof},
|
||||
{"error", cfun_parse_error},
|
||||
{"flush", cfun_parse_flush},
|
||||
{"has-more", cfun_parse_has_more},
|
||||
@ -852,7 +907,6 @@ static const JanetMethod parser_methods[] = {
|
||||
{"state", cfun_parse_state},
|
||||
{"status", cfun_parse_status},
|
||||
{"where", cfun_parse_where},
|
||||
{"eof", cfun_parse_eof},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@ -869,6 +923,13 @@ static const JanetReg parse_cfuns[] = {
|
||||
"Creates and returns a new parser object. Parsers are state machines "
|
||||
"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,
|
||||
JDOC("(parser/has-more parser)\n\n"
|
||||
|
@ -109,4 +109,13 @@
|
||||
(comment 1 2 3)
|
||||
(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)
|
||||
|
Loading…
Reference in New Issue
Block a user