LL(1)语法分析实验报告
- 格式:doc
- 大小:58.50 KB
- 文档页数:7
编译原理上机实验报告小组成员:王金名、周攀、汪国辉、澎湃、王帅、齐娟娟、刘鸳鸳一、实验目的:了解LL(1)文法分析的基本原理;提高上机实践能力;增强团队协作能力。
二、实验内容:通过LL1文法分析表分析任意一个符号串是否为某文法的句子;显示具体分析过程;打开、新建、保存分析表;保存分析结果三、实验原理:1.C#字符串处理及数组处理,这是本实验最强有力的工具;2.LL(1)文法分析的基本原理,详见教材P80 LL(1)分析器的总控算法;3.C#文件操作,C#常用控件使用。
四、实验步骤:1.构造应用程序框架,利用内置分析表实现分析符号串的最基础功能(1)使用Visual Studio 2005 新建C#语言环境的windows应用程序LL1GAnalysis;(2)将窗体的名称改成From_Main,相应的代码名称会随之更改;(3)添加texbox控件ID为textBox_input,添加listView控件,ID为listView_Result;(4)public partial class Form_Main : Form里面编写相应代码://全局变量const int Max = 100;public string[,] staticmTable ={{"","i","+","*","(",")","#"},{"S","<error>","<error>","<error>","S::=A","S::=A","<error>"},{"A","<error>","<error>","<error>","A::=BA\'","A::=BA\'","<error>"},{"A\'","A\'::=iBA\'","<error>","A\'::=ε","<error>","<error>","A\'::=ε"},{"B","<error>","<error>","<error>","B::=CB\'","B::=CB\'","<error>"},{"B\'","B\'::=ε","B\'::=+CB\'","B\'::=ε","<error>","<error>","B\'::=ε"},{"C","<error>","<error>","<error>","C::=(","C::=)A*","<error>"} };string[] VN = new string[Max]; int VNLength;string[] VT = new string[Max]; int VTLength;//以下是分析过程中要用到的公共函数public void addTolistView_Result(string step, string stack, string input, stringproduction)//分析步骤及结果显示(向listView中添加条目,并保存到string类型变量(analysisResult)作最终保存分析结果时使用{string strResultbuf = "";strResultbuf += step.PadRight(20, ' ');strResultbuf += stack.PadRight(20, ' ');strResultbuf += input.PadRight(20, ' ');strResultbuf += production.PadRight(20, ' ') + "\r\n";analysisResult += strResultbuf;ListViewItem li = new ListViewItem();li.Text = step;ListViewItem.ListViewSubItem ls = new ListViewItem.ListViewSubItem();ls.Text = stack;li.SubItems.Add(ls);ls = new ListViewItem.ListViewSubItem();ls.Text = input;li.SubItems.Add(ls);ls = new ListViewItem.ListViewSubItem();ls.Text = production;li.SubItems.Add(ls);listView_Result.Items.Add(li);}public void GetVN(string[,] table)//从分析表中获取非终结符{int i;for ( i = 1; i < table.GetLength(0);i++ ){VN[i-1] = table[i,0];}VNLength = i;}public void GetVT(string[,] table)//从分析表中获取终结符{int i;for (i = 1; i < table.GetLength(1); i++){VT[i-1] = table[0,i];}VTLength = i;}public int isVT(string str)//判断str是不是VT中的符号{int mark = 0;for (int i = 0; i < VTLength; i++){if (VT[i] == str){mark = 1;}}return mark;}public int isVN(string str)//判断str是不是VN中的符号{int mark = 0;for (int i = 0; i < VNLength; i++){if (VN[i] == str){mark = 1;}}return mark;}public string outStack(string[] Stack, int top)//栈内符号合并输出的时候用 {string str = "";for (int i = 0; i <= top; i++){str += Stack[i];}return str;}public void removeAllItems(ListView list)//清空listview Items{int itemcount = list.Items.Count;for (int i = itemcount; i > 0 ;i-- ){list.Items.RemoveAt(0);}}public string matchInTable(string[,] mt,string stacktop, string nowstr)//查表栈顶与ch 交叉处的标志并返回{int i,j;for (i = 0; i < mt.GetLength(0); i++ ){if (mt[i,0] == stacktop){break;}}for (j = 0; j < mt.GetLength(1);j++ ){if (mt[0,j] == nowstr){break;}}if (i < mt.GetLength(0)&&j<mt.GetLongLength(1)){return mt[i,j];}else{return"error! ";}}//以下是分析过程public void Start_Analysis(string[,] mTable)//开始分析并显示分析过程{tabControl_mTable.SelectTab(tabPage_Show);ShowmTable(mTable);removeAllItems(listView_Result);listView_Result.BeginUpdate();int top = -1; int step = 0;string[] Stack = new string[Max];string str = textBox_input.Text.Trim();//初始化GetVN(mTable); GetVT(mTable);top++; Stack[top] = "#";top++; Stack[top] = VN[0];str += "#";//分析while (true){if (isVT(Stack[top]) == 1)//Stack[top]是终结符,则比较栈顶符与当前符号{if (Stack[top] == str[0].ToString())//匹配当前符号{if (Stack[top] == "#")//ok{step++;addTolistView_Result(step.ToString(), outStack(Stack, top), str, "OK!");step = 0;break;}else//同时退栈{step++;addTolistView_Result(step.ToString(), outStack(Stack, top), str, ""); top--;str = str.Remove(0, 1);}}else//错误{step++;addTolistView_Result(step.ToString(), outStack(Stack, top), str,"Error!");break;}}else if (isVN(Stack[top]) == 1)//Stack[top]是非终结符,则查表{string production = matchInTable(mTable, Stack[top], str[0].ToString());if (production != "<error>"){step++;addTolistView_Result(step.ToString(), outStack(Stack, top), str, production);string probuf = "";if (production[1] == '\''){probuf = production.Remove(0, 5);}else{probuf = production.Remove(0, 4);}char[] chbuf = probuf.ToCharArray();int i = chbuf.Length - 1;string strbuf = "";Stack[top] = null;top--;while (i >= 0){if (chbuf[i] != 'ε'){if (chbuf[i] != '\''){top++;Stack[top] = strbuf.Insert(0, chbuf[i].ToString());strbuf = "";}else if (chbuf[i] == '\''){strbuf += strbuf.Insert(0, chbuf[i].ToString());}}else { break; }i--;}}else//错误production.Length != 0不在分析表中{step++;addTolistView_Result(step.ToString(), outStack(Stack, top), str, "Error!");break;}}else//错误非法字符{step++;addTolistView_Result(step.ToString(), "错误", str, "非法字符:" +str[0].ToString());break;}}//分析结束listView_Result.EndUpdate();}private void button_Start_Click(object sender, EventArgs e)//菜单及按钮开始分析(菜单项及开始按钮公用函数){string[,] mTable;if (radioButton_Staticmt.Checked){mTable = staticmTable;ShowmTable(mTable);Start_Analysis(mTable);}else if (radioButton_Createmt.Checked){if (created == 1){mTable = creamTable;ShowmTable(mTable);Start_Analysis(mTable);}else{MessageBox.Show("你还没有创建分析表,请先创建!", "错误提示",MessageBoxButtons.OK, MessageBoxIcon.Exclamation);}}else if (radioButton_Openmt.Checked){if (opened == 1){mTable = openmTable;ShowmTable(mTable);Start_Analysis(mTable);}else{MessageBox.Show("你还没有打开分析表,请先打开或创建!", "错误提示",MessageBoxButtons.OK, MessageBoxIcon.Exclamation);}}}2.实现显示分析表及新建分析表并利用该表分析句子的功能(1)添加tabControl控件ID为tabControl_mTable建立3个页面tabPage_Show显示当前分析表、tabPage_Edit新建分析表、tabPage_Open打开分析表(2)tabPage_Show中添加listView控件ID为listView_mtableshow用于显示分析表(3)tabPage_Edit中添加两个Button 控件ID分别为button_StartAdd开始添加、button_FilishAdd 完成添加;两个textBox控件ID分别为textBox_VT 、textBox_VN、分别用于获取要添加的终结符及非终结符个数;一个tableLayoutPanel控件ID为tableLayoutPanel_mTable用于根据用户输入的VT及VN的个数建立输入表(4)编辑相应代码:private void button_StartAdd_Click(object sender, EventArgs e)//新建分析表并开始输入{try{int conwidth,conheight,col, row;TextBox txb;tableLayoutPanel_mTable.Controls.Clear();conwidth = 50; conheight = 20;col = Convert.ToInt32(textBox_VT.Text)+1;row = Convert.ToInt32(textBox_VN.Text)+1;tableLayoutPanel_mTable.ColumnCount =col;tableLayoutPanel_mTable.RowCount = row;for (int i = 0; i < col;i++ ){for (int j = 0; j < row;j++ ){if (i == 0&&j==0){Label lb = new Label();lb.Text = "VN\\VT";lb.Width = conwidth;lb.ForeColor = Color.Red;tableLayoutPanel_mTable.Controls.Add(lb,i,j);}else{txb = new TextBox();txb.Width = conwidth;txb.Height = conheight;tableLayoutPanel_mTable.Controls.Add(txb,i,j);}}}}catch{MessageBox.Show("终结符或非终结符格式不对!\n请输入数字!","错误提示",MessageBoxButtons.OK, MessageBoxIcon.Exclamation);}}private void button_FilishAdd_Click(object sender, EventArgs e)//完成添加,更新分析表 {int col = tableLayoutPanel_mTable.ColumnCount;int row = tableLayoutPanel_mTable.RowCount;if (col > 1&&row>1){creamTable = new string[row, col];for (int i = 0; i < row; i++){for (int j = 0; j < row; j++){if (i == 0 && j == 0){creamTable[i, j] = "";}else{creamTable[i, j] =((TextBox)tableLayoutPanel_mTable.GetControlFromPosition(j, i)).Text.Trim();if (creamTable[i,j].Length == 0){creamTable[i, j] = "<error>";}}}}MessageBox.Show("成功更新分析表!");tabControl_mTable.SelectTab(tabPage_Show);radioButton_Createmt.Checked = true;created = 1;ShowmTable(creamTable);}else{MessageBox.Show("请先点击“开始添加”创建表格!","错误提示",MessageBoxButtons.OK, MessageBoxIcon.Exclamation);}}public void ShowmTable(string[,] mTable)//显示分析表{listView_mtableshow.Clear();ColumnHeader colHeader;ListViewItem lvi;ListViewItem.ListViewSubItem lvsi;for (int i = 1; i <= mTable.GetLength(1); i++){colHeader = new ColumnHeader();colHeader.Text = i.ToString();listView_mtableshow.Columns.Add(colHeader);}for (int i = 0; i < mTable.GetLength(0); i++){lvi = new ListViewItem();lvi.Text = mTable[i, 0];for (int j = 1; j < mTable.GetLength(1); j++){lvsi = new ListViewItem.ListViewSubItem();lvsi.Text = mTable[i, j];lvi.SubItems.Add(lvsi);}listView_mtableshow.Items.Add(lvi);}}private void miFileNew_Click(object sender, EventArgs e)//菜单新建分析表{tabControl_mTable.SelectTab(tabPage_Edit);}3.实现打开、保存分析表、保存分析结果的功能(1)添加主菜单menuStrip_Main两个Item:miFile文件、miGraAnylysis语法分析。
LL(1)语法分析设计原理与实现技术实验报告变更说明、实验目的:本实验的目的在于在教师的引导下以问题回朔与思维启发的方式, 使学生在不断的探究过程中掌握编译程序设计与构造的基本原理与实现技术, 启迪学生的抽象思维、激发学生的学习兴趣、培养学生的探究精神与专业素养, 从而提高学生发现问题、分析问题与解决问题的能力。
、实验内容[ 实验项目]实现LL(1)分析中控制程序(表驱动程序);完成以下描述算术表达式的LL(1)文法的LL(1)分析程序。
G[E]: E —TEE'—ATE | &T—F「T'—MFT | &F—(E)|iA—+|-M—*|/[ 实验说明]终结符号i 为用户定义的简单变量, 即标识符的定义。
[ 设计要求](1) 输入串应就是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果。
输出为输入串就是否为该文法定义的算术表达式的判断结果(2) LL(1) 分析过程应能发现输入串出错;(3) 设计两个测试用例(尽可能完备,正确与出错), 并给出测试结果。
三、实验环境操作系统:Windows 7 软件: VC++6、0四、程序功能描述提供了文件输入方式, 且输入的内容为二元式序列; 能够对输入的字符串做出正确的LL(1) 分析判断,并给出判断结果,判断结果输出到文件, 并显示在屏幕;能发现输入串中的错误,包含非法字符, 输入不匹配等; 能够处理一些可预见性的错误,如文件不存在, 输入非法等。
五、数据结构设计全局:MAX 50ch^r dn^lvseSt^cl<[MAX]; 丿/勺〜析丰戋char toRen[HAJ<]|; "匾人車typedef= struct CSS "严主式结构体<char loft;char Klgtlt[5];int rightlength;}CSS; _CSS E,G9G1,T9H,H1,F.F1P A,A1P M JI1 ;|CSS anali)5elable[7][8];局部(mai n()中):int nain()<C1 h 3 厂 a "int i=0,j = 0f ni,u=6(u=n;"i指示栈顶位貳j扌繇剩余串扫描位置Int num un,num ut;bool Flag=true;char tokenl[MAK];char t oken2[HAX];FILE *fpin,*fpout;六、程序结构描述设计方法:本程序采用从文件读取的输入方式,输入的内容需为二元式序列,然后按照LL(1)分析的方法对输入的字符串进行分析判断,并输出判断结果,程序通过对输入串的检查能够发现输入串中的错误。
国开电大编译原理实验4:语法分析实
验报告
1. 实验目的
本实验的目的是研究和掌握语法分析的原理和实现方法。
2. 实验内容
本次实验主要包括以下内容:
- 设计并实现自顶向下的LL(1)语法分析器;
- 通过语法分析器对给定的输入串进行分析,并输出相应的分析过程;
- 编写测试用例,验证语法分析器的正确性。
3. 实验步骤
3.1 设计LL(1)文法
首先,根据实验要求和给定的语法规则,设计LL(1)文法。
3.2 构建预测分析表
根据所设计的LL(1)文法,构建预测分析表。
3.3 实现LL(1)语法分析器
根据预测分析表,实现自顶向下的LL(1)语法分析器。
3.4 对输入串进行分析
编写程序,通过LL(1)语法分析器对给定的输入串进行分析,并输出相应的分析过程和结果。
3.5 验证语法分析器的正确性
设计多组测试用例,包括正确的语法串和错误的语法串,验证语法分析器的正确性和容错性。
4. 实验结果
经过实验,我们成功设计并实现了自顶向下的LL(1)语法分析器,并对给定的输入串进行了分析。
实验结果表明该语法分析器具有较好的准确性和容错性。
5. 实验总结
通过本次实验,我们对语法分析的原理和实现方法有了更深入的了解。
同时,我们也学会了如何设计并实现自顶向下的LL(1)语
法分析器,并验证了其正确性和容错性。
这对于进一步研究编译原理和深入理解编程语言的语法结构具有重要意义。
6. 参考资料
- 《编译原理与技术》
- 课程实验文档及代码。
北华航天工业学院《编译原理》课程实验报告课程实验题目:LL(1)语法分析实验作者所在系部:计算机科学与工程系作者所在专业:计算机科学与技术作者所在班级:xxx作者学号:xxxxx _ 作者姓名:xxxx指导教师姓名:xxxx完成时间:2011年4月28日一、实验目的理解预测分析表方法的实现原理。
二、实验内容及要求编写一通用的预测法分析程序,要求有一定的错误处理能力,出错后能够使程序继续运行下去,直到分析过程结束。
可通过不同的文法(通过数据表现)进行测试。
给定算术表达式文法,编写程序。
测试数据:1.算术表达式文法E→TE’E’→ +TE’|- TE’|εT→FT’T’→*FT’ |/ FT’ |%FT’|εF→(E) |id|num2.作业3.10 文法三、实验程序设计说明1.实验方案设计主要函数之间的调用关系如下图所示:2.程序源代码源代码如下:#include <iostream>#include <cstdio>#include <stack>using namespace std;struct Node1{ char vn;char vt;char s[10];}MAP[20];//存储分析预测表每个位置对应的终结符,非终结符,产生式int k;//用R代表E',W代表T',e代表空char start='E';int len=8;charG[10][10]={"E->TR","R->+TR","R->e","T->FW","W->*FW","W->e","F->(E)","F->i "};//存储文法中的产生式char VN[6]={'E','R','T','W','F'};//存储非终结符char VT[6]={'i','+','*','(',')','#'};//存储终结符char SELECT[10][10]={"(,i","+","),#","(,i","*","+,),#","(","i"};//存储文法中每个产生式对应的SELECT集char Right[10][8]={"->TR","->+TR","->e","->FW","->*FW","->e","->(E)","->i"}; //用R代表A',W代表B',e代表空/*char start='A';int len=6;char G[10][10]={"A->aR","R->ABl","R->e","B->dW","W->bW","W->e"};char VN[6]={'A','R','B','W'};char VT[6]={'a','d','b','#','l'};char SELECT[10][10]={"a","a","d,#","d","b","l"};char Right[10][6]={"->aR","->ABl","->e","->dW","->bW","->e"};*/stack <char> stak;bool compare(char *a,char *b){ int i,la=strlen(a),j,lb=strlen(b);for(i=0;i<la;i++)for(j=0;j<lb;j++){ if(a[i]==b[j])return 1; }return 0;}char *Find(char vn,char vt){ int i;for(i=0;i<k;i++){ if(MAP[i].vn==vn && MAP[i].vt==vt)return MAP[i].s;}return "error";}char * Analyse(char * word){ char p,action[10],output[10];int i=1,j,l=strlen(word),k=0,l_act,m;while(!stak.empty())stak.pop();stak.push('#');stak.push(start);printf("___________________________________________________________\n");printf("\n 对符号串%s的分析过程\n",word);printf(" -----------------------------------------------------------------------\n");printf("\n");printf(" 步骤栈顶元素剩余输入串动作\n");printf(" -----------------------------------------------------------------------\n");p=stak.top();while(p!='#'){ printf("%7d ",i++);p=stak.top();stak.pop();printf("%6c ",p);for(j=k,m=0;j<l;j++)output[m++]=word[j];output[m]='\0';printf("%10s",output);if(p==word[k]){ if(p=='#'){ printf(" 分析成功\n");return "SUCCESS";}printf(" 匹配终结符“%c”\n",p);k++;}else{ strcpy(action,Find(p,word[k]));if(strcmp(action,"error")==0){ printf(" 没有可用的产生式\n");return "ERROR"; }printf(" 展开非终结符%c%s\n",p,action);int l_act=strlen(action);if(action[l_act-1]=='e')continue;for(j=l_act-1;j>1;j--)stak.push(action[j]);}} if(strcmp(output,"#")!=0)return "ERROR";}int main (){ freopen("in1.txt","r",stdin);//freopen("in2.txt","r",stdin);char source[100];int i,j,flag,l,m;//printf("\n***为了方便编写程序,用R代表E',W代表T',e代表空*****\n\n");printf("\n****为了方便编写程序,用R代表A',W代表B',e代表空*****\n\n");printf("该文法的产生式如下:\n");for(i=0;i<len;i++)printf(" %s\n",G[i]);printf("___________________________________________________________\n");printf("\n该文法的SELECT集如下:\n");for(i=0;i<len;i++){ printf(" SELECT(%s) = { %s }\n",G[i],SELECT[i]); }printf("___________________________________________________________\n");//判断是否是LL(1)文法flag=1;for(i=0;i<8;i++){ for(j=i+1;j<8;j++){if(G[i][0]==G[j][0]){ if(compare(SELECT[i],SELECT[j])){flag=0;break;}}} if(j!=8)break; }if(flag)printf("\n有相同左部产生式的SELECT集合的交集为空,所以文法是LL(1)文法。
LL1语法分析程序实验报告实验目的:通过编写LL(1)语法分析程序,加深对语法分析原理的理解,掌握语法分析方法的实现过程,并验证所编写的程序的正确性。
实验准备:1.了解LL(1)语法分析的原理和步骤;2.根据语法规则,构建一个简单的文法;3.准备一组测试用例,包括符合语法规则的输入和不符合语法规则的输入。
实验步骤:1.根据文法规则,构建预测分析表;2.实现LL(1)语法分析程序;3.编写测试用例进行测试;4.分析测试结果。
实验结果:我根据上述步骤,编写了一个LL(1)语法分析程序,并进行了测试。
以下是我的测试结果:测试用例1:输入:9+7*(8-5)分析结果:成功测试用例2:输入:3+*5分析结果:失败测试用例3:输入:(3+5)*分析结果:失败测试用例4:输入:(3+5)*2+4分析结果:成功分析结果符合预期,说明我编写的LL(1)语法分析程序是正确的。
在测试用例1和测试用例4中,分析结果是成功的,而在测试用例2和测试用例3中,分析结果是失败的,这是因为输入不符合文法规则。
实验总结:通过本次实验,我进一步理解了LL(1)语法分析的原理和步骤。
编写LL(1)语法分析程序不仅要根据文法规则构建预测分析表,还要将预测分析表与输入串进行比对,根据匹配规则进行预测分析,最终得到分析结果。
在实验过程中,我发现在构建预测分析表和编写LL(1)语法分析程序时需要仔细思考和调试才能保证正确性。
通过本次实验,我对语法分析方法的实现过程有了更深入的认识,对于将来在编译原理方面的学习和工作有了更好的准备。
语法分析实验报告一: 实验内容:编写语法分析程序, 实现对算术表达式的语法分析, 要求所分析的算术表达式由如下的文法产生。
E->E+T|E-T|TT->T*F|T/F|FF->id|(E)|num二: 实验要求:在对表达式进行分析的同时, 输出所采用的产生式。
1.编写LL(1)语法分析程序, 要求:编程实现算法4.2, 为给定的文法自动构造预测分析表编程实现算法4.1, 构造LL(1)预测分析程序,2.编写语法分析程序, 实现自底向上的分析, 要求:构造识别所有活前缀的DFA构造LR分析表编程实现算法4.3, 构造LR分析程序1.三: 实验分析:2.方法二(编写LL(1)语法分析程序)1.步骤:(1)根据题目所给出的文法构造相应的无左递归文法, 并求出该文法各非终结符的FIRST、FOLLOW集合;(2)构造文法的LL(1)分析表;(3)由此构造LL分析程序。
2.实现方法:1.输入缓冲区为一个字符型数组, 读入输入的算术表达式并保存在此, 以’$’结束;2.为构造文法的LL(1)分析表, 构建一个相对应的字符串数组;3.在实际程序中P代表E', Q代表T', e代表ε,i代表id, n代表num;4.处理输入表达式中代表id和num的子串, 分别将它们转化为'i'和'n'进行分析;5.LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a做哪种过程的。
对于任何(X,a),总控程序每次都执行下述三种可能的动作之一:(1)若X = a =‘$’, 则宣布分析成功, 停止分析过程。
(2)若X = a!=‘$’, 则把X从STACK栈顶弹出, 让a指向下一个输入符号。
①如果是终结符合, 则栈不加入新符号②如果是非终结符合, 则把表达式右边入栈(3)若M[A, a]中存放着“出错标志”, 则调用出错诊断程序ERROR。
青岛科技大学LL(1)分析编译原理实验报告学生班级__________________________学生学号__________________________学生姓名________________________________年 ___月 ___日一、实验目的LL(1)分析法的基本思想是:自项向下分析时从左向右扫描输入串,分析过程中将采用最左推导,并且只需向右看一个符号就可决定如何推导。
通过对给定的文法构造预测分析表和实现某个符号串的分析,掌握LL(1)分析法的基本思想和实现过程。
二、实验要求设计一个给定的LL(1)分析表,输入一个句子,能根据LL(1)分析表输出与句子相应的语法数。
能对语法数生成过程进行模拟。
三、实验内容(1)给定表达式文法为:G(E’): E’→#E# E→E+T | T T→T*F |F F→(E)|i(2)分析的句子为:(i+i)*i四、模块流程五、程序代码#include<iostream>#include<stdio.h>#include <string>#include <stack>using namespace std;char Vt[]={'i','+','*','(',')','#'}; /*终结符*/char Vn[]={'E','e','T','t','F'}; /*非终结符*/ int LENVt=sizeof(Vt);void showstack(stack <char> st) //从栈底开始显示栈中的内容{int i,j;char ch[100];j=st.size();for(i=0;i<j;i++){ch[i]=st.top();st.pop();}for(i=j-1;i>=0;i--){cout<<ch[i];st.push(ch[i]);}}int find(char c,char array[],int n) //查找函数,返回布尔值{int i;int flag=0;for(i=0;i<n;i++){if(c==array[i])flag=1;}return flag;}int location(char c,char array[]) //定位函数,指出字符所在位置,即将字母转换为数组下标值{int i;for(i=0;c!=array[i];i++);return i;}void error(){cout<<" 出错!"<<endl;}void analyse(char Vn[],char Vt[],string M[5][6],string str){int i,j,p,q,h,flag=1;char a,X;stack <char> st; //定义堆栈st.push('#');st.push(Vn[0]); //#与识别符号入栈j=0; //j指向输入串的指针h=1;a=str[j];cout<<"步骤"<<"分析栈"<<"剩余输入串"<<" 所用产生式"<<endl;while(flag==1){cout<<h<<" "; //显示步骤h++;showstack(st); //显示分析栈中内容cout<<" ";for(i=j;i<str.size();i++) cout<<str[i]; //显示剩余字符串X=st.top(); //取栈顶符号放入X if(find(X,Vt,LENVt)==1) //X是终结符if(X==a) //分析栈的栈顶元素和剩余输入串的第一个元素相比较if (X!='#'){cout<<" "<<X<<"匹配"<<endl;st.pop();a=str[++j]; //读入输入串的下一字符}else{ cout<<" "<<"acc!"<<endl<<endl; flag=0;}else{error();break;}else{p=location(X,Vn); //实现下标的转换(非终结符转换为行下标)q=location(a,Vt); //实现下标的转换(终结符转换为列下标)string S1("NULL"),S2("null");if(M[p][q]==S1 || M[p][q]==S2) //查找二维数组中的产生式{error();break;} //对应项为空,则出错else{string str0=M[p][q];cout<<" "<<X<<"-->"<<str0<<endl; //显示对应的产生式st.pop();if(str0!="$") //$代表"空"字符for(i=str0.size()-1;i>=0;i--) st.push(str0[i]);//产生式右端逆序进栈}}}}main(){string M[5][6]={"Te" ,"NULL","NULL","Te", "NULL","NULL","NULL","+Te" ,"NULL","NULL","$", "$","Ft", "NULL","NULL","Ft", "NULL","NULL","NULL","$", "*Ft", "NULL","$", "$","i", "NULL","NULL","(E)", "NULL","NULL"}; //预测分析表j string str;int errflag,i;cout<<"文法:E->E+T|T T->T*F|F F->(E)|i"<<endl;cout<<"请输入分析串(以#结束):"<<endl;do{ errflag=0;cin>>str;for(i=0;i<str.size();i++)if(!find(str[i],Vt,LENVt)){ cout<<"输入串中包含有非终结符"<<str[i]<<"(输入错误)!"<<endl;errflag=1;}} while(errflag==1); //判断输入串的合法性analyse(Vn, Vt, M,str);return 0;}六、实验结果七、实验总结。
LL(1)语法分析器实验报告书小组负责人:潘豪 SWE08030小组成员:邹杰光 SWE08018叶凯翔 SWE08039张志峰 SWE08046许英俊 SWE08062厦门大学嘉庚学院计算机系软件工程班课程小组2010年7月目录第一章概述 (3)1.1 开发平台 (3)1.2 实验目的 (3)1.3 实验要求 (3)第二章语法分析器的实现 (3)2.1 LL(1)语法分析器原理 (3)2.2 求出能推出空的终结符 (4)2.3 FIRST集的确定 (4)2.4 FOLLOW集的确定 (4)2.5 SELECT集的确定 (4)2.6 LL(1)文法的判别 (4)2.7 逻辑结构 (4)2.8 预测分析表的生成 (5)2.9 句子的判定 (5)2.10 其他说明 (5)第三章系统运行与测试 (6)3.1 程序运行环境 (6)3.2 运行界面 (6)3.3 系统测试 (8)第四章总述 (11)4.1 程序综述 (11)4.2小组工作总结 (11)第一章概述1.1 开发平台本程序基于Microsoft Visual Studio 2008开发,使用C#语言。
1.2 实验目的掌握LL(1)分析法的基本原理,掌握LL(1)分析表的构造方法,掌握LL(1)驱动程序的构造方法。
1.3 实验要求编写一个语法分析器,不限语言,方法。
第二章语法分析器的实现2.1 LL(1)语法分析器原理语法分析是编译过程的核心部分,它的主要任务是按照程序的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行词法检查,为语义分析和代码生成作准备。
这里采用自顶向下的LL(1)分析方法。
语法分析程序的流程图如图5-4所示。
语法分析程序流程图2.2 求出能推出空的终结符见许英俊报告2.3 FIRST集的确定见邹杰光报告2.4 FOLLOW集的确定见张志峰报告2.5 SELECT集的确定见叶凯翔报告2.6 LL(1)文法的判别见叶凯翔报告2.7 逻辑结构一个LL(1)分析器由一张分析表、一个分析栈和一个总控程序组成。
LL(1)语法分析实验报告一、实验目的通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,检查语法错误,进一步掌握常用的语法分析方法。
二、实验内容构造LL(1)语法分析程序,任意输入一个文法符号串,并判断它是否为文法的一个句子。
程序要求为该文法构造预测分析表,并按照预测分析算法对输入串进行语法分析,判别程序是否符合已知的语法规则,如果不符合则输出错误信息。
消除递归前的文法消除递归后的等价文法E→E+T E→TE’E→T E’→+TE’|εT→T*F T→FT’T→F T’→*FT’|εF→(E)|i F→(E)|i根据已建立的分析表,对下列输入串:i+i*i进行语法分析,判断其是否符合文法。
三、实验要求1.根据已由的文法规则建立LL(1)分析表;2.输出分析过程。
请输入待分析的字符串: i+i*i符号栈输入串所用产生式#E i+i*i# E→TE’#E’T i+i*i# T→FT’#E’T’F i+i*i# F→i#E’T’i i+i*i##E’T’ +i*i# T’→ε#E’ +i*i# E’→+TE’#E’T+ +i*i##E’T i*i# T→FT’#E’T’F i*i# F→i#E’T’i i*i##E’T’ *i# T’→*FT’#E’T’F* *i##E’T’F i# F→i#E’T’i i##E’T’ # T’→ε#E’ # E’→ε# #四、程序思路模块结构:1、定义部分:定义常量、变量、数据结构。
2、初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体等);3、运行程序:让程序分析一个text文件,判断输入的字符串是否符合文法定义的规则;4、利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示简单的错误提示。
五、程序流程图输入要分析的串判断输入串是否正确判断分析句型是否完全匹配?成功失败否是是否八、程序调试与测试结果运行后结果如下:九、实验心得递归下降分析法是确定的自上而下分析法,这种分析法要求文法是LL(1)文法。
实验报告姓名:***学号:**********班级:惠普开发142学校:青岛科技大学Mail:电话:178****6475教师:宮生文实验报告:实验名称:LL(1)语法分析实验目的和要求编制一个能识别由词法分析给出的单词符号序列是否是给定文法的正确句子(程序),输出对输入符号串的分析过程。
实验内容和步骤:一、实验内容对于这个实验,总共用了三个函数,即主函数、输出分析栈函数、输出剩余串函数。
在主函数中,还要构造预测分析表。
二、实验步骤1、基于实验的内容,构造程序所需的模块2、根据已建构的模块,写出各个模块的相应程序代码3、在主函数中调用模块来完成所要得到的效果在本程序中,首先使用了结构体类型定义来定义产生式,用字符串数组存放分析栈、剩余串、终结符和非终结符,用二维数组存放预测分析表,利用指针对栈中数据进行读取。
在本程序中,总共用了三个函数,即主函数、输出分析栈函数、输出剩余串函数。
在主函数中,还要构造预测分析表,对输入的字符串进行分析,调用另外两个函数。
实验代码如下:#include<stdio.h>#include<stdlib.h>#include<string.h>#include<dos.h>char A[20];/*分析栈*/char B[20];/*剩余串*/char v1[20]={'i','+','*','(',')','#'};/*终结符*/char v2[20]={'E','G','T','S','F'};/*非终结符*/int j=0,b=0,top=0,l;/*L为输入串长度*/typedef struct type/*产生式类型定义*/{char origin;/*大写字符*/char array[5];/*产生式右边字符*/int length;/*字符个数*/}type;type e,t,g,g1,s,s1,f,f1;/*结构体变量*/type C[10][10];/*预测分析表*/void print()/*输出分析栈*/{int a;/*指针*/for(a=0;a<=top+1;a++)printf("%c",A[a]);printf("\t\t");}/*print*/void print1()/*输出剩余串*/{int j;for(j=0;j<b;j++)/*输出对齐符*/printf(" ");for(j=b;j<=l;j++)printf("%c",B[j]);printf("\t\t\t");}/*print1*/void main(){int m,n,k=0,flag=0,finish=0;char ch,x;type cha;/*用来接受C[m][n]*//*把文法产生式赋值结构体*/e.origin='E';strcpy(e.array,"TG");e.length=2;t.origin='T';strcpy(t.array,"FS");t.length=2;g.origin='G';strcpy(g.array,"+TG");g.length=3;g1.origin='G';g1.array[0]='^';g1.length=1;s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';s1.array[0]='^';s1.length=1;f.origin='F';strcpy(f.array,"(E)");f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++)/*初始化分析表*/for(n=0;n<=5;n++)C[m][n].origin='N';/*全部赋为空*//*填充分析表*/C[0][0]=e;C[0][3]=e;C[1][1]=g;C[1][4]=g1;C[1][5]=g1;C[2][0]=t;C[2][3]=t;C[3][1]=s1;C[3][2]=s;C[3][4]=C[3][5]=s1;C[4][0]=f1;C[4][3]=f;printf("提示:本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进行分析,\n"); printf("请输入要分析的字符串:");do/*读入分析串*/{scanf("%c",&ch);if ((ch!='i') &&(ch!='+') &&(ch!='*')&&(ch!='(')&&(ch!=')')&&(ch!='#')){printf("输入串中有非法字符\n");exit(1);}B[j]=ch;j++;}while(ch!='#');l=j;/*分析串长度*/ch=B[0];/*当前分析字符*/A[top]='#'; A[++top]='E';/*'#','E'进栈*/printf("步骤\t\t分析栈\t\t剩余字符\t\t所用产生式\n");do{x=A[top--];/*x为当前栈顶字符*/printf("%d",k++);printf("\t\t");for(j=0;j<=5;j++)/*判断是否为终结符*/if(x==v1[j]){flag=1;break;}if(flag==1)/*如果是终结符*/{if(x=='#'){finish=1;/*结束标记*/printf("acc!\n");/*接受*/getchar();getchar();exit(1);}/*if*/if(x==ch){print();print1();printf("%c匹配\n",ch);ch=B[++b];/*下一个输入字符*/flag=0;/*恢复标记*/}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",ch);/*输出出错终结符*/exit(1);}/*else*/}/*if*/else/*非终结符处理*/{for(j=0;j<=4;j++)if(x==v2[j]){m=j;/*行号*/break;}for(j=0;j<=5;j++)if(ch==v1[j]){n=j;/*列号*/break;}cha=C[m][n];if(cha.origin!='N')/*判断是否为空*/{print();print1();printf("%c-",cha.origin);/*输出产生式*/for(j=0;j<cha.length;j++)printf("%c",cha.array[j]);printf("\n");for(j=(cha.length-1);j>=0;j--)/*产生式逆序入栈*/A[++top]=cha.array[j];if(A[top]=='^')/*为空则不进栈*/top--;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",x);/*输出出错非终结符*/exit(1);}/*else*/}/*else*/}while(finish==0);}/*main*/三、实验过程记录:实验截图:当输入内容不匹配或输入内容非法时要退出程序,此时若不关闭已经打开的文件可能导致文件内容受到破坏;解决方法是给error()函数设置一个文件指针变量参数FILE* fp,在退出程序之前通过fp关闭文件四、实验总结:通过本次实验我锻炼了自己的上机操作能力及编程能力,并对理论知识有了进一步的了解。
老师提供的LL(1)分析法的流程图给了我很大的帮助,使得本实验基本思路变得很清晰,用较为简单的算法就能实现,程序的难点是产生式结构体的构造、分析表的构造、解决实验中遇到的问题也花费了一部分时间,我增长了处理关于文件错误的能力。