词法分析器实验报告
实验名称:语法分析器
实验内容:利用LL(1)或LR(1)分析语句语法,判断其是否符合可识别语法。学会根据状态变化、first、follow或归约转移思想构造状态分析表,利用堆栈对当前内容进行有效判断
实验设计:
1. 实现功能
可对一段包含加减乘除括号的赋值语句进行语法分析,其必须以$为终结符,语句间以;隔离,判断其是否符合语法规则,依次输出判断过程中所用到的产生式,并输出最终结论,若有错误可以报错并提示错误所在行数及原因
2. 实验步骤
3. 算法与数据结构
a) LLtable:left记录产生式左端字符;right记录产生式右端字符;ln记录产生式右端字符长度
Status:记录token分析情况
Token:category,类型;value,具体内容
b) 根据LL(1)算法,手工构造分析表,并将内容用数组存储,便于查找
c) 先将当前语句的各token按序存储,当前处理语句最后一个token以#标记,作为输入流与产生式比较,堆栈中初始放入#,x,a为处理输入流中当前读头内容
ü 若top=a=‘#‘表示识别成功,退出分析程序
ü 若top=a!=‘#‘表示匹配,弹出栈顶符号,读头前进一个
ü 若top为i或n,但top!=a,出错,输出当前语句所在行,出错具体字符
ü 若top不为i或n,查预测分析表,若其中存放关于top产生式,则弹出top,将产生式右部自右向左压入栈内,输出该产生式,若其中没有产生式,出错,输出当前语句所在行,出错具体字符
d) 以;作为语句终结,每次遇到分号则处理之前语句并清空后预备下语句处理,当遇到$表示该段程序结束,停止继续处理
4. 分析表构造过程
a) x->i=e
e->e+t|e-t|t
t->t*f|t/f|f
f->(e)|i|n
note: i表示变量,n表示数字,!表示空串
b) 提取左公因子
x->i=e
e->ea|t
a->+t|-t
t->tb|f
b->*f|/f
f->(e)|i|n
c) 消除左递归
x->i=e
e->tc
c->ac|!
a->+t|-t
t->fd
d->bd|!
b->*e|/f
f->(e)|i|n
d) FIRST & FOLLOW
e) 分析表
5. 类
class parser
{
public:
LLtable table[100][100]; //LL(1)表
void scanner(); //扫描输入流中内容并分析
parser(istream& in); //初始化,得到输入文件地址
int getLine() const; //得到当前行数
private:
int match(); //分析语法
stack
void constructTable(); //建立LL(1)表
int getRow(char ch); //取字符所在表中行
int getCol(char ch); //取字符所在表中列
istream* pstream; //输入流
void insertToken(token& t); //插入当前token
status getToken(token& t); //找到token
int getChar(); //得到当前字符
int peekChar(); //下一个字符
void putBackChar(char ch); //将字符放回
void skipChar(); //跳过当前字符
void initialization(); //初始化堆栈等
int line; //当前行数
token tokens[1000]; //字符表
int counter; //记录当前字符表使用范围
}
6. 主要代码
void parser::constructTable() //建立LL(1)表
{
for (int i=0;i<8;i++)
{
for (int j=0;j<9;j++)
{
table[i][j].left=' ';
for (int k=0;k<3;k++)
table[i][j].right[k]=' ';
}
}
table[0][6].left='x';
table[0][6].ln=3;
table[0][6].right[0]='i';
table[0][6].right[1]='=';
table[0][6].right[2]='e';
table[1][4].left='e';
table[1][4].ln=2;
table[1][4].right[0]='t';
table[1][4].right[1]='c';
table[1][6].left='e';
table[1][6].ln=2;
table[1][6].right[0]='t';
table[1][6].right[1]='c';
table[1][7].left='e';
table[1][7].ln=2;
table[1][7].right[0]='t';
table[1][7].right[1]='c';
table[2][0].left='c';
table[2][0].ln=2;
table[2][0].right[0]='a';
table[2][0].right[1]='c';
table[2][1].left='c';
table[2][1].ln=2;
table[2][1].right[0]='a';
table[2][1].right[1]='c';
table[2][5].left='c';
table[2][5].ln=0;
table[2][5].right[0]='!';
table[2][8].left='c';
table[2][8].ln=0;
table[2][8].right[0]='!';
table[3][0].left='a';
table[3][0].ln=2;
table[3][0].right[0]='+';
table[3][0].right[1]='t';
table[3][1].left='a';
table[3][1].ln=2;
table[3][1].right[0]='-';
table[3][1].right[1]='t';
table[4][4].left='t';
table[4][4].ln=2;
table[4][4].right[0]='f';
table[4][4].right[1]='d';
table[4][6].left='t';
table[4][6].ln=2;
table[4][6].right[0]='f';
table[4][6].right[1]='d';
table[4][7].left='t';
table[4][7].ln=2;
table[4][7].right[0]='f';
table[4][7].right[1]='d';
table[5][0].left='d';
table[5][0].ln=0;
table[5][0].right[0]='!';
table[5][1].left='d';
table[5][1].ln=0;
table[5][1].right[0]='!';
table[5][2].left='d';
table[5][2].ln=2;
table[5][2].right[0]='b';
table[5][2].right[1]='d';
table[5][3].left='d';
table[5][3].ln=2;
table[5][3].right[0]='b';
table[5][3].right[1]='d';
table[5][5].left='d';
table[5][5].ln=0;
table[5][5].right[0]='!';
table[5][8].left='d';
table[5][8].ln=0;
table[5][8].right[0]='!';
table[6][2].left='b';
table[6][2].ln=2;
table[6][2].right[0]='*';
table[6][2].right[1]='f';
table[6][3].left='b';
table[6][3].ln=2;
table[6][3].right[0]='/';
table[6][3].right[1]='f';
table[7][4].left='f';
table[7][4].ln=3;
table[7][4].right[0]='(';
table[7][4].right[1]='e';
table[7][4].right[2]=')';
table[7][6].left='f';
table[7][6].ln=1;
table[7][6].right[0]='i';
table[7][7].left='f';
table[7][7].ln=1;
table[7][7].right[0]='n';
}
int parser::match() //分析语法
{
ofstream ofs("out.txt",ios::app);
char a;
int i=0;
for (int p=0;p { cout< ofs< } cout< ofs< while(1) { if(tokens[i].category=='n' || tokens[i].category=='i') a=tokens[i].category; else a=(tokens[i].value)[0]; if(a==proStack.top()) { if(a=='#') { cout<<"This is valid!"< ofs<<"This is valid!"< return 0; } else { proStack.pop(); i++; } } else { if(proStack.top() =='n'|| proStack.top() =='i') { if(a!='#') { cout<<"ERROR(LINE "< ofs<<"ERROR(LINE "< } else { cout<<"ERROR(LINE "< ofs<<"ERROR(LINE "< } cout<<"This is invalid!"< ofs<<"This is invalid!"< return 0; } else { if((table[getRow(proStack.top())][getCol(a)]).left!=' ') { char pst=proStack.top(); int n=table[getRow(pst)][getCol(a)].ln; int k=0; ofs< proStack.pop(); while (n>0) { //cout< proStack.push(table[getRow(pst)][getCol(a)].right[n-1]); n--; } } else { if(a!='#') { cout<<"ERROR(LINE "< ofs<<"ERROR(LINE "< } else { cout<<"ERROR(LINE "< ofs<<"ERROR(LINE "< } cout<<"This is invalid!"< ofs<<"This is invalid!"< return 0; } } } } } 实验结果: l 输入(in.txt) l 输出1 l 输出2(out.txt) 实验总结: 原本以为处理四则运算赋值将会很困难,但在使用LL(1)后发现,思路还是挺清晰简单的,但在实验过程中,由于LL(1)不能出现左递归和左公因子,不得不将其消除,原本简单的产生式一下变多了,而在产生式理解上也没有原来直观,不过其状态复杂度没有LR高,故仍选择该方法。另外,在分别求first、follow时容易出错,在程序运行中没有得到期望结果时才发现,因此手工构造分析表较容易出错。最简单的四则运算赋值也牵涉到如此多的细节、转换,相信更为复杂的语句判断、循环等更不简单,如今计算机各种处理都远比四则运算赋值复杂得多,牵涉到诸多关系,而机器则能根据规则无差错完成,这也是人类依靠机器的重要原因,机器只是根据产生式一步步判断得出结论。而关于树形输出,在操作过程中发现较为困难,没有成功实现。 编译原理实验报告实验名称实验类型指导教师专业班级姓名学号实验地点实验成绩编写语法分析程序上机实验蒋勇软件1002班20xx1东6A319日期20xx年05月日20一实验目的通过设计编写调试一个递归下降语法分析程... 实验三语法分析器一实验目的理解和掌握LL1语法分析方法的基本原理根据给出的LL1文法掌握LL1分析表的构造及分析过程的实现掌握语法分析方法和程序设计方法二实验要求对每个非终极符按其产生式结构构造相应语法分析子程... 语法分析器的设计实验报告一实验内容语法分析程序用LL1语法分析方法首先输入定义好的文法书写文件所用的文法可以用LL1分析先求出所输入的文法的每个非终结符是否能推出空再分别计算非终结符号的FIRST集合每个非终结... 词法分析器实验报告实验目的设计编制调试一个词法分析子程序识别单词加深对词法分析原理的理解实验要求该程序要实现的是一个读单词过程从输入的源程序中识别出各个具有独立意义的单词即基本保留字标识符常数运算符分界符五大类... 山东大学编译技术课程设计班级软件一班学号20xx008000XX姓名软件一班万岁指导老师贺老师二零一一年三月一目的ltlt编译技术gtgt是理论与实践并重的课程而其实验课要综合运用一二年级所学的多门课程的内容用... 编译原理语法分析实验报告软工082班兰洁20xx31104044一实验内容二实验目的三实验要求四程序流程图主函数scannerirparser函数yucu语句串分析statement语句分析函数expressi... 曲阜师范大学实验报告软件工程一班组计算机系20xx年级日期20xx1112姓名王战海学号20xx416596实验名称语法分析实验一实验目的1通过完成预测分析法的语法分析程序了解预测分析法和递归子程序法的区别和联... Project实验名称SyntaxAnalyzerforExpressions表达式语法分析器Goals实验目的1Understandthemechanismofsyntaxanalysis了解语法分析器的运行... 装订线编译原理实验报告递归下降语法分析器学院计算机科学与技术专业xxxxxxxxxxxxxxxx学号xxxxxxxxxxxx姓名宁剑指导教师xx20xx年xx月xx日递归下降语法分析器题目一实验目的了解语法分析... 实验二词法分析器一实验目的1强化对系统软件综合工程实现能力的训练2加强对词法分析原理方法和基本实现技术的理解二实验内容用C语言或者其他的高级语言作为宿主语言完成实验一设计的C0语言的词法分析器的设计和实现三实验... 编译原理实验报告题目语法分析器的制作学生姓名班级软件1202学号04123049指导教师成绩西安邮电大学计算机学院20xx年6月7日一实验目的熟悉语法分析的过程理解相关文法的步骤熟悉First集和Follow集... 词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。二、实验要求2.1待分析的简单的词法(1)关键字:beginifthenwhiledoend所有的关键字都是小写。(2)运算符和界…
"<