mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 07:33:01 +00:00 
			
		
		
		
	Complete adding parser to scripting.
This commit is contained in:
		| @@ -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 */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose