]> ocean-lang.org Git - ocean/commitdiff
parsergen: allow prefix code for do_reduce to be provided.
authorNeilBrown <neil@brown.name>
Thu, 6 Jun 2019 22:51:23 +0000 (08:51 +1000)
committerNeilBrown <neil@brown.name>
Thu, 6 Jun 2019 22:51:23 +0000 (08:51 +1000)
This allow common variables to be declared and initialised
for all reduce fragments.

Use this in oceani to declare 'c' holding the parser context,
so we don't need to call config2context in so many places.

Signed-off-by: NeilBrown <neil@brown.name>
csrc/oceani.mdc
csrc/parsergen.mdc

index 1f4805e85eb9a901571474f45051b618ca60fee6..f36bbdb13593c6c306920bacd7d1d619513c2957 100644 (file)
@@ -123,6 +123,9 @@ structures can be used.
        #define config2context(_conf) container_of(_conf, struct parse_context, \
                config)
 
+###### Parser: reduce
+       struct parse_context *c = config2context(config);
+
 ###### Parser: code
 
        #include <unistd.h>
@@ -1002,7 +1005,7 @@ like "if" and the code following it.
 ###### Grammar
 
        $void
-       OpenScope -> ${ scope_push(config2context(config)); }$
+       OpenScope -> ${ scope_push(c); }$
 
 Each variable records a scope depth and is in one of four states:
 
@@ -1675,7 +1678,6 @@ make a copy of an array with controllable depth.
                $0->array.member = $<4;
                $0->array.vsize = NULL;
                {
-               struct parse_context *c = config2context(config);
                char tail[3];
                mpq_t num;
                if (number_parse(num, tail, $2.txt) == 0)
@@ -1698,13 +1700,12 @@ make a copy of an array with controllable depth.
        }$
 
        | [ IDENTIFIER ] Type ${ {
-               struct parse_context *c = config2context(config);
                struct variable *v = var_ref(c, $2.txt);
 
                if (!v)
-                       tok_err(config2context(config), "error: name undeclared", &$2);
+                       tok_err(c, "error: name undeclared", &$2);
                else if (!v->constant)
-                       tok_err(config2context(config), "error: array size must be a constant", &$2);
+                       tok_err(c, "error: array size must be a constant", &$2);
 
                $0 = calloc(1, sizeof(struct type));
                *($0) = array_prototype;
@@ -2001,7 +2002,7 @@ function will be needed.
 ###### top level grammar
        DeclareStruct -> struct IDENTIFIER FieldBlock ${ {
                struct type *t =
-                       add_type(config2context(config), $2.txt, &structure_prototype);
+                       add_type(c, $2.txt, &structure_prototype);
                int cnt = 0;
                struct fieldlist *f;
 
@@ -2053,10 +2054,10 @@ function will be needed.
                        $0->f.init = val_prepare($0->f.type);
                        do {
                                ok = 1;
-                               propagate_types($<5, config2context(config), &ok, $3, 0);
+                               propagate_types($<5, c, &ok, $3, 0);
                        } while (ok == 2);
                        if (!ok)
-                               config2context(config)->parse_error = 1;
+                               c->parse_error = 1;
                        else
                                $0->f.init = interp_exec($5);
                } }$
@@ -2159,7 +2160,7 @@ an executable.
                        if (number_parse($0->val.num, tail, $1.txt) == 0)
                                mpq_init($0->val.num);
                                if (tail[0])
-                                       tok_err(config2context(config), "error: unsupported number suffix",
+                                       tok_err(c, "error: unsupported number suffix",
                                                &$1);
                        }
                        }$
@@ -2170,7 +2171,7 @@ an executable.
                        char tail[3];
                        string_parse(&$1, '\\', &$0->val.str, tail);
                        if (tail[0])
-                               tok_err(config2context(config), "error: unsupported string suffix",
+                               tok_err(c, "error: unsupported string suffix",
                                        &$1);
                        }
                        }$
@@ -2181,7 +2182,7 @@ an executable.
                        char tail[3];
                        string_parse(&$1, '\\', &$0->val.str, tail);
                        if (tail[0])
-                               tok_err(config2context(config), "error: unsupported string suffix",
+                               tok_err(c, "error: unsupported string suffix",
                                        &$1);
                        }
                        }$
