在语法树中解释执行Goto语句

解释执行含有goto语句的语法树是相当麻烦的。

当遇到goto节点时,要抛出goto的目标节点。然后逐级向语法树上游回溯,每回溯一层,又要向下扫描这一层除抛出goto的节点以外的语句。如果找到目标节点,则清除这个label,从这个点恢复执行语法树。否则继续抛出goto。这里还有两种情况,因为下层的语句有可能已经执行过了,然而在执行过程中又抛出了goto。所以还需判断返回的goto是否和传入的goto相同。如果不同,那么前面被排除的抛出goto的分支再排除已经是不对的了,要重新加回去扫描。

在搜寻goto 目标时,所有的语句都“不执行”。不管是条件语句,循环语句,还是复合语句,都被同样的对待。这时,条件控制逻辑不起作用。直到回溯返回值告知goto已经被解除时,才从当前层下一条语句恢复解释执行。当然这是恢复语法树的下一条语句,而不是解释程序的下一条语句。

如此,解释程序的这部分代码是非常复杂的。里面充满了平时难以得见的奇怪的goto语句,如果想用结构化语句来表达会很难很难,对绝大多数程序员来说,这基本上是妄想。所以简单的说一句“我不用goto语句”,真的很无知,只能说明“我”从来没有做过复杂一点的东西。

相应的代码看起来是这样的:


struct node *execute_e_ls(struct node *s, struct node *label, int *exception)
{
    
    
        int i;
        struct node *res;
        struct node *disable;
        struct exprval val;

        if (!s) return NULL;
        disable = NULL;
        if (s == label) {
    
    
                label = NULL;
        }
        if (label) goto locate_label;

