⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pl0.c

📁 C语言编写的PLO源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    int i, cx1, cx2;
    bool nxtlev[symnum];

    if (sym == ident)   /* 准备按照赋值语句处理 */
    {
        i = position(id, *ptx);
        if (i == 0)
    	{
            error(11);  /* 变量未找到 */
    	}
        else
    	{
            if(table[i].kind != variable)
    		{
                error(12);  /* 赋值语句格式错误 */
            	i = 0;
    		}
        	else
    		{
                getsymdo;
                if(sym == becomes)  // becomes为冒号等于
        		{
                	getsymdo;
        		}
        		else
        		{
                    error(13);  /* 没有检测到赋值符号 */
        		}
                memcpy(nxtlev, fsys, sizeof(bool)*symnum);
                expressiondo(nxtlev, ptx, lev); /* 处理赋值符号右侧表达式 */
                if(i != 0)
        		{
                    /* expression将执行一系列指令,但最终结果将会保存在栈顶,执行sto命令完成赋值 */
                    gendo(sto, lev-table[i].level, table[i].adr);
        		}
    		}
        }//if (i == 0)
    }
    else
    {
        if (sym == readsym) /* 准备按照read语句处理 */
    	{
            getsymdo;
            if (sym != lparen)   //lparen为左括号
    		{
                error(34);  /* 格式错误,应是左括号 */
    		}
        	else
    		{
        		do {
                	getsymdo;
                    if (sym == ident)
        			{
                        i = position(id, *ptx); /* 查找要读的变量 */
        			}
            		else
        			{
            			i=0;
        			}

                	if (i == 0)
        			{
                        error(35);  /* read()中应是声明过的变量名 */
        			}
                    else if (table[i].kind != variable)
        			{
                        error(32);  /* read()参数表的标识符不是变量 */
        			}
            		else
        			{
                        gendo(opr, 0, 16);  /* 生成输入指令,读取值到栈顶 */
                        gendo(sto, lev-table[i].level, table[i].adr);   /* 储存到变量 */
        			}
                	getsymdo;

                } while (sym == comma); /* 一条read语句可读多个变量,comma为逗号 */
    		}
            if(sym != rparen)
    		{
                error(33);  /* 格式错误,应是右括号 */
                while (!inset(sym, fsys))   /* 出错补救,直到收到上层函数的后跟符号 */
        		{
                	getsymdo;
        		}
    		}
        	else
    		{
                getsymdo;
    		}
    	}
        else
    	{
            if (sym == writesym)    /* 准备按照write语句处理,与read类似 */
    		{
                getsymdo;
                if (sym == lparen)
        		{
            		do {
                		getsymdo;
                        memcpy(nxtlev, fsys, sizeof(bool)*symnum);
                        nxtlev[rparen] = true;
                        nxtlev[comma] = true;       /* write的后继符号为) or , */
                        expressiondo(nxtlev, ptx, lev); /* 调用表达式处理,此处与read不同,read为给变量赋值 */
                        gendo(opr, 0, 14);  /* 生成输出指令,输出栈顶的值 */
                    } while (sym == comma);
                    if (sym != rparen)
        			{
                        error(33);  /* write()中应为完整表达式 */
        			}
            		else
        			{
                		getsymdo;
        			}
        		}
                gendo(opr, 0, 15);  /* 输出换行 */
    		}
        	else
    		{
                if (sym == callsym) /* 准备按照call语句处理 */
        		{
                	getsymdo;
                    if (sym != ident)
        			{
                        error(14);  /* call后应为标识符 */
        			}
            		else
        			{
                        i = position(id, *ptx);
                    	if (i == 0)
        				{
                            error(11);  /* 过程未找到 */
        				}
            			else
        				{
                            if (table[i].kind == procedur)
        					{
                                gendo(cal, lev-table[i].level, table[i].adr);   /* 生成call指令 */
        					}
            				else
        					{
                                error(15);  /* call后标识符应为过程 */
        					}
        				}
                		getsymdo;
        			}
        		}
        		else
        		{
                    if (sym == ifsym)   /* 准备按照if语句处理 */
        			{
                		getsymdo;
                        memcpy(nxtlev, fsys, sizeof(bool)*symnum);
                        nxtlev[thensym] = true;
                        nxtlev[dosym] = true;   /* 后跟符号为then或do */
                        conditiondo(nxtlev, ptx, lev); /* 调用条件处理(逻辑运算)函数 */
                        if (sym == thensym)
        				{
                			getsymdo;
        				}
            			else
        				{
                            error(16);  /* 缺少then */
        				}
                        cx1 = cx;   /* 保存当前指令地址 */
                        gendo(jpc, 0, 0);   /* 生成条件跳转指令,跳转地址未知,暂时写0 */
                        statementdo(fsys, ptx, lev);    /* 处理then后的语句 */
                        code[cx1].a = cx;   /* 经statement处理后,cx为then后语句执行完的位置,它正是前面未定的跳转地址 */
        			}
            		else
        			{
                        if (sym == beginsym)    /* 准备按照复合语句处理 */
        				{
                			getsymdo;
                            memcpy(nxtlev, fsys, sizeof(bool)*symnum);
                            nxtlev[semicolon] = true;
                            nxtlev[endsym] = true;  /* 后跟符号为分号或end */
                            /* 循环调用语句处理函数,直到下一个符号不是语句开始符号或收到end */
                            statementdo(nxtlev, ptx, lev);

                            while (inset(sym, statbegsys) || sym==semicolon)
        					{
                                if (sym == semicolon)
            					{
                    				getsymdo;
            					}
            					else
            					{
                                    error(10);  /* 缺少分号 */
            					}
                                statementdo(nxtlev, ptx, lev);
        					}
                        	if(sym == endsym)
        					{
                    			getsymdo;
        					}
            				else
        					{
                                error(17);  /* 缺少end或分号 */
        					}
        				}
            			else
        				{
                            if (sym == whilesym)    /* 准备按照while语句处理 */
        					{
                                cx1 = cx;   /* 保存判断条件操作的位置 */
                    			getsymdo;
                                memcpy(nxtlev, fsys, sizeof(bool)*symnum);
                                nxtlev[dosym] = true;   /* 后跟符号为do */
                                conditiondo(nxtlev, ptx, lev);  /* 调用条件处理 */
                                cx2 = cx;   /* 保存循环体的结束的下一个位置 */
                                gendo(jpc, 0, 0);   /* 生成条件跳转,但跳出循环的地址未知 */
                            	if (sym == dosym)
            					{
                    				getsymdo;
            					}
            					else
            					{
                                    error(18);  /* 缺少do */
            					}
                                statementdo(fsys, ptx, lev);    /* 循环体 */
                                gendo(jmp, 0, cx1); /* 回头重新判断条件 */
                                code[cx2].a = cx;   /* 反填跳出循环的地址,与if类似 */
        					}
            				else
        					{
                                memset(nxtlev, 0, sizeof(bool)*symnum); /* 语句结束无补救集合 */
                                testdo(fsys, nxtlev, 19);   /* 检测语句结束的正确性 */
        					}
        				}
        			}
        		}
    		}
    	}
    }
    return 0;
}