@@ -2268,38 +2269,38 @@ link to find the primary instance.
 
        $*var
        VariableDecl -> IDENTIFIER : ${ {
-               struct variable *v = var_decl(config2context(config), $1.txt);
+               struct variable *v = var_decl(c, $1.txt);
                $0 = new_pos(var, $1);
                $0->var = v;
                if (v)
                        v->where_decl = $0;
                else {
-                       v = var_ref(config2context(config), $1.txt);
+                       v = var_ref(c, $1.txt);
                        $0->var = v;
-                       type_err(config2context(config), "error: variable '%v' redeclared",
+                       type_err(c, "error: variable '%v' redeclared",
                                 $0, NULL, 0, NULL);
-                       type_err(config2context(config), "info: this is where '%v' was first declared",
+                       type_err(c, "info: this is where '%v' was first declared",
                                 v->where_decl, NULL, 0, NULL);
                }
        } }$
            | IDENTIFIER :: ${ {
-               struct variable *v = var_decl(config2context(config), $1.txt);
+               struct variable *v = var_decl(c, $1.txt);
                $0 = new_pos(var, $1);
                $0->var = v;
                if (v) {
                        v->where_decl = $0;
                        v->constant = 1;
                } else {
-                       v = var_ref(config2context(config), $1.txt);
+                       v = var_ref(c, $1.txt);
                        $0->var = v;
-                       type_err(config2context(config), "error: variable '%v' redeclared",
+                       type_err(c, "error: variable '%v' redeclared",
                                 $0, NULL, 0, NULL);
-                       type_err(config2context(config), "info: this is where '%v' was first declared",
+                       type_err(c, "info: this is where '%v' was first declared",
                                 v->where_decl, NULL, 0, NULL);
                }
        } }$
            | IDENTIFIER : Type ${ {
-               struct variable *v = var_decl(config2context(config), $1.txt);
+               struct variable *v = var_decl(c, $1.txt);
                $0 = new_pos(var, $1);
                $0->var = v;
                if (v) {
@@ -2307,16 +2308,16 @@ link to find the primary instance.
                        v->where_set = $0;
                        v->val = val_prepare($<3);
                } else {
-                       v = var_ref(config2context(config), $1.txt);
+                       v = var_ref(c, $1.txt);
                        $0->var = v;
-                       type_err(config2context(config), "error: variable '%v' redeclared",
+                       type_err(c, "error: variable '%v' redeclared",
                                 $0, NULL, 0, NULL);
-                       type_err(config2context(config), "info: this is where '%v' was first declared",
+                       type_err(c, "info: this is where '%v' was first declared",
                                 v->where_decl, NULL, 0, NULL);
                }
        } }$
            | IDENTIFIER :: Type ${ {
-               struct variable *v = var_decl(config2context(config), $1.txt);
+               struct variable *v = var_decl(c, $1.txt);
                $0 = new_pos(var, $1);
                $0->var = v;
                if (v) {
@@ -2325,22 +2326,22 @@ link to find the primary instance.
                        v->val = val_prepare($<3);
                        v->constant = 1;
                } else {
-                       v = var_ref(config2context(config), $1.txt);
+                       v = var_ref(c, $1.txt);
                        $0->var = v;
-                       type_err(config2context(config), "error: variable '%v' redeclared",
+                       type_err(c, "error: variable '%v' redeclared",
                                 $0, NULL, 0, NULL);
-                       type_err(config2context(config), "info: this is where '%v' was first declared",
+                       type_err(c, "info: this is where '%v' was first declared",
                                 v->where_decl, NULL, 0, NULL);
                }
        } }$
 
        $*exec
        Variable -> IDENTIFIER ${ {
-               struct variable *v = var_ref(config2context(config), $1.txt);
+               struct variable *v = var_ref(c, $1.txt);
                $0 = new_pos(var, $1);
                if (v == NULL) {
                        /* This might be a label - allocate a var just in case */
-                       v = var_decl(config2context(config), $1.txt);
+                       v = var_decl(c, $1.txt);
                        if (v) {
                                v->val = val_prepare(Tlabel);
                                v->val.label = &v->val;
@@ -2353,9 +2354,9 @@ link to find the primary instance.
 
        $*type
        Type -> IDENTIFIER ${
-               $0 = find_type(config2context(config), $1.txt);
+               $0 = find_type(c, $1.txt);
                if (!$0) {
-                       tok_err(config2context(config),
+                       tok_err(c,
                                "error: undefined type", &$1);
 
                        $0 = Tnone;
@@ -3259,7 +3260,7 @@ it is declared, and error will be raised as the name is created as
 
        | VariableDecl ${
                        if ($1->var->where_set == NULL) {
-                               type_err(config2context(config),
+                               type_err(c,
                                         "Variable declared with no type or value: %v",
                                         $1, NULL, 0, NULL);
                        } else {
@@ -3530,7 +3531,7 @@ defined.
                        $0->thenpart = $<2;
                        $0->condpart = $3.condpart; $3.condpart = NULL;
                        $0->dopart = $3.dopart; $3.dopart = NULL;
-                       var_block_close(config2context(config), CloseSequential);
+                       var_block_close(c, CloseSequential);
                        }$
                |  forPart WhilePart CondSuffix ${
                        $0 = $<3;
@@ -3538,7 +3539,7 @@ defined.
                        $0->thenpart = NULL;
                        $0->condpart = $2.condpart; $2.condpart = NULL;
                        $0->dopart = $2.dopart; $2.dopart = NULL;
-                       var_block_close(config2context(config), CloseSequential);
+                       var_block_close(c, CloseSequential);
                        }$
                | whilePart CondSuffix ${
                        $0 = $<2;
@@ -3554,14 +3555,14 @@ defined.
                        $0->condpart = $1.condpart; $1.condpart = NULL;
                        $0->thenpart = $1.thenpart; $1.thenpart = NULL;
                        // This is where we close an "if" statement
-                       var_block_close(config2context(config), CloseSequential);
+                       var_block_close(c, CloseSequential);
                        }$
 
        CondSuffix -> IfSuffix ${
                        $0 = $<1;
                        // This is where we close scope of the whole
                        // "for" or "while" statement
-                       var_block_close(config2context(config), CloseSequential);
+                       var_block_close(c, CloseSequential);
                }$
                | CasePart CondSuffix ${
                        $0 = $<2;
@@ -3577,7 +3578,7 @@ defined.
                        $0 = calloc(1,sizeof(struct casepart));
                        $0->value = $<2;
                        $0->action = $<4;
-                       var_block_close(config2context(config), CloseParallel);
+                       var_block_close(c, CloseParallel);
                }$
 
        $*cond_statement
@@ -3586,12 +3587,12 @@ defined.
                | else OpenScope Block ${
                        $0 = new(cond_statement);
                        $0->elsepart = $<3;
-                       var_block_close(config2context(config), CloseElse);
+                       var_block_close(c, CloseElse);
                }$
                | else OpenScope CondStatement ${
                        $0 = new(cond_statement);
                        $0->elsepart = $<3;
-                       var_block_close(config2context(config), CloseElse);
+                       var_block_close(c, CloseElse);
                }$
 
        $void
@@ -3612,11 +3613,11 @@ defined.
 
        ThenPart -> Then OpenScope SimpleStatements ${
                        $0 = reorder_bilist($<3);
-                       var_block_close(config2context(config), CloseSequential);
+                       var_block_close(c, CloseSequential);
                }$
                |  Then OpenScope Block ${
                        $0 = $<3;
-                       var_block_close(config2context(config), CloseSequential);
+                       var_block_close(c, CloseSequential);
                }$
 
        // This scope is closed in CondSuffix
@@ -3654,13 +3655,13 @@ defined.
                        $0.type = Xcond_statement;
                        $0.condpart = $<3;
                        $0.thenpart = $<5;
-                       var_block_close(config2context(config), CloseParallel);
+                       var_block_close(c, CloseParallel);
                }$
                | if OpenScope Block Then OpenScope Block ${
                        $0.type = Xcond_statement;
                        $0.condpart = $<3;
                        $0.thenpart = $<6;
-                       var_block_close(config2context(config), CloseParallel);
+                       var_block_close(c, CloseParallel);
                }$
 
        $*exec
@@ -3966,7 +3967,7 @@ searching through for the Nth constant for decreasing N.
                int ok;
                struct variable *v;
 
-               v = var_decl(config2context(config), $1.txt);
+               v = var_decl(c, $1.txt);
                if (v) {
                        struct var *var = new_pos(var, $1);
                        v->where_decl = var;
@@ -3974,17 +3975,17 @@ searching through for the Nth constant for decreasing N.
                        var->var = v;
                        v->constant = 1;
                } else {
-                       v = var_ref(config2context(config), $1.txt);
-                       tok_err(config2context(config), "error: name already declared", &$1);
-                       type_err(config2context(config), "info: this is where '%v' was first declared",
+                       v = var_ref(c, $1.txt);
+                       tok_err(c, "error: name already declared", &$1);
+                       type_err(c, "info: this is where '%v' was first declared",
                                 v->where_decl, NULL, 0, NULL);
                }
                do {
                        ok = 1;
-                       propagate_types($5, config2context(config), &ok, $3, 0);
+                       propagate_types($5, c, &ok, $3, 0);
                } while (ok == 2);
                if (!ok)
-                       config2context(config)->parse_error = 1;
+                       c->parse_error = 1;
                else if (v) {
                        v->val = interp_exec($5);
                }
@@ -4043,7 +4044,6 @@ analysis is a bit more interesting at this level.
 ###### top level grammar
 
        DeclareProgram -> Program ${ {
-               struct parse_context *c = config2context(config);
                if (c->prog)
                        type_err(c, "Program defined a second time",
                                 $1, NULL, 0, NULL);
@@ -4057,11 +4057,11 @@ analysis is a bit more interesting at this level.
                $0->op = Program;
                $0->left = reorder_bilist($<3);
                $0->right = $<4;
-               var_block_close(config2context(config), CloseSequential);
-               if (config2context(config)->scope_stack) abort();
+               var_block_close(c, CloseSequential);
+               if (c->scope_stack) abort();
                }$
                | ERROR ${
-                       tok_err(config2context(config),
+                       tok_err(c,
                                "error: unhandled parse error", &$1);
                }$
 
@@ -4075,7 +4075,7 @@ analysis is a bit more interesting at this level.
 
        $*var
        ArgDecl -> IDENTIFIER ${ {
-               struct variable *v = var_decl(config2context(config), $1.txt);
+               struct variable *v = var_decl(c, $1.txt);
                $0 = new(var);
                $0->var = v;
        } }$
index 2fdbf453c8114746843e5b3f95ee2ab07b570932..478482e0f6b0512b9fc09946b4b1b5ead04fe7fd 100644 (file)
@@ -1872,13 +1872,14 @@ pieces of code provided in the grammar file, so they are generated first.
 
 ###### parser_generate
 
-       static void gen_parser(FILE *f, struct grammar *g, char *file, char *name)
+       static void gen_parser(FILE *f, struct grammar *g, char *file, char *name,
+                              struct code_node *pre_reduce)
        {
                gen_known(f, g);
                gen_non_term(f, g);
                gen_goto(f, g);
                gen_states(f, g);
-               gen_reduce(f, g, file);
+               gen_reduce(f, g, file, pre_reduce);
                gen_free(f, g);
 
                fprintf(f, "#line 0 \"gen_parser\"\n");
@@ -2112,14 +2113,18 @@ automatically freed.  This is equivalent to assigning `NULL` to the pointer.
 
 ###### functions
 
-       static void gen_reduce(FILE *f, struct grammar *g, char *file)
+       static void gen_reduce(FILE *f, struct grammar *g, char *file,
+                              struct code_node *code)
        {
                int i;
-               fprintf(f, "#line 0 \"gen_reduce\"\n");
+               fprintf(f, "#line 1 \"gen_reduce\"\n");
                fprintf(f, "static int do_reduce(int prod, void **body, struct token_config *config, void *ret)\n");
                fprintf(f, "{\n");
                fprintf(f, "\tint ret_size = 0;\n");
+               if (code)
+                       code_node_print(f, code, file);
 
+               fprintf(f, "#line 4 \"gen_reduce\"\n");
                fprintf(f, "\tswitch(prod) {\n");
                for (i = 0; i < g->production_count; i++) {
                        struct production *p = g->productions[i];
@@ -2316,6 +2321,7 @@ parser with neither. "grammar" must be provided.
        struct code_node *hdr = NULL;
        struct code_node *code = NULL;
        struct code_node *gram = NULL;
+       struct code_node *pre_reduce = NULL;
        for (s = table; s; s = s->next) {
                struct text sec = s->section;
                if (tag && !strip_tag(&sec, tag))
@@ -2326,6 +2332,8 @@ parser with neither. "grammar" must be provided.
                        code = s->code;
                else if (text_is(sec, "grammar"))
                        gram = s->code;
+               else if (text_is(sec, "reduce"))
+                       pre_reduce = s->code;
                else {
                        fprintf(stderr, "Unknown content section: %.*s\n",
                                s->section.len, s->section.txt);
@@ -2397,7 +2405,7 @@ file with the code section (if any) and the parser tables and function.
                if (f) {
                        if (code)
                                code_node_print(f, code, infile);
-                       gen_parser(f, g, infile, name);
+                       gen_parser(f, g, infile, name, pre_reduce);
                        fclose(f);
                } else {
                        fprintf(stderr, "Cannot create %s.c\n",