C# LR(1)语法分析器代码解析
C# LR(1)语法分析器代码解析
本文将详细分析两段C#代码,它们共同实现了一个LR(1)语法分析器。
代码1:button4_Click 事件处理函数c#private void button4_Click(object sender, EventArgs e){ step = 0;//单步计数置零 lr = new LR();
listView1.Columns.Clear(); listView1.Items.Clear(); listView1.View = View.Details;
// 添加第一列 listView1.Columns.Add('状态', 150); listView1.Columns.Add('项目族信息', 350);
lr.Buildprod(richTextBox1.Text);//调用
for (int i = 0; i < lr.proitemset.Count; i++)//输出 { ListViewItem li = new ListViewItem(); li.SubItems.Clear(); li.SubItems[0].Text = i.ToString(); string tempstr = ''; for (int j = 0; j < lr.proitemset[i].Container.Count; j++) { tempstr += lr.LRobjNum[lr.proitemset[i].Container[j]].Left + '->' + lr.LRobjNum[lr.proitemset[i].Container[j]].Right + ' '; } li.SubItems.Add(tempstr); listView1.Items.Add(li); } listView1.GridLines = true;}
这段代码定义了一个名为 button4_Click 的私有方法,该方法在点击名为 button4 的按钮时被调用。
- 首先,代码初始化了两个变量:
step被设置为 0,表示单步计数清零;lr被实例化为一个新的LR对象,用于进行 LR(1) 语法分析。* 接下来,代码清空了名为listView1的列表视图控件,并将其视图模式设置为View.Details,准备用于显示分析结果。* 然后,代码向listView1中添加了两列,分别用于显示 '状态' 和 '项目族信息',并调用lr对象的Buildprod方法,将名为richTextBox1的富文本框中的文本作为参数传入。*Buildprod方法的主要功能是根据传入的文法规则构建 LR(1) 分析表,其具体实现将在代码2中进行分析。* 最后,代码遍历lr.proitemset列表,将每个项目集的信息添加到listView1中,并设置listView1的网格线可见。
代码2:Buildprod 方法c#public void Buildprod(string str){ LRNode Lr; int i = 0; string left = ''; string right = ''; left += 'S''; right += str[0]; Lr = new LRNode(left, right);//拓广文法开始 LRproNum.Add(Lr); while (i < str.Length) { left = right = '';//还原 int j = i; while (i < str.Length && str[i] != ' ' && str[i] != ' ')//换行符‘ ’ { if (str[i] == ' ') { i++; continue; } if (str[i] == '|') // 遇到“|”可构造一条产生式 { Lr = new LRNode(left, right); LRproNum.Add(Lr); right = ''; //产生式左边相同 右边重新积累 i++; //跳过“|” continue; } if ((i - j) == 0) { if (!exist(Nchar, str[i]))//如果非终结符集合中不存在str[i],加入Nchar 产生式左边 只有非终结符 不必判断终结符 Nchar.Add(str[i]); left += str[i++]; } else if (i - j <= 2) i++; else { if (isFinalsymbol(str[i]) && !exist(Nchar, str[i]))//如果非终结符集合中不存在str[i],加入Nchar isfinalsymbol 非终结符返回T 终结符返回F Nchar.Add(str[i]); else if (!isFinalsymbol(str[i]) && !exist(Echar, str[i]))//产生式右边 需要判断终结符 Echar.Add(str[i]); right += str[i++]; }
}//while
i++;//跳过换行符 if (left != '' && right != '') { Lr = new LRNode(left, right);//构造每一行最后一个产生式,不存在'|'时就是该行产生式本身 LRproNum.Add(Lr); } }//while Echar.Add('#');
//构造项目 对产生式集合LRproNum中的所有产生式都循环插'.' LRNode Lobj; for (i = 0; i < LRproNum.Count; i++) { left = ''; right = ''; for (int j = 0; j <= LRproNum[i].Right.Length; j++)//j可以等于length 项目共length+1个 { left = LRproNum[i].Left; right = CreObj(LRproNum[i].Right, j);//在第j个位置插入'.' if (j == LRproNum[i].Right.Length && LRobjNum.Count != 1) {//在产生式最后的位置插入. 即为归约项目 项目集中1号位置为接受项目 Gy_obj.Add(LRobjNum.Count);//归约项目在项目集中的序号 不用+1 本身就是从0开始的 } Lobj = new LRNode(left, right); LRobjNum.Add(Lobj); left = '';//还原 right = ''; } } Creteitemsets();//项目集 RStr_obitemset += '
项目集构建: '; for (int j = 0; j < proitemset.Count; j++) { RStr_obitemset += 'I' + j.ToString() + ':' + ' '; for (i = 0; i < proitemset[j].Container.Count; i++) { RStr_obitemset += LRobjNum[proitemset[j].Container[i]].Left.ToString() + '->' + LRobjNum[proitemset[j].Container[i]].Right.ToString() + ' '; } } //return RStr_obitemset;
原文地址: https://www.cveoy.top/t/topic/fZVL 著作权归作者所有。请勿转载和采集!