From 3a14858a70afb534fda1e8dcf41cdb7ee67525f4 Mon Sep 17 00:00:00 2001 From: Ian Piumarta Date: Wed, 22 Mar 2023 17:39:38 +0900 Subject: [PATCH] Make yy context be local. Add input struct pointer to yy context object. Returning multiple objects from meta function appends them all to program. Meta import via read-eval-print instead of changing input file pointer. Add treeCopy and treeCopyUnquoting functions. Add primitive treeCopy. --- src/ccmeta.leg | 131 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 106 insertions(+), 25 deletions(-) diff --git a/src/ccmeta.leg b/src/ccmeta.leg index f710b4c..457f64f 100644 --- a/src/ccmeta.leg +++ b/src/ccmeta.leg @@ -3,7 +3,7 @@ # Copyright (c) 2016-2021 Ian Piumarta and other contributors (see AUTHORS) # All rights reserved (see LICENSE) # -# Last edited: 2023-03-22 17:14:46 by piumarta on zora-10.local +# Last edited: 2023-03-22 17:37:51 by piumarta on zora-10.local %{ /* compile: leg -o ccmeta.c ccmeta.leg @@ -102,7 +102,7 @@ jb_record *jbs= NULL; jbs= jbrec.next // this is the global scope and other global variable for parsimony lang -oop globals= 0; +oop globals = 0; oop program = 0; oop prog_last = 0; oop prog_unions = 0; @@ -151,15 +151,16 @@ void runtimeError(char *fmt, ...); typedef struct input_t { - oop name; - FILE *file; - struct input_t *next; - int lineNumber; + struct input_t *next; + oop name; + FILE *file; + struct _yycontext *yy; + int lineNumber; } input_t; input_t *inputStack= NULL; -void inputStackPush(char *name) { +void inputStackPush(struct _yycontext *yy, char *name) { FILE *file = stdin; if (NULL != name) { file= fopen(name, "rb"); @@ -171,21 +172,25 @@ void inputStackPush(char *name) { name= ""; } input_t *input = malloc(sizeof(input_t)); + input->next= inputStack; input->name= makeString(name); input->lineNumber= 1; input->file= file; - input->next= inputStack; + input->yy= yy; inputStack= input; return; } input_t *inputStackPop(void) { assert(inputStack); + fclose(inputStack->file); input_t *first= inputStack; inputStack= first->next; return first; } +void readEvalPrint(oop scope, char *fileName); + int isFalse(oop obj) { return obj == null || (isInteger(obj) && (0 == getInteger(obj))); @@ -887,9 +892,12 @@ oop new_C_enumerator(oop id, oop attributeSpecifier, oop expression) { return object; } -#define YY_INPUT(buf, result, max_size) \ +#define YY_CTX_LOCAL 1 // allocate parser contexts explicitly +#define YY_CTX_MEMBERS input_t *input; // pointer back to our input structure + +#define YY_INPUT(yy, buf, result, max_size) \ { \ - int yyc= feof(inputStack->file) ? EOF : getc(inputStack->file); \ + int yyc= feof(yy->input->file) ? EOF : getc(yy->input->file); \ result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \ } @@ -909,7 +917,7 @@ oop eval(oop scope, oop ast); struct _yycontext; -int yyparsefrom(int (*yystart)(struct _yycontext *yy)); +int yyparsefrom(struct _yycontext *yy, int (*yystart)(struct _yycontext *yy)); int irow= 0, icol= 0; int gnu= 1; @@ -1357,7 +1365,38 @@ oop treeCopy(oop obj) oop map= malloc(sizeof(*obj)); memcpy(map, obj, sizeof(*obj)); for (int i = 0; ijb, 0); if (0 == jbt) { - while (yyparse()) { + while (yyparse(&ctx)) { if (!yylval) { // EOF - fclose(inputStack->file); - if (top == inputStack) break; - inputStackPop(); - assert(inputStack); - continue; + assert(top == inputStack); + break; } assert(yylval); if (null == yylval) { // change of language or input file @@ -3577,10 +3615,17 @@ void readEvalPrint(oop scope, char *fileName) } oop proto = map_get(yylval, __proto___symbol); if (proto == null) { + if (is(Map, yylval)) { // multiple values returned from meta function + for (int i = 0; i < map_size(yylval); i++) { + map_append(outputProgram, treeCopyUnquoting(scope, map_get(yylval, makeInteger(i)))); + } + continue; + } + println(map_keys(yylval)); printf("no prototype associated with "); println(yylval); fflush(stdout); - fprintf(stderr, "aborting\n"); + fprintf(stderr, "(readEvalPrint - proto == null) aborting\n"); exit(1); } // proto_number is the enum version of the proto symbol @@ -3622,10 +3667,6 @@ oop prim_import(oop scope, oop params) { if (map_hasIntegerKey(params, 0)) { char *file= get(get(params, Map, elements)[0].value, String, value); - if (yyctx->__pos < yyctx->__limit) { - yyctx->__limit--; - ungetc(yyctx->__buf[yyctx->__limit], inputStack->file); - } readEvalPrint(scope, file); } return null; @@ -3642,6 +3683,46 @@ oop prim_scope(oop scope, oop params) return fixScope(scope); } +oop prim_parseFrom(oop scope, oop params) +{ + if (map_size(params) != 1) return null; + oop name = get(params, Map, elements)[0].value; + if (!is(String, name)) return null; + char *s = get(name, String, value); + assert(inputStack); + struct _yycontext *zz = inputStack->yy; + struct _yycontext ctx, *yy = &ctx; + memcpy(&ctx, zz, sizeof(struct _yycontext)); + yy->__thunkslen= YY_STACK_SIZE; + yy->__thunks= (yythunk *)YY_MALLOC(yy, sizeof(yythunk) * yy->__thunkslen); + yy->__valslen= YY_STACK_SIZE; + yy->__vals= (YYSTYPE *)YY_MALLOC(yy, sizeof(YYSTYPE) * yy->__valslen); + yy->__thunkpos= 0; + int res; + if (!strcmp(s, "declaration" )) res = yyparsefrom(yy, yy_declaration ); + else if (!strcmp(s, "expression" )) res = yyparsefrom(yy, yy_expression ); + else if (!strcmp(s, "statement" )) res = yyparsefrom(yy, yy_statement ); + else if (!strcmp(s, "id" )) res = yyparsefrom(yy, yy_id ); + else if (!strcmp(s, "func" )) res = yyparsefrom(yy, yy_functionDefinition); + else if (!strcmp(s, "error" )) res = yyparsefrom(yy, yy_error ); + else { + fprintf(stderr, "parseFrom: %s not implemented", s); + exit(1); + } + oop value; + if (res) { + value = __; + zz->__buf= yy->__buf; + zz->__buflen= yy->__buflen; + zz->__pos= yy->__pos; + zz->__limit= yy->__limit; + } else { + printf("%s expected\n", s); + value = null; + } + return value; +} + #include oop prim_microseconds(oop scope, oop params)