mirror of
https://github.com/janet-lang/janet
synced 2024-12-24 23:40:27 +00:00
Complete adding parser to scripting.
This commit is contained in:
parent
631bb0cb63
commit
c6e9f24f82
@ -39,6 +39,7 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue env) {
|
||||
gst_compiler(&c, vm);
|
||||
gst_compiler_usemodule(&c, "std");
|
||||
gst_compiler_usemodule(&c, "std.io");
|
||||
gst_compiler_usemodule(&c, "std.parse");
|
||||
gst_compiler_globals(&c, env);
|
||||
func = gst_wrap_function(gst_compiler_compile(&c, ast));
|
||||
/* Check for compilation errors */
|
||||
@ -145,6 +146,7 @@ int main(int argc, const char **argv) {
|
||||
|
||||
gst_init(&vm);
|
||||
gst_stl_load(&vm);
|
||||
gst_parse_load(&vm);
|
||||
if (argc > 1) {
|
||||
const char *filename;
|
||||
FILE *f;
|
||||
|
11
core/gc.c
11
core/gc.c
@ -34,6 +34,11 @@ struct GCMemoryHeader {
|
||||
uint32_t tags : 31;
|
||||
};
|
||||
|
||||
/* Mark a chunk of memory as reachable for the gc */
|
||||
void gst_mark_mem(Gst *vm, void *mem) {
|
||||
gc_header(mem)->color = vm->black;
|
||||
}
|
||||
|
||||
/* Helper to mark function environments */
|
||||
static void gst_mark_funcenv(Gst *vm, GstFuncEnv *env) {
|
||||
if (gc_header(env)->color != vm->black) {
|
||||
@ -172,8 +177,10 @@ void gst_mark(Gst *vm, GstValueUnion x, GstType type) {
|
||||
|
||||
case GST_USERDATA:
|
||||
if (gc_header(x.string - sizeof(GstUserdataHeader))->color != vm->black) {
|
||||
GstUserdataHeader *userHeader = (GstUserdataHeader *)x.string - 1;
|
||||
gc_header(userHeader)->color = vm->black;
|
||||
GstUserdataHeader *h = (GstUserdataHeader *)x.pointer - 1;
|
||||
gc_header(h)->color = vm->black;
|
||||
if (h->type->gcmark)
|
||||
h->type->gcmark(vm, x.pointer, h->size);
|
||||
}
|
||||
break;
|
||||
|
||||
|
125
core/parse.c
125
core/parse.c
@ -42,11 +42,6 @@ struct GstParseState {
|
||||
uint8_t endDelimiter;
|
||||
GstArray *array;
|
||||
} form;
|
||||
struct {
|
||||
GstValue key;
|
||||
int keyFound;
|
||||
GstTable *table;
|
||||
} table;
|
||||
struct {
|
||||
GstBuffer *buffer;
|
||||
uint32_t count;
|
||||
@ -540,3 +535,123 @@ void gst_parser(GstParser *p, Gst *vm) {
|
||||
p->flags = GST_PARSER_FLAG_EXPECTING_COMMENT;
|
||||
parser_push(p, PTYPE_ROOT, ' ');
|
||||
}
|
||||
|
||||
/* CG finalize a parser */
|
||||
static void gst_stl_parser_finalize(Gst *vm, void *data, uint32_t len) {
|
||||
/* printf("Finalizing parser: %p, %d\n", data, len); */
|
||||
}
|
||||
|
||||
/* GC mark a parser */
|
||||
static void gst_stl_parser_mark(Gst *vm, void *data, uint32_t len) {
|
||||
uint32_t i;
|
||||
GstParser *p = (GstParser *) data;
|
||||
gst_mark_mem(vm, p->data);
|
||||
gst_mark_value(vm, p->value);
|
||||
for (i = 0; i < p->count; ++i) {
|
||||
GstParseState *ps = p->data + i;
|
||||
switch (ps->type) {
|
||||
case PTYPE_ROOT:
|
||||
break;
|
||||
case PTYPE_FORM:
|
||||
gst_mark_value(vm, gst_wrap_array(ps->buf.form.array));
|
||||
break;
|
||||
case PTYPE_STRING:
|
||||
case PTYPE_TOKEN:
|
||||
gst_mark_value(vm, gst_wrap_buffer(ps->buf.string.buffer));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***/
|
||||
/* Stl functions */
|
||||
/***/
|
||||
|
||||
/* Parse filetype */
|
||||
static const GstUserType gst_stl_parsetype = {
|
||||
"std.parser",
|
||||
NULL,
|
||||
NULL,
|
||||
&gst_stl_parser_finalize,
|
||||
&gst_stl_parser_mark
|
||||
};
|
||||
|
||||
/* Create a parser */
|
||||
int gst_stl_parser(Gst *vm) {
|
||||
GstParser *p = gst_userdata(vm, sizeof(GstParser), &gst_stl_parsetype);
|
||||
gst_parser(p, vm);
|
||||
gst_c_return(vm, gst_wrap_userdata(p));
|
||||
}
|
||||
|
||||
/* Consume a value from the parser */
|
||||
int gst_stl_parser_consume(Gst *vm) {
|
||||
GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype);
|
||||
if (p == NULL)
|
||||
gst_c_throwc(vm, "expected parser");
|
||||
if (!gst_parse_hasvalue(p))
|
||||
gst_c_throwc(vm, "parser has no pending value");
|
||||
gst_c_return(vm, gst_parse_consume(p));
|
||||
}
|
||||
|
||||
/* Check if the parser has a value to consume */
|
||||
int gst_stl_parser_hasvalue(Gst *vm) {
|
||||
GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype);
|
||||
if (p == NULL)
|
||||
gst_c_throwc(vm, "expected parser");
|
||||
gst_c_return(vm, gst_wrap_boolean(gst_parse_hasvalue(p)));
|
||||
}
|
||||
|
||||
/* Parse a single byte. Returns if the byte was successfully parsed. */
|
||||
int gst_stl_parser_byte(Gst *vm) {
|
||||
GstInteger b;
|
||||
GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype);
|
||||
if (p == NULL)
|
||||
gst_c_throwc(vm, "expected parser");
|
||||
if (!gst_check_integer(vm, 1, &b))
|
||||
gst_c_throwc(vm, "expected integer");
|
||||
if (p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT) {
|
||||
dispatch_char(p, b);
|
||||
gst_c_return(vm, gst_wrap_boolean(1));
|
||||
} else {
|
||||
gst_c_return(vm, gst_wrap_boolean(0));
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse a string or buffer. Returns nil if the entire char array is parsed,
|
||||
* otherwise returns the remainder of what could not be parsed. */
|
||||
int gst_stl_parser_charseq(Gst *vm) {
|
||||
uint32_t i;
|
||||
uint32_t len;
|
||||
const uint8_t *data;
|
||||
GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype);
|
||||
if (p == NULL)
|
||||
gst_c_throwc(vm, "expected parser");
|
||||
if (!gst_chararray_view(gst_arg(vm, 1), &data, &len))
|
||||
gst_c_throwc(vm, "expected string/buffer");
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (p->status != GST_PARSER_PENDING && p->status != GST_PARSER_ROOT) break;
|
||||
dispatch_char(p, data[i]);
|
||||
}
|
||||
if (i == len) {
|
||||
/* No remainder */
|
||||
gst_c_return(vm, gst_wrap_nil());
|
||||
} else {
|
||||
/* We have remaining characters */
|
||||
gst_c_return(vm, gst_wrap_string(gst_string_b(vm, data + i, len - i)));
|
||||
}
|
||||
}
|
||||
|
||||
/* The module */
|
||||
static const GstModuleItem gst_parser_module[] = {
|
||||
{"parser", gst_stl_parser},
|
||||
{"parse-byte", gst_stl_parser_byte},
|
||||
{"parse-consume", gst_stl_parser_consume},
|
||||
{"parse-hasvalue", gst_stl_parser_hasvalue},
|
||||
{"parse-charseq", gst_stl_parser_charseq},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* Load the module */
|
||||
void gst_parse_load(Gst *vm) {
|
||||
gst_module_put(vm, "std.parse", gst_cmodule_struct(vm, gst_parser_module));
|
||||
}
|
||||
|
@ -524,6 +524,7 @@ static GstUserType gst_stl_filetype = {
|
||||
"io.file",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -646,6 +647,12 @@ int gst_stl_dasm(Gst *vm) {
|
||||
return GST_RETURN_OK;
|
||||
}
|
||||
|
||||
/* Force garbage collection */
|
||||
int gst_stl_gcollect(Gst *vm) {
|
||||
gst_collect(vm);
|
||||
return GST_RETURN_OK;
|
||||
}
|
||||
|
||||
/****/
|
||||
/* Bootstraping */
|
||||
/****/
|
||||
@ -693,6 +700,7 @@ static const GstModuleItem const std_module[] = {
|
||||
{"write", gst_stl_write},
|
||||
{"close", gst_stl_close},
|
||||
{"dasm", gst_stl_dasm},
|
||||
{"gcollect", gst_stl_gcollect},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -191,7 +191,7 @@ GstInteger gst_real_to_integer(GstReal x) {
|
||||
}
|
||||
|
||||
GstInteger gst_startrange(GstInteger raw, uint32_t len) {
|
||||
if (raw > len)
|
||||
if (raw >= len)
|
||||
return -1;
|
||||
if (raw < 0)
|
||||
return len + raw;
|
||||
|
@ -264,6 +264,7 @@ struct GstUserType {
|
||||
GstValue (*serialize)(Gst *vm, void *data, uint32_t len);
|
||||
GstValue (*deserialize)(Gst *vm, GstValue in);
|
||||
void (*finalize)(Gst *vm, void *data, uint32_t len);
|
||||
void (*gcmark)(Gst *vm, void *data, uint32_t len);
|
||||
};
|
||||
|
||||
/* Contains information about userdata */
|
||||
@ -462,6 +463,7 @@ void gst_mem_tag(void *mem, uint32_t tags);
|
||||
void gst_collect(Gst *vm);
|
||||
void gst_maybe_collect(Gst *vm);
|
||||
void gst_clear_memory(Gst *vm);
|
||||
void gst_mark_mem(Gst *vm, void *mem);
|
||||
|
||||
/****/
|
||||
/* VM */
|
||||
|
@ -68,4 +68,7 @@ int gst_parse_hasvalue(GstParser *p);
|
||||
/* Gets a value from the parser */
|
||||
GstValue gst_parse_consume(GstParser *p);
|
||||
|
||||
/* Load the parsing library */
|
||||
void gst_parse_load(Gst *vm);
|
||||
|
||||
#endif /* end of include guard: PARSE_H_ONYWMADW */
|
||||
|
Loading…
Reference in New Issue
Block a user