Browse Source

added parsing of string literals

main
Ludovic 'Archivist' Lagouardette 1 month ago
parent
commit
bdc1d1dac9
4 changed files with 107 additions and 8 deletions
  1. +3
    -0
      CMakeLists.txt
  2. +1
    -0
      include/ink.h
  3. +102
    -8
      lib.c
  4. +1
    -0
      test/test04.nk

+ 3
- 0
CMakeLists.txt View File

@ -11,6 +11,9 @@ add_library(ink lib.c include/ink.h)
# Uncomment to disable array types
# add_definitions(-DNOARRAYLIB)
# Uncomment to disable string literals
# add_definitions(-DNOSTRINGLITERALS)
# Ensures the interpreter doesn't use the standard C library functions
# add_definitions(-DNOSTDLIB)

+ 1
- 0
include/ink.h View File

@ -99,6 +99,7 @@ struct ink_collection_list {
*/
struct element_slab {
void* data;
int is_protected;
int uses;
int in_use;
};

+ 102
- 8
lib.c View File

@ -355,11 +355,43 @@ struct context* ink_make_default_context(void) {
}
#endif
static int ink_consume_one(int* end, struct context* pContext, char* r) {
#ifndef NOSTRINGLITERALS
static void new_protected_array(struct context* ctx);
#endif
static int ink_consume_one(int* end, struct context* pContext, char* r, int is_str) {
int i;
int done;
struct elem value;
int err;
#ifndef NOSTRINGLITERALS
if(is_str) {
struct ink_routine* routine = pContext->routines + pContext->routine_current;
struct ink_array* ary;
int it = 0;
new_protected_array(pContext);
if(routine->top < 1) {
pContext->panic = -1;
return -8746;
}
value = routine->stack[routine->top - 1];
ary = ink_get_value(pContext, value);
if(ary == NULL) {
pContext->panic = -1;
return -8747;
}
for(;it != *end;++it) {
struct elem character;
character.type = INK_INTEGER;
/* TODO: codepoint conversion and coalescence is required here */
character.value = r[it];
array_push(pContext, routine, ary, character);
}
*end = 0;
return 0;
}
#endif
is_str = is_str;
if(*end == 0) {
return 0;
}
@ -460,9 +492,46 @@ static int ink_lex(struct context *pContext, const char* buffer) {
char r[128];
int end;
int err;
#ifndef NOSTRINGLITERALS
int parses_string;
#endif
end = 0;
restart_after_comment:
#ifndef NOSTRINGLITERALS
parses_string = 0;
#endif
while(*buffer != 0) {
#ifndef NOSTRINGLITERALS
if(parses_string) {
switch(*buffer) {
case '"': {
if(*(buffer+1) == 0 || isspace(*(buffer+1))) {
err = ink_consume_one(&end, pContext, r, 1);
if(err < 0) {
pContext->panic = 1;
return -995;
}
parses_string = 0;
} else if(*(buffer+1) == '"') {
r[end] = *buffer;
++end;
++buffer;
} else if(*(buffer+1) == '/' && *(buffer+2) == '"') {
r[end] = '\n';
++end;
++buffer;
++buffer;
} else {
pContext->panic = 1;
return -994;
}
}break;
default:
r[end] = *buffer;
++end;
}
} else /* ... */
#endif
if(isspace(*buffer)) {
if(end == 1 && r[0] == '#') {
while(*buffer != '\n' && *buffer != 0) {
@ -471,18 +540,24 @@ restart_after_comment:
end = 0;
goto restart_after_comment;
}
err = ink_consume_one(&end, pContext, r);
err = ink_consume_one(&end, pContext, r, 0);
if(err < 0) {
pContext->panic = 1;
return -8;
}
} else {
} else /* ... */
#ifndef NOSTRINGLITERALS
if(end == 0 && *buffer == '"' && !parses_string) {
parses_string = 1;
} else /* ... */
#endif
{
r[end] = *buffer;
++end;
}
++buffer;
}
err = ink_consume_one(&end, pContext, r);
err = ink_consume_one(&end, pContext, r, 0);
if(err < 0) {
pContext->panic = 1;
return -9;
@ -930,7 +1005,7 @@ void* ink_get_value(struct context* ctx, struct elem ref) {
return s->data;
}
struct elem ink_make_native(struct context* ctx, int type, void* ptr) {
struct elem ink_make_native_unsafe(struct context* ctx, int type, void* ptr, int is_protected) {
int type_id;
struct elem ret;
int g, i;
@ -982,7 +1057,8 @@ struct elem ink_make_native(struct context* ctx, int type, void* ptr) {
for(i = 0; i < g; ++i) {
if(! ctx->types[type_id].elements[i].in_use) {
ctx->types[type_id].elements[i].in_use = 1;
ctx->types[type_id].elements[i].uses = 1;
ctx->types[type_id].elements[i].uses = 1;
ctx->types[type_id].elements[i].is_protected = is_protected;
if(ctx->types[type_id].element_size < 0) {
ctx->types[type_id].elements[i].data = ptr;
} else {
@ -1006,6 +1082,10 @@ struct elem ink_make_native(struct context* ctx, int type, void* ptr) {
return ret;
}
struct elem ink_make_native(struct context* ctx, int type, void* ptr) {
return ink_make_native_unsafe(ctx, type, ptr, 0);
}
void ink_gc(struct context* ctx) {
int i, j, k;
int marked;
@ -1041,7 +1121,7 @@ void ink_gc(struct context* ctx) {
for (i = 0; i < ctx->types_top; ++i) {
for (j = 0; j < ctx->types[i].elements_top; ++j) {
/* Only mark from things that are active and detected as in use */
if (ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].uses) {
if (ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].is_protected && ctx->types[i].elements[j].uses) {
struct ink_collection_list c;
c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data);
for (k = 0; k < c.count; ++k) {
@ -1061,7 +1141,7 @@ void ink_gc(struct context* ctx) {
/* Sweep phase: explore any allocated data and sweep the unused away */
for(i = 0; i < ctx->types_top; ++i) {
for(j = 0; j < ctx->types[i].elements_top; ++j) {
if(ctx->types[i].elements[j].uses == 0 && ctx->types[i].elements[j].in_use) {
if(ctx->types[i].elements[j].uses == 0 && ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].is_protected == 0) {
ctx->collections++;
ctx->types[i].collect(ctx, ctx->types[i].elements[j].data);
if(ctx->types[i].element_size > 0) {
@ -1598,6 +1678,20 @@ static void new_array(struct context* ctx) {
ink_push(ctx, e);
}
#ifndef NOSTRINGLITERALS
static void new_protected_array(struct context* ctx) {
int tid;
struct elem e;
struct ink_array ary;
tid = get_type_by_name(ctx, "array");
ary.elements = NULL;
ary.top = 0;
ary.capacity = 0;
e = ink_make_native_unsafe(ctx, tid, &ary, 1);
ink_push(ctx, e);
}
#endif
static void push_array_stack_delim(struct context* ctx) {
int tid;
struct elem e;

+ 1
- 0
test/test04.nk View File

@ -0,0 +1 @@
"""Hello world"""/"" array.print_utf8

Loading…
Cancel
Save