        switch(s->node_type) {
    
    
        case NT_EMPTYS:
                return NULL;
        case NT_AS:
                e_eval(s->left,exception); EXCEPTION_CHK;
                return NULL;
        case NT_PS:
                do_e_print_op(s->left, exception); EXCEPTION_CHK;
                printf("\n");
                return NULL;
        case NT_IFS:
                restart_ifs:
                val = e_eval(s->left,exception); EXCEPTION_CHK;
                if (val.u.value) {
    
    
                        res = execute_e_ls(s->medium, 0,exception);
                        EXCEPTION_CHK;
                        if (res==&throw_goto && throw_goto.medium==s) {
    
    
                                goto restart_ifs;
                        }
                        return  res;
                }
                return NULL;
        case NT_IFSES:
                restart_ifses:
                val = e_eval(s->left,exception); EXCEPTION_CHK;
                if (val.u.value) {
    
    
                        res = execute_e_ls(s->medium, 0,exception);
                        EXCEPTION_CHK;
                        if (res==&throw_goto) {
    
    
                                if (throw_goto.medium==s) {
    
    
                                        goto restart_ifses;
                                }
                                label = throw_goto.medium;
                                disable = s->medium;
                                goto locate_ifses2;
                        }
                }
                else {
    
    
                        res = execute_e_ls(s->right, 0,exception);
                        EXCEPTION_CHK;
                        if (res==&throw_goto) {
    
    
                                if (throw_goto.medium==s) {
    
    
                                        goto restart_ifses;
                                }
                                label = throw_goto.medium;
                                disable = s->right;
                                goto locate_ifses1;
                        }
                }
                return res;
        case NT_WS:
                restart_ws:
                val = e_eval(s->left,exception); EXCEPTION_CHK;
                while (val.u.value) {
    
    
                        res = execute_e_ls(s->medium, 0,exception);
                        EXCEPTION_CHK;
                enable_ws:
                        if (res == &node_return) {
    
    
                                return res;
                        }
                        if (res == &node_break) {
    
    
                                break;
                        }
                        if (res == &throw_goto) {
    
    
                                if (throw_goto.medium==s) {
    
    
                                        goto restart_ws;
                                }
                                return res;
                        }
                        val = e_eval(s->left,exception); EXCEPTION_CHK;
                }
                return NULL;
        case NT_FS:
                restart_fs:
                if(s->left->left) {
    
    
                        e_eval(s->left->left,exception); EXCEPTION_CHK;
                }
                val = e_eval(s->left->medium,exception); EXCEPTION_CHK;
                while (val.u.value!=0) {
    
    
                        res = execute_e_ls(s->medium, 0,exception);
                        EXCEPTION_CHK;
                enable_fs:
                        if (res == &node_return) {
    
    
                                return res;
                        }
                        if (res == &node_break) {
    
    
                                break;
                        }
                        if (res == &throw_goto) {
    
    
                                if (throw_goto.medium==s) {
    
    
                                        goto restart_fs;
                                }
                                return res;
                        }
                        if(s->left->right) {
    
    
                                e_eval(s->left->right,exception); EXCEPTION_CHK;

                        }
                        val = e_eval(s->left->medium,exception); EXCEPTION_CHK;
                }
                return NULL;
        case NT_CSS:
                restart_css:
                if (s->left) {
    
    
                        res = execute_e_ls(s->left, 0,exception);
                        EXCEPTION_CHK;
                        if (res == &throw_goto) {
    
    
                                if (throw_goto.medium==s) {
    
    
                                        goto restart_css;
                                }
                                label= throw_goto.medium;
                                disable = s->left;
                                goto locate_css2;
                        }
                        if (res !=NULL) {
    
    
                                return  res;
                        }
                }
                enable_css:
                res = execute_e_ls(s->medium, 0,exception);
                EXCEPTION_CHK;
                if (res == &throw_goto) {
    
    
                        if (throw_goto.medium==s) {
    
    
                                goto restart_css;
                        }
                        label= throw_goto.medium;
                        disable = s->medium;
                        goto locate_css1;
                }
                return res;
        case NT_BS_BRK:
                return &node_break;
        case NT_BS_CONT:
                return &node_continue;
        case NT_BS_RET:
                val = e_eval(s->left,exception); EXCEPTION_CHK;
                stk->e[top].ret = val;
                return &node_return;

        case NT_INITVS:
                i = (int) s->left;
                e_initv(i, s->right, exception); EXCEPTION_CHK;
                return NULL;

        case NT_GOTO:
                i = (int) s->left;
                throw_goto.medium = stk->e[top].func->labeltab[i];
                if (throw_goto.medium== s) {
    
    
                        printf("dead loop\n");
                        *exception=1; goto exception_out;
                }
                return &throw_goto;
        }


locate_label:
        switch (s->node_type) {
    
    
        case NT_IFS:
                res = execute_e_ls(s->medium, label,exception);
                EXCEPTION_CHK;
                if (res == &throw_goto &&throw_goto.medium==s) {
    
    
                        label = NULL;
                        goto restart_ifs;
                }
                return  res;
        case NT_IFSES:
                locate_ifses1:
                res = execute_e_ls(s->medium, label,exception);
                EXCEPTION_CHK;
                if (res == &throw_goto &&throw_goto.medium==s) {
    
    
                        label = NULL;
                        goto restart_ifses;
                }
                locate_ifses2:
                if (res == &throw_goto && throw_goto.medium != label) {
    
    
                        label = throw_goto.medium;
                        disable = s->medium;
                }
                if (res == &throw_goto &&s->right!=disable) {
    
    
                        res = execute_e_ls(s->right, label,exception);
                        EXCEPTION_CHK;
                        if (res == &throw_goto) {
    
    
                                if (throw_goto.medium==s) {
    
    
                                        label = NULL;
                                        goto restart_ifses;
                                }
                                if (throw_goto.medium != label) {
    
    
                                        label = throw_goto.medium;
                                        disable = s->right;
                                        goto locate_ifses1;
                                }
                        }
                }
                return res;
        case NT_WS:
                res = execute_e_ls(s->medium, label,exception);
                EXCEPTION_CHK;
                if (res!= &throw_goto) {
    
    
                        label == NULL;
                        goto enable_ws;
                }
                else if (throw_goto.medium==s) {
    
    
                        label == NULL;
                        goto restart_ws;
                }
                return res;
        case NT_FS:
                res = execute_e_ls(s->medium, label,exception);
                EXCEPTION_CHK;
                if (res!= &throw_goto) {
    
    
                        label == NULL;
                        goto enable_fs;
                }
                else if (throw_goto.medium==s) {
    
    
                        label == NULL;
                        goto restart_fs;
                }
                return res;
        case NT_CSS:
                locate_css1:
                if (s->left) {
    
    
                        res = execute_e_ls(s->left, label,exception);
                        EXCEPTION_CHK;
                        if (res == &throw_goto) {
    
    
                                if (throw_goto.medium==s) {
    
    
                                        label == NULL;
                                        goto restart_css;
                                }
                                if (throw_goto.medium != label) {
    
    
                                        label = throw_goto.medium;
                                        disable = s->left;
                                }
                        }
                        else if (res==NULL) {
    
    
                                label = NULL;
                                goto enable_css;
                        }
                        else return res;
                }
                locate_css2:
                if (s->medium != disable) {
    
    
                        res = execute_e_ls(s->medium, label,exception);
                        EXCEPTION_CHK;
                        if (res == &throw_goto) {
    
    
                                if (throw_goto.medium==s) {
    
    
                                        label == NULL;
                                        goto restart_css;
                                }
                                if (throw_goto.medium != label) {
    
    
                                        label = throw_goto.medium;
                                        disable = s->medium;
                                        goto locate_css1;
                                }
                        }
                }
                return res;

        default:
                return &throw_goto;
        }

exception_out:
        return NULL;
}


おすすめ

転載: blog.csdn.net/aaasssdddd96/article/details/114741588