]> 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.
 
-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.
@@ -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`.
 
+`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;
+               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;
+                       int use = 0;
                        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++;
+                       if (*c == '<') {
+                               use = 1;
+                               c++;
+                       }
                        if (*c < '0' || *c > '9') {
+                               if (use)
+                                       fputc('<', f);
                                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);
-                       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);
+                               used[n-1] = use;
+                       }
                }
                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