/*
* 表达式处理
*/
int expression(bool* fsys, int* ptx, int lev)
{
    enum symbol addop;  /* 用于保存正负号 */
    bool nxtlev[symnum];

    if(sym==plus || sym==minus) /* 开头的正负号,此时当前表达式被看作一个正的或负的项 */
    {
        addop = sym;    /* 保存开头的正负号 */
        getsymdo;
        memcpy(nxtlev, fsys, sizeof(bool)*symnum);
        nxtlev[plus] = true;
        nxtlev[minus] = true;
        termdo(nxtlev, ptx, lev);   /* 处理项 */
        if (addop == minus)
    	{
            gendo(opr,0,1); /* 如果开头为负号生成取负指令 */
    	}
    }
    else    /* 此时表达式被看作项的加减 */
    {
        memcpy(nxtlev, fsys, sizeof(bool)*symnum);
        nxtlev[plus] = true;
        nxtlev[minus] = true;
        termdo(nxtlev, ptx, lev);   /* 处理项 */
    }
    while (sym==plus || sym==minus)
    {
        addop = sym;
        getsymdo;
        memcpy(nxtlev, fsys, sizeof(bool)*symnum);
        nxtlev[plus] = true;
        nxtlev[minus] = true;
        termdo(nxtlev, ptx, lev);   /* 处理项 */
        if (addop == plus)
    	{
            gendo(opr, 0, 2);   /* 生成加法指令 */
    	}
        else
    	{
            gendo(opr, 0, 3);   /* 生成减法指令 */
    	}
    }
    return 0;
}

/*
* 项处理
*/
int term(bool* fsys, int* ptx, int lev)
{
    enum symbol mulop;  /* 用于保存乘除法符号 */
    bool nxtlev[symnum];

    memcpy(nxtlev, fsys, sizeof(bool)*symnum);
    nxtlev[times] = true;
    nxtlev[slash] = true;
    factordo(nxtlev, ptx, lev); /* 处理因子 */
    while(sym==times || sym==slash)
    {
        mulop = sym;
        getsymdo;
        factordo(nxtlev, ptx, lev);
        if(mulop == times)
    	{
            gendo(opr, 0, 4);   /* 生成乘法指令 */
    	}
        else
    	{
            gendo(opr, 0, 5);   /* 生成除法指令 */
    	}
    }
    return 0;
}

/*
* 因子处理
*/
int factor(bool* fsys, int* ptx, int lev)
{
    int i;
    bool nxtlev[symnum];
    testdo(facbegsys, fsys, 24);    /* 检测因子的开始符号 */
    /* while(inset(sym, facbegsys)) */  /* 循环直到不是因子开始符号 */
    if(inset(sym,facbegsys))    /* BUG: 原来的方法var1(var2+var3)会被错误识别为因子 */
    {
        if(sym == ident)    /* 因子为常量或变量 */
    	{
            i = position(id, *ptx); /* 查找名字 */
            if (i == 0)
    		{
                error(11);  /* 标识符未声明 */
    		}
        	else
    		{
                switch (table[i].kind)
        		{
                case constant:  /* 名字为常量 */
                    gendo(lit, 0, table[i].val);    /* 直接把常量的值入栈 */
            		break;
                case variable:  /* 名字为变量 */
                    gendo(lod, lev-table[i].level, table[i].adr);   /* 找到变量地址并将其值入栈 */
            		break;
                case procedur:  /* 名字为过程 */
                    error(21);  /* 不能为过程 */
            		break;
        		}
    		}
            getsymdo;
    	}
        else
    	{
            if(sym == number)   /* 因子为数 */
    		{
                if (num > amax)
        		{
                	error(31);
                	num = 0;
        		}
                gendo(lit, 0, num);
                getsymdo;
    		}
        	else
    		{
                if (sym == lparen)  /* 因子为表达式 */
        		{
                	getsymdo;
                    memcpy(nxtlev, fsys, sizeof(bool)*symnum);
                    nxtlev[rparen] = true;
                    expressiondo(nxtlev, ptx, lev);
                    if (sym == rparen)
        			{
                		getsymdo;
        			}
            		else
        			{
                        error(22);  /* 缺少右括号 */
        			}
        		}
                testdo(fsys, facbegsys, 23);    /* 因子后有非法符号 */
    		}
    	}
    }
    return 0;
}

/*
* 条件处理
*/
int condition(bool* fsys, int* ptx, int lev)
{
    enum symbol relop;
    bool nxtlev[symnum];

    if(sym == oddsym)   /* 准备按照odd运算处理 */
    {
        getsymdo;
        expressiondo(fsys, ptx, lev);
        gendo(opr, 0, 6);   /* 生成odd指令 */
    }
    else
    {
        /* 逻辑表达式处理 */
        memcpy(nxtlev, fsys, sizeof(bool)*symnum);
        nxtlev[eql] = true;
        nxtlev[neq] = true;
        nxtlev[lss] = true;
        nxtlev[leq] = true;
        nxtlev[gtr] = true;
        nxtlev[geq] = true;
        expressiondo(nxtlev, ptx, lev);
        if (sym!=eql && sym!=neq && sym!=lss && sym!=leq && sym!=gtr && sym!=geq)
    	{
            error(20);
    	}
        else
    	{
            relop = sym;
            getsymdo;
            expressiondo(fsys, ptx, lev);
            switch (relop)
    		{
            case eql:
                gendo(opr, 0, 8);
            	break;
            case neq:
                gendo(opr, 0, 9);
            	break;
            case lss:
                gendo(opr, 0, 10);
            	break;
            case geq:
                gendo(opr, 0, 11);
            	break;
            case gtr:
                gendo(opr, 0, 12);
            	break;
            case leq:
                gendo(opr, 0, 13);
            	break;
    		}
    	}
    }
    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -