private void button1_Click(object sender, EventArgs e) { String phrase = ""; String error = ""; //词法分析 c.fenxi(textBox1.Text, out phrase, out error); textBox2.Text = phrase; //词法分析结果 textBox4.Text = "词法分析错误:\r\n"; textBox4.Text += error; //出现的错误 //Console.WriteLine(phrase); //句法分析 JFFX j = new JFFX(); String sen = ""; j.fenxi(phrase, out sen, out error); textBox3.Text = sen; textBox4.Text += "\r\n语法分析错误:\r\n"; textBox4.Text += error; //中间代码 textBox5.Text = YYFX.yuyi; textBox5.Text += (YYFX.line + 1) + "\tend\r\n";//输出end 终结语义分析 //符号表 this.dataGridView1.Rows.Clear(); Hashtable fuhaobiao = YYFX.fuhaoBiao; foreach (DictionaryEntry d in fuhaobiao) { FuHao fuhao = (FuHao)d.Value; int index = this.dataGridView1.Rows.Add(); this.dataGridView1.Rows[index].Cells[0].Value = fuhao.name; this.dataGridView1.Rows[index].Cells[1].Value = fuhao.width; this.dataGridView1.Rows[index].Cells[2].Value = fuhao.offset; this.dataGridView1.Rows[index].Cells[3].Value = fuhao.leixin; } dataGridView1.Sort(dataGridView1.Columns[2], ListSortDirection.Ascending); }
//调用语义子程序的函数,在语法分析时同步调用,即可边进行语法分析,边得到语义分析结果 //i 得到具体要调用哪个语义子程序 //n 调用时变量等的值 //行号,报错时会用到 public static void run(int i, String n, string el) { switch (i) { case 1: //由于主函数以及其他函数比较特殊,涉及到int main,main是一个标识符,但却不需要进行语义分析。所以将其类型赋值为特殊 zxin = "teshu"; zw = 3; break; case 2: name = n; //a.value,将函数中的函数名,即一个标识符赋值给name变量 break; case 3: //char bxin = "char"; w = 1; //变量宽度为1 break; case 4: //double bxin = "double"; w = 8; //变量宽度为8 break; case 5: //float bxin = "float"; w = 8; break; case 6: //int bxin = "int"; w = 4; break; case 7: //long bxin = "long"; w = 4; break; case 8: //short bxin = "short"; w = 4; break; case 9: //指针 zxin = "pointer( " + zxin + " )"; //类型是指针 zw = 4; //指针占多少字节 break; case 10: //数组 sxin = sxin.Replace(bxin, "array(" + int.Parse(n) + ", " + bxin + ")"); //敲定类型,int.Parse(n)是数组大小,bxin是数组类型 sw = int.Parse(n) * sw; //数组占多少个字节,即程序一开始要为数组分配多少内存;n的值就是数组[]内的值 // yuyi += "" + (++line) + "\t" + newTmp() + " = " + int.Parse(n) + "\r\n";// // yuyi += "" + (++line) + "\t" + newTmp() + " = " + shuZuName + "[" + getTmp(2) + "]\r\n";// // Console.WriteLine("Hello World!"); break; case 11: //数组 sxin = bxin; //数组的类型,int,char等 sw = w; //数组的宽度 break; case 12: //数组初始化,紧接11 xin = zxin.Replace("teshu", sxin); //确定类型,将得到的sxin替换teshu得到新属性 w = (4 - zw) * (sw - 3) + zw; //重新计算数组所占内存大小,zw为指针宽度,变量宽度=(4-指针宽度)*(数组宽度-3)+指针宽度;zw被初始化为3 if (fuhaoBiao[name] == null) //如果该数组在fuhaobiao中不存在,就将其添加至fuhaobiao中 { fuhaoBiao[name] = new FuHao(name, offset, xin, w); offset += w; } else //变量重复声明时报错 { w = 0; xin = ""; errIn += "line " + el + "\t变量 " + name + " 重复声明\r\n"; } break; case 13: //老规矩,不知道时就先用teshu替代 zxin = "teshu"; zw = 3; break; case 14: //已经知道到底是什么类型了,名称和所占的内存大小也知道了 name = n; //名称 sxin = bxin; //类型 sw = w; //位移,内存 break; case 15: xin = zxin.Replace("teshu", sxin); //找出真正的类型 w = (4 - zw) * (sw - 3) + zw; //计算一个这样的符号应占多少内存 if (fuhaoBiao[name] == null) { fuhaoBiao[name] = new FuHao(name, offset, xin, w); //将变量加入符号表中 offset += w; } else { w = 0; xin = ""; errIn += "line " + el + "\t变量 " + name + " 重复声明\r\n"; } break; case 16: //赋值语句,类似 t3 = 0 , a(这是个变量) = t3 yuyi += "" + (++line) + "\t" + fname + " = " + getTmp(1) + "\r\n"; break; case 17: //得到变量的名称 fname = name; break; case 18: //和17配套,作用同16 yuyi += "" + (++line) + "\t" + fname + " = " + getTmp(1) + "\r\n"; break; case 19: //例如,int a = 0;那么case 19就是t0 = 0,t0是一个临时变量 yuyi += "" + (++line) + "\t" + newTmp() + " = " + n + "\r\n"; break; case 20: //将表达式得到的一个临时变量重新赋给一个新的临时变量,如t5 = t3*t4,t6 = t5这里表达的就是t6=t5这一层含义 yuyi += "" + (++line) + "\t" + newTmp() + " = " + Tz + "\r\n"; break; case 21: Ez = Tz; // break; case 22: //加法减法 左部 Ez 右部 Tz yuyi += "" + (++line) + "\t" + newTmp() + " = " + Ez + " + " + Tz + "\r\n"; Tz = getTmp(1); break; case 23: Ez = Tz; break; case 24: yuyi += "" + (++line) + "\t" + newTmp() + " = " + Ez + " - " + Tz + "\r\n"; Tz = getTmp(1); break; case 25: Tz = Fz; break; case 26: //乘法操作前变量赋值 Rz = Fz; break; case 27: //乘法除法 的左部Rz,开始乘法操作 yuyi += "" + (++line) + "\t" + newTmp() + " = " + Rz + " * " + Fz + "\r\n"; Fz = getTmp(1); break; case 28: Rz = Fz; break; case 29: yuyi += "" + (++line) + "\t" + newTmp() + " = " + Rz + " / " + Fz + "\r\n"; Fz = getTmp(1); break; case 30: //四则表达式的值可能是int值 Fz = n; break; case 31: //四则表达式的值可能是float值 Fz = n; break; case 32: //将得到的表达式中各个部分的值压入堆栈备用 biaodashi.Push(Ez); biaodashi.Push(Tz); biaodashi.Push(Fz); biaodashi.Push(Rz); break; case 33: //使用堆栈中的变量,进行出栈操作 Tz = biaodashi.Pop(); Ez = biaodashi.Pop(); Rz = biaodashi.Pop(); Fz = biaodashi.Pop(); Fz = getTmp(1); break; case 34: //在不知道数组大小时先初始化为0 //wy = 0; sd = 0; break; case 35: //Fz = name; Fz = getTmp(1); break; case 36: biaodashi.Push(Ez); biaodashi.Push(Tz); biaodashi.Push(Fz); biaodashi.Push(Rz); //yuyi += "" + (++line) + "\t" + newTmp() + " = " + wy + "\r\n"; sd++; break; case 37: //使用数组 Rz = biaodashi.Pop(); Fz = biaodashi.Pop(); Tz = biaodashi.Pop(); Ez = biaodashi.Pop(); FuHao f = (FuHao)fuhaoBiao[shuZuName]; String [] s = f.leixin.Split(", ".ToCharArray()); //将数组类型分类出来,数组类型一般为array(5,int)这样 try { String ss = s[2 * sd - 2]; //一维就取出S[0],二维取出S[1],以此类推。 ss = ss.Substring(6, ss.Length - 6); nw = nw / int.Parse(ss); //数组总占内存数/数组的的元素总量即为当前每个元素所占的大小 yuyi += "" + (++line) + "\t" + newTmp() + " = " + getTmp(2) + " * " + nw + "\r\n"; if (sd > 1) //数组维数大于1维 { yuyi += "" + (++line) + "\t" + newTmp() + " = " + getTmp(2) + " + " + wy + "\r\n"; } wy = getTmp(1); } catch { nw = 0; errIn += "line " + el + "\t变量 " + shuZuName + " 数组引用错误\r\n"; } break; case 38: //假如符号表中没有该变量,就说明该变量是未声明就直接使用了,此时应输出异常 if (fuhaoBiao[n] == null) { errIn += "line " + el + "\t变量 " + name + " 没有声明即使用\r\n"; } shuZuName = n; nw = ((FuHao)fuhaoBiao[n]).width; //符号表中存储的一个该类型的符号所占内存大小 break; case 39: //if条件句,p代表判断条件,panduan yuyi += "" + (++line) + "\tif " + p + " goto " + (line + 2) + "\r\n"; yuyi += "" + (++line) + "\tgo1to Le \r\n"; break; case 40: //如果判断条件实效,和case 39配套 yuyi += "" + (++line) + "\tgo2to Lin \r\n"; break; case 41: //回填对应的行号 Le = "" + (line + 1); yuyi = yuyi.Replace("Le", Le); Lin = "" + (line + 1); yuyi = yuyi.Replace("Lin", Lin); break; case 42: //else语句块中语句的行号指示 Le = "" + (line + 1); yuyi = yuyi.Replace("Le", Le); Lin = "" + (line + 1); yuyi = yuyi.Replace("Lin", Lin); break; case 43: //while循环 yuyi += "" + (++line) + "\tif " + p + " goto " + (line + 2) + "\r\n"; //条件正确的话去那一行 yuyi += "" + (++line) + "\tgo3to We \r\n"; //条件错误的话去那一行 biaodashi.Push(wb); //将条件正确时跳转到的行号压入biaodashi栈留作后用 break; case 44: wb = biaodashi.Pop(); //弹出wb yuyi += "" + (++line) + "\tgoto " + wb + " \r\n"; //这是是真跳出循环,不加的话会顺序执行,所以必须要加 we = "" + (line + 1); yuyi = yuyi.Replace("We", we); //回填行号 break; case 45: //do while wb = "" + (line + 1); //找到条件正确时要跳转的行号 biaodashi.Push(wb); //压入栈留作备用 break; case 46: //do while wb = biaodashi.Pop(); yuyi += "" + (++line) + "\tif " + p + " goto " + wb + "\r\n"; //while()中的条件,正确的话跳转到wb break; case 47: //条件判断 p = "" + getTmp(1) + "!=0"; break; case 48: pq = getTmp(1); break; case 49: //最后得到的结果形如 p = t11<t10 p = pq + bj + getTmp(1); break; case 50: //比较符号 bj means比较,n代表具体的符号 bj = n; break; case 51: //比较 bj = n; break; case 52: //比较 bj = n; break; case 53: //比较 bj = n; break; case 54: //比较 bj = n; break; case 55: //比较 bj = n; break; case 56: //真正的else语句,接case40 Le = "" + (line + 1); yuyi = yuyi.Replace("Le", Le); //le才是真正else语句中的内容所对应的行号 break; case 57: //while循环 wb = "" + (line + 1); break; case 58: //变量,数组等一系列初始化的开始,现将变量名赋值给fname fname = name; break; case 59: if (sd > 0) //数组维数如果大于一维的话 { //wy代表数组的偏移 yuyi += "" + (++line) + "\t" + newTmp() + " = " + shuZuName + "[" + wy + "]" + "\r\n"; FuHao ff = (FuHao)fuhaoBiao[shuZuName]; String [] sss = ff.leixin.Split(", ".ToCharArray()); //举例,array[5,int] String ss22; try { ss22 = sss[2 * sd]; //得到数组类型,int或float } catch { errIn += "line " + el + "\t变量 " + shuZuName + " 引用错误\r\n"; return; } if (ss22.Substring(0, 3).Equals("int") || ss22.Substring(0, 5).Equals("float")) { } else { errIn += "line " + el + "\t变量 " + shuZuName + " 未引用到基本类型\r\n"; } } else { yuyi += "" + (++line) + "\t" + newTmp() + " = " + shuZuName + "\r\n"; } break; case 60: //将case 2中的IDN,即函数的名称赋值给hanshuname,原来的name是泛指,这里就变成特指函数名了 hanshuname = name; fhxin = zxin.Replace("teshu", bxin); canshuzu = ""; //此时还不知道具体的参数,暂且赋值为空 break; case 61: //类型未知时先赋值为teshu zxin = "teshu"; break; case 62: //数组的具体类型 sxin = bxin; break; case 63: //将原来的未知类型teshu替换成已知的数组类型 String canshu = zxin.Replace("teshu", sxin); if (canshuzu.Equals("")) //假如参数组中没有任何内容 { canshuzu = canshu; } else //否则的话,在原有内容的基础上加入新内容 { canshuzu = canshuzu + "X" + canshu; } break; case 64: if (fuhaoBiao[hanshuname] == null) { if (canshuzu.Equals("")) //如果参数组中没有任何值,就将其赋值为“空” { canshuzu = "空"; } fuhaoBiao[hanshuname] = new FuHao(hanshuname, offset, canshuzu + "->" + fhxin, 4); offset += 4; } else //出现错误 { errIn += "line " + el + "\t变量 " + name + " 重复声明\r\n"; } break; default: break; } }