]> ocean-lang.org Git - ocean/commitdiff
pargergen: support $<N in code fragments
authorNeilBrown <neilb@suse.de>
Sun, 11 May 2014 06:58:40 +0000 (16:58 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 15 Jun 2014 07:18:28 +0000 (17:18 +1000)
This removes the need to add "$N = NULL" to avoid the referenced structure
being removed.

Signed-off-by: NeilBrown <neilb@suse.de>
csrc/parsergen.mdc

index ef01bf31c0e825a4201fe60149252906a18cf615..b3d1cf638b3d47a4ff84add7b05c89eef59d86de 100644 (file)
@@ -397,12 +397,15 @@ collected and forms the code-fragment for the production.  It must all
 be in one `code_node` of the literate code.  The `}$` must be
 at the end of a line.
 
 be in one `code_node` of the literate code.  The `}$` must be
 at the end of a line.
 
-Text in the code fragment will undergo substitutions where `$N` for
-some numeric `N` will be replaced with a variable holding the parse
-information for the particular symbol in the production.  `$0` is the
-head of the production, `$1` is the first symbol of the body, etc.
-The type of `$N` for a terminal symbol is `struct token`.  For
-a non-terminal, it is whatever has been declared for that symbol.
+Text in the code fragment will undergo substitutions where `$N` or
+`$<N`,for some numeric `N`, will be replaced with a variable holding
+the parse information for the particular symbol in the production.
+`$0` is the head of the production, `$1` is the first symbol of the
+body, etc.  The type of `$N` for a terminal symbol is `struct token`.
+For a non-terminal, it is whatever has been declared for that symbol.
+The `<` may be included for symbols declared as storing a reference
+(not a structure) and means that the reference is being moved out, so
+it will not automatically be freed.
 
 While building productions we will need to add to an array which needs to
 grow dynamically.
 
 While building productions we will need to add to an array which needs to
 grow dynamically.
@@ -1965,15 +1968,23 @@ structure returned by a previous reduction.  These pointers need to be cast
 to the appropriate type for each access.  All this is handling in
 `gen_code`.
 
 to the appropriate type for each access.  All this is handling in
 `gen_code`.
 
+`gen_code` also allows symbol references to contain a '`<`' as in '`$<2`'.
+This applied only to symbols with references (or pointers), not those with structures.
+The `<` implies that the reference it being moved out, so the object will not be
+automatically freed.  This is equivalent to assigning `NULL` to the pointer.
 
 ###### functions
 
        static void gen_code(struct production *p, FILE *f, struct grammar *g)
        {
                char *c;
 
 ###### functions
 
        static void gen_code(struct production *p, FILE *f, struct grammar *g)
        {
                char *c;
+               char *used = calloc(1, p->body_size);
+               int i;
+
                fprintf(f, "\t\t\t");
                for (c = p->code.txt; c < p->code.txt + p->code.len; c++) {
                        int n;
                fprintf(f, "\t\t\t");
                for (c = p->code.txt; c < p->code.txt + p->code.len; c++) {
                        int n;
+                       int use = 0;
                        if (*c != '$') {
                                fputc(*c, f);
                                if (*c == '\n')
                        if (*c != '$') {
                                fputc(*c, f);
                                if (*c == '\n')
@@ -1981,7 +1992,13 @@ to the appropriate type for each access.  All this is handling in
                                continue;
                        }
                        c++;
                                continue;
                        }
                        c++;
+                       if (*c == '<') {
+                               use = 1;
+                               c++;
+                       }
                        if (*c < '0' || *c > '9') {
                        if (*c < '0' || *c > '9') {
+                               if (use)
+                                       fputc('<', f);
                                fputc(*c, f);
                                continue;
                        }
                                fputc(*c, f);
                                continue;
                        }
@@ -2002,13 +2019,23 @@ to the appropriate type for each access.  All this is handling in
                                        n-1);
                        else if (p->body[n-1]->struct_name.txt == NULL)
                                fprintf(f, "$%d", n);
                                        n-1);
                        else if (p->body[n-1]->struct_name.txt == NULL)
                                fprintf(f, "$%d", n);
-                       else
+                       else {
                                fprintf(f, "(*(struct %.*s*%s)body[%d])",
                                        p->body[n-1]->struct_name.len,
                                        p->body[n-1]->struct_name.txt,
                                        p->body[n-1]->isref ? "*":"", n-1);
                                fprintf(f, "(*(struct %.*s*%s)body[%d])",
                                        p->body[n-1]->struct_name.len,
                                        p->body[n-1]->struct_name.txt,
                                        p->body[n-1]->isref ? "*":"", n-1);
+                               used[n-1] = use;
+                       }
                }
                fputs("\n", f);
                }
                fputs("\n", f);
+               for (i = 0; i < p->body_size; i++) {
+                       if (p->body[i]->struct_name.txt &&
+                           p->body[i]->isref &&
+                           used[i])
+                               // assume this has been copied out
+                               fprintf(f, "\t\t*(void**)body[%d] = NULL;\n", i);
+               }
+               free(used);
        }
 
 ###### functions
        }
 
 ###### functions