实验一词法分析

合集下载

实验1 词法分析

实验1 词法分析

实验1 词法分析一、目的与要求1)目的通过设计调试词法分析程序,实现从源程序中分出各种单词的方法;加深对课 堂教学的理解;提高词法分析方法的实践能力。

2)要求u掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文 件的方法。

u掌握词法分析的实现方法。

u上机调试编出的词法分析程序。

二、说明本实验以赋值语句(以#号表示输入结束)为输入文件,BNF表示如下:〈赋值语句〉 ∷= 变量 = 算术表达式〈算术表达式〉∷=〈项〉〈算术表达式〉∷=〈算术表达式〉+〈项〉〈算术表达式〉∷=〈算术表达式〉-〈项〉〈项〉∷=〈因式〉〈项〉∷=〈项〉*〈因式〉〈项〉∷=〈项〉/〈因式〉〈因式〉∷=〈变量〉〈因式〉∷=(〈算术表达式〉)〈变量〉::= 标识符|常整数字母表:Σ={+,­,*,\,(,),=,a,b,c….z,A,B,C…Z,0,1,2,…9,#} 单词类型:u标识符 :字母组成,长度不限u常整数 :数字组成u运算符 :+,-,*,\,()u结束符:#数据结构: 标识符用单独的符号表来记录,符号表中标识符的属性只有一项: 标识符本身的字符串值。

输出:二元式,第一部分为单词的类别,第二部分为单词的属性值,其中标识 符的属性值为标识符表的索引值,常整数的属性值为常整数值,其他的属性值为单 词本身的字符串值三、词法分析过程1、背景知识(对源程序或中间结果从头到尾扫 词法分析是作为相对独立的阶段来完成的描一次,并作相应的加工处理,生成新的中间结果或目标程序)。

在词法分析 过程中,编译程序是通过操作系统从外部介质中读取源程序文件中的各个字符 的。

同时,为正确地识别单词,有时还需进行超前搜索和回退字符等操作。

因 此,为了提高读盘效率和便于扫描器进行工作,通常可采用缓冲输入的方案, 即在内存中设置一个适当大小的输入缓冲区,让操作系统直接将磁盘上的源程 序字符串分批送入此缓冲区中,供扫描器进行处理。

词法分析程序的一般设计方案是:1) 程序设计语言词法规则⇒正规文法⇒ FA;或:词法规则⇒正规表达式⇒ FA;2) NFA 确定化⇒ DFA;3) DFA 最简化;4) 确定单词符号输出形式;5) 化简后的DFA+单词符号输出形式⇒构造词法分析程序。

实验一 词法分析

实验一  词法分析

实验名称: 词法分析器设计专业: 计算机科学与技术**: ***学号: *********词法分析器设计一. 实验要求1.从源程序文件中读取有效字符和并将其转换成二元组机内表示形式输出。

2.掌握词法分析的实现方法。

二. 实验内容1、主程序设计要求:(1)主程序的说明部分为各种表格和变量安排空间(关键字和特殊符号表)。

(2)id 和ci 数组分别存放标识符和常数;还有一些为造表填表设置的变量。

(3)主程序的工作部分建议设计成便于调试的循环结构。

每个循环处理一个单词;接收键盘上送来的一个单词;调用词法分析过程;输出每个单词的内部码。

2.词法分析过程要求:该过程取名为lexical, 它根据输入单词的第一个有效字符(有时还需读第二个字符), 判断单词类, 产生类号。

对于标识符和常数, 需分别与标识符表和常数表中已登记的元素相比较, 如表中已有该元素, 则记录其在表中的位置, 如未出现过, 将标识符按顺序填入数组id 中, 将常数存入数组中ci 中, 并记录其在表中的位置。

注: 所有识别出的单词都用二元组表示。

第一个表示单词的种类。

关键字的t=1;标识符的t=2;常数t=3;运算符t=4;界符t=5。

第二个为该单词在各自表中的指针或内部码值(常数表和标识符表是在编译过程中建立起来的。

其i 值是将词法分析程序设计成独立一遍扫描源程序的结构。

其主流程图如下:图1 词法分析程序流程图三. 程序设计思想及实现步骤设计思想:本程序使用MFC可视化程序设计实现, 采用vs2010编译环境。

通过Eidt控件输入程序代码, 点击按钮启动词法分析, 将结果显示在CListBox控件中。

实现步骤:1、为程序各变量设计存储形式, 具体设计如下所示:CString m_strToken; 读入的程序代码CString m_strCodes; 得到的一个单词或符号char m_ch; 字符变量, 存放最新读进的源程序字符int m_nLocat; 查找时的位置int m_nId; 标识符表位置int m_nDigit; 常数表中的位置CString WordSheet[WORD_LEN]; 关键字表CString IdSheet[WORD_LEN]; 标识符表CString DigitSheet[WORD_LEN]; 常数表2.为程序设计各个过程, 具体设计如下所示:void GetBC(void); 检查空格符, 并将其舍弃void Concat(void); 连接字符BOOL IsLetter(void); 判断输入的是否为字符BOOL IsDigit(void); 判断输入的是否为数字int Reserve(void); 查找保留字表, 返回在表中对应的位置void Retract(void); 回退一个字符得到单词int InsertId(void); 将单词插入标识符表/int InsertConst(void) 将数字插入常数表3.对各个过程进行实现;4、调试运行并检验实验结果, 结果如图1.1所示:图 1.1 词法分析结果图四. 程序源码1、各过程的实现:void CAnalysisWordsDlg::GetChar(void) {//得到下个输入字符UpdateData();m_ch = m_strCodes.GetAt(m_nLocat);m_nLocat++;}void CAnalysisWordsDlg::GetBC(void) {//检查空白符if(m_ch == ' ')GetChar();}// 连接字符void CAnalysisWordsDlg::Concat(void) {m_strToken += m_ch;} //是否是字符BOOL CAnalysisWordsDlg::IsLetter(void) {if(m_ch>='a' && m_ch<='z')return TRUE;else if(m_ch>='A' && m_ch<='Z')return TRUE;return FALSE;}//是否是数字BOOL CAnalysisWordsDlg::IsDigit(void) {if(m_ch>='0' && m_ch<='9')return TRUE;return FALSE;}// //查找保留字表int CAnalysisWordsDlg::Reserve(void){for(int i=1;i<41;i++){if(m_strToken == WordSheet[i])return i;}return 0;}// //得到字符void CAnalysisWordsDlg::Retract(void){//m_strToken=m_strToken.Left(m_strToken.GetLength()-1);m_nLocat--;m_ch = ' ';}// //将字符插入字符表int CAnalysisWordsDlg::InsertId(void){for(int i=1;i<m_nId+1;i++){if(IdSheet[i] == m_strToken)return i;}m_nId++;IdSheet[m_nId] = m_strToken;return m_nId;}// //将数字插入数字表int CAnalysisWordsDlg::InsertConst(void) {for(int i=1;i<m_nDigit+1;i++){if(m_strToken == DigitSheet[i])return i;}m_nDigit++;DigitSheet[m_nDigit] = m_strToken;return m_nDigit;}2.Edit控件中换行的消息预处理函数:BOOL CAnalysisWordsDlg::PreTranslateMessage(MSG* pMsg) {// TODO: 在此添加专用代码和/或调用基类if(pMsg->message == WM_KEYDOWN){if(pMsg->wParam == VK_RETURN ){return FALSE;}}return CDialogEx::PreTranslateMessage(pMsg);}3.主过程的实现(按钮对应的消息函数):void CAnalysisWordsDlg::OnBnClickedBtnStartAnaly(){// TODO: 在此添加控件通知处理程序代码UpdateData();m_nLocat = 0;//GetDlgItem(IDC_LIST_RESULT)->SetItemText(_T(""));int n = m_lstResult.GetCount();for(int i=0;i<n;i++)m_lstResult.DeleteString(i+1);if(m_strCodes != _T("")){int nLen = m_strCodes.GetLength();while(nLen != m_nLocat){CString strLst;m_strToken = _T("");int code,value;GetChar();GetBC();if(IsLetter()){while (IsLetter() || IsDigit()){Concat();GetChar();}Retract();code = Reserve();if(code == 0){//标识符value = InsertId();strLst.Format(_T("标识符: (2,%d,%s)"),value,m_strToken);m_lstResult.AddString(strLst);}else{strLst.Format(_T("关键字: (1,%d,%s)"),code,m_strToken);m_lstResult.AddString(strLst);}}else if(IsDigit()){while(IsDigit()){Concat();GetChar();}Retract();value = InsertConst();strLst.Format(_T("数字: (3,%d,%s)"),value,m_strToken);m_lstResult.AddString(strLst);}else{while(!(IsLetter() || IsDigit() || m_ch ==' ' || (m_nLocat == nLen+1))){Concat();GetChar();}Retract();code = Reserve();if(code == 14 || (code >= 30&&code <= 38)){//界符strLst.Format(_T("界符: (5,%d,%s)"),code,m_strToken);m_lstResult.AddString(strLst);}else if((code>=15 && code <= 29) || (code>=39 && code<=40)){//运算符strLst.Format(_T("运算符: (4,%d,%s)"),code,m_strToken);m_lstResult.AddString(strLst);}}}}}五. 结果分析及试验心得:(1)本次实验主要的函数及功能教材上提供的很全面, 因此本次实验主要的工作就是对各个函数过程的实现, 做起来还是比较容易的!但对程序的几点思考使我对词法分析有了更深的认识:表结构的存储: 对与各个表的存储开始时我想到是运用数据库存储, 这样实现起来会更容易!但是数据库的引入减少了代码的量, 但却使程序脱离的底层失去了词法分析的意义;程序功能的实现:对于程序中的“++”、“--”等运算符用到了超前搜索的思想, 由于开始设计时的从简原则, 使得在这一块的实现上还存在这问题, 需要以后的继续改进;分析错误的处理: 虽然这次实验我并没有加入错误的处理程序, 但我个人认为对于错误的处理是程序设计中一个很重要的环节, 他对程序的健壮性用很大的影响。

编译原理实验--词法分析器

编译原理实验--词法分析器

实验一词法分析器设计【实验目的】1.熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。

2.复习高级语言,进一步加强用高级语言来解决实际问题的能力。

3.通过完成词法分析程序,了解词法分析的过程。

【实验内容】用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。

【实验流程图】【实验步骤】1.提取pl/0文件中基本字的源代码while((ch=fgetc(stream))!='.'){int k=-1;char a[SIZE];int s=0;while(ch>='a' && ch<='z'||ch>='A' && ch<='Z'){if(ch>='A' && ch<='Z') ch+=32;a[++k]=(char)ch;ch=fgetc(stream);}for(int m=0;m<=12&&k!=-1;m++)for(int n=0;n<=k;n++){if(a[n]==wsym[m][n]) ++s;else s=0;if(s==(strlen(wsym[m]))) {printf("%s\t",wsym[m]);m=14;n=k+1;} }2.提取pl/0文件中标识符的源代码while((ch=fgetc(stream))!='.'){int k=-1;char a[SIZE]=" ";int s=0;while(ch>='a' && ch<='z'||ch>='A' && ch<='Z'){if(ch>='A' && ch<='Z') ch+=32;a[++k]=(char)ch;ch=fgetc(stream);}for(int m=0;m<=12&&k!=-1;m++)for(int n=0;n<=k;n++){if(a[n]==wsym[m][n]) ++s;else s=0;if(s==(strlen(wsym[m]))) {m=14;n=k+1;}}if(m==13) for(m=0;a[m]!=NULL;m++) printf("%c ",a[m]);3.提取pl/0文件中常数的源代码while((ch=fgetc(stream))!='.'){while(ch>='0' && ch<='9'){num=10*num+ch-'0';ch=fgetc(stream);}if(num!=0) printf("%d ",num);num=0;}4.提取pl/0文件中运算符的源代码int ch=fgetc(stream);while(ch!='.'){switch(ch){case'+': printf("+ ");break;case'-': printf("- ");break;case'*': printf("* ");break;case'/': printf("/ ");break;case'>': if(fgetc(stream)=='=')printf(">= "); else printf("> ");break;case'<': if(fgetc(stream)=='=')printf("<= "); else printf("< ");break;case':': printf(":= ");break;case'#': printf("# ");break;case'=': printf("= ");break;default: break;}ch=fgetc(stream);5.提取pl/0文件中界符的源代码int ch=fgetc(stream);while(ch!='.'){switch(ch){case',': printf(", ");break;case';': printf("; ");break;case'(': printf("( ");break;case')': printf(") ");break;default: break;}ch=fgetc(stream);}【实验结果】1.pl/0文件(222.txt)内容const a=10;var b,c;procedure p;beginc:=b+a;end;beginread(b);while b#0 dobegincall p;write(2*c);read(b)endend .2.实验运行结果【实验小结】1.了解程序在运行过程中对词法分析,识别一个个字符并组合成相应的单词,是机器能过明白程序,定义各种关键字,界符。

实验一词法分析实验报告1

实验一词法分析实验报告1

实验一词法分析一、实验目的通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。

并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。

并依次输出各个单词的内部编码与单词符号自身值。

(遇到错误时可显示“Error”,然后跳过错误部分继续显示)二、实验要求使用一符一种的分法关键字、运算符和分界符可以每一个均为一种标识符和常数仍然一类一种三、实验内容功能描述:1、待分析的简单语言的词法(1)关键字:begin if then while do end(2)运算符和界符:(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter| digit)*NUM=digit digit *(4)空格由空白、制表符和换行符组成。

空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。

2、各种单词符号对应的种别码图 1程序结构描述:符号界符等符号四、实验结果输入begin x:=9: if x>9 then x:=2*x+1/3; end # 后经词法分析输出如下序列:(begin 1)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图3所示:图3输入private x:=9;if x>0 then x:=2*x+1/3; end#后经词法分析输出如下序列:(private 10)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图4所示:图4显然,private是关键字,却被识别成了标示符,这是因为图1中没有定义private关键字的种别码,所以把private当成了标示符。

输入private x:=9;if x>0 then x:=2*x+1/3; @ end#后经词法分析输出如下序列:(private 10)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图5所示图5显然,@没有在图一中定义种别,所以输出了“Error in row 1!”的报错信息。

实验1 词法分析实验报告

实验1  词法分析实验报告
{
p=0;
row=1;
cout<<"Please input string:"<<endl;
do
{
cin.get(ch);
prog[p++]=ch;
}
while(ch!='#');
p=0;
do
{
scaner();
switch(syn)
{
case 11: cout<<"("<<syn<<","<<sum<<")"<<endl; break;
实验二时发现怎么出结果都会出现一个缺:=错误,便回头检查代码才发现实验一时的scaner()函数最后的:和:=的种别码互相写错了,所以回过头来重新修正了代码和实验结果图。
case -1: cout<<"Error in row"<<row<<"!"<<endl; break;
case -2: row=row++;break;
default: cout<<"("<<syn<<","<<token<<")"<<endl;break;
}
}
while (syn!=0);
}
四、结果验证
{
syn=21;
token[m++]=ch;
}
else if(ch=='=')

实验一(词法分析)

实验一(词法分析)

实验一词法分析一.实验目的1、学会针对DFA转换图实现相应的高级语言源程序。

2、深刻领会状态转换图的含义,逐步理解有限自动机。

3、掌握手工生成词法分析器的方法,了解词法分析器的内部工作原理。

二.实验内容TINY计算机语言的编译程序的词法分析部分实现。

从左到右扫描每行该语言源程序的符号,拼成单词,换成统一的内部表示(token)送给语法分析程序。

为了简化程序的编写,有具体的要求如下:(1)数仅仅是整数。

(2)空白符仅仅是空格、回车符、制表符。

(3)代码是自由格式。

(4)注释应放在花括号之内,并且不允许嵌套三.实验要求要求实现编译器的以下功能:(1)按规则拼单词,并转换成二元式形式(2)删除注释行(3)删除空白符(空格、回车符、制表符)(4)列表打印源程序,按照源程序的行打印,在每行的前面加上行号,并且打印出每行包含的记号的二元形式(5)发现并定位错误,词法分析进行具体的要求:(1)记号的二元式形式中种类采用枚举方法定义;其中保留字和特殊字符是每个都一个种类,标示符自己是一类,数字是一类;单词的属性就是表示的字符串值。

(2)词法分析的具体功能实现是一个函数GetToken(),每次调用都对剩余的字符串分析得到一个单词或记号识别其种类,收集该记号的符号串属性,当识别一个单词完毕,采用返回值的形式返回符号的种类,同时采用程序变量的形式提供当前识别出记号的属性值。

这样配合语法分析程序的分析需要的记号及其属性,生成一个语法树。

(3)标示符和保留字的词法构成相同,为了更好的实现,把语言的保留字建立一个表格存储,这样可以把保留字的识别放在标示符之后,用识别出的标示符对比该表格,如果存在该表格中则是保留字,否则是一般标示符。

源程序:/*注意:测试时把测试的源程序存入当前目录中,并改名为source.txt*/#include<iostream>#include<iomanip>#include<ctype.h>#include<fstream>#include<string>usingnamespacestd;enumWordType {WRONG, NUMBER, BIAOSHI, IF, THEN, ELSE, END, REPEAT, UNTIL,//9READ, WRITE, PLUS, SUBTRACT, MULTIPLY, DIVIDEY, EQUAL, LESSTHAN, COLON,//18ASSIGNMENT, LINE_FEED, SPACE, TAB, BRACKET_L, BRACKET_R};//24enumCharType {ALPHABET, OTHER};enumWrongType {ZERO, ALP_NUM, NUM_ALP, UNLEAGL_S, NO_MATCH, UNKNOW};char*Words [] = {"wrong","number","biaoshi","if","then","else","end","repeat","until",//9"read","write","+","-","*","/","=","<",":",//18":=","\n"," ","","{","}"};//24typedefstruct {charArrayChar[100], cbuffer;inti=-1, numline = 1, wordtype;string LineChar;Two T;ifstream fp("source.txt",ios::in);intmain (){char*str;intwordtype;}Two;voidHandleAlphabet();voidHandleNumber ();voidHandleOther ();if(!fp){cout << setiosflags (ios::left) << setw(6) <<"行数"<<"(";cout << setiosflags (ios::left) << setw(10)<<"类别编码"<<", ";cout << setiosflags (ios::left) << setw(20) <<"字符"<<")"<< endl;fp.get (cbuffer);while(!fp.eof ()){}if(cbuffer =='\n')//忽略换行符{} elseif(cbuffer ==' ')//忽略空字符{}elseif(cbuffer =='')//忽略制表符{}elseif(isalpha(cbuffer))//判断是否是字母{} elseif(isdigit(cbuffer))//判断是否是数字{}else//其他字符HandleOther ();HandleNumber ();HandleAlphabet ();LineChar +=" ";fp.get(cbuffer);LineChar +=" ";fp.get(cbuffer);cout <<"第"<< numline <<"行所有字符:"<< LineChar << endl;numline++;LineChar ="";fp.get(cbuffer);cout<<"文件打开错误!!"<<endl;elsei = -1;}}cout <<"第"<< numline <<"行所有字符:"<< LineChar << endl;fp.close ();system ("pause");return0;intMatch(charstr[],intchartype)//查找匹配的字符{} voidTypeWrong (intwrongtype,intline){switch(wrongtype){caseZERO:cout <<"字母后面不能紧跟数字!";break;cout <<"数字后面不能紧跟字母!";break;cout <<"非法特殊符号!";break;caseALP_NUM:inti;switch(chartype){caseALPHABET:}returnWRONG;for(i = IF; i <= WRITE; i++){}for(i = PLUS; i <= ASSIGNMENT; i++){}if(strcmp(Words[i],str) == 0) returni;if(strcmp(Words[i],str) == 0)returni;caseOTHER:caseNUM_ALP:caseUNLEAGL_S:}caseNO_MATCH:}cout <<"没有与第"<< line <<"行“{”匹配的“}”!";cout <<"其它类型错误!";break;default:Two ConvertTwo (charstr[],intwordtype,intwrongtype,intnumline,intline)//进行二元转换{}voidHandleAlphabet ()//首字符为字母时的处理{ArrayChar[i+1]='\0';boolmark =true;while(!fp.eof() && isalpha(cbuffer)){}if(isdigit (cbuffer)){}mark =false;while(!fp.eof() && (isalpha(cbuffer)||isdigit(cbuffer))){}ArrayChar[++i]=cbuffer;fp.get(cbuffer);ArrayChar[++i]=cbuffer;fp.get(cbuffer);returnT;cout << setiosflags (ios::left) << setw(6) << numline <<"(";cout << setiosflags (ios::left) << setw(10)<< T.wordtype <<", ";cout << setiosflags (ios::left) << setw(20) << T.str <<")";if(T.wordtype == WRONG)TypeWrong (wrongtype, line);cout << endl;Two T;T.wordtype = wordtype;T.str = str;}LineChar += ArrayChar;if(mark){}elseT = ConvertTwo(ArrayChar,WRONG, ALP_NUM, numline, numline); wordtype = Match(ArrayChar, ALPHABET);T = ConvertTwo(ArrayChar,(BIAOSHI > wordtype ? BIAOSHI : wordtype), ZERO, numline,numline);voidHandleNumber ()//首字符为数字时的处理{} voidDeleteNote ()//删除注释{intrecord = numline;while(!fp.eof() && cbuffer !='}'){fp.get(cbuffer);while(!fp.eof() && cbuffer !='}')boolmark =true;while(!fp.eof() && isdigit(cbuffer)){}if(isalpha(cbuffer)){}ArrayChar[i+1]='\0';LineChar += ArrayChar;if(mark)T = ConvertTwo(ArrayChar, NUMBER, ZERO, numline, numline);T = ConvertTwo(ArrayChar,WRONG, NUM_ALP, numline, numline);else mark =false;while(!fp.eof() && (isalpha(cbuffer)||isdigit(cbuffer))){}ArrayChar[++i]=cbuffer; fp.get(cbuffer);ArrayChar[++i]=cbuffer;fp.get(cbuffer);}}{}ArrayChar[i + 1]='\0';if(cbuffer =='}'){}else{}T = ConvertTwo("", WRONG, NO_MATCH, numline, record); ArrayChar [++i] ='}';ArrayChar[i + 1]='\0';T = ConvertTwo("}",BRACKET_R, ZERO, numline, numline);if(cbuffer =='\n'){}ArrayChar[++i]=cbuffer;fp.get(cbuffer);ArrayChar [i + 1] ='\0';LineChar += ArrayChar;cout <<"第"<< numline <<"行所有字符:"<< LineChar << endl;LineChar ="";numline++;i = -1;fp.get(cbuffer);LineChar += ArrayChar;fp.get(cbuffer);voidHandleOther ()//字符为特殊字符时的处理{if(ArrayChar [i] =='{')//删除注释{}else//其他字符{fp.get(cbuffer);while(!fp.eof() && cbuffer !='\n'&& cbuffer !=' '&& cbuffer !=''ConvertTwo("{", BRACKET_L, ZERO, numline, numline);DeleteNote ();ArrayChar [++i] = cbuffer;&& !isalpha(cbuffer) && !isdigit(cbuffer))}}{}ArrayChar[i + 1]='\0';wordtype = Match(ArrayChar, OTHER);LineChar += ArrayChar;T = ConvertTwo(ArrayChar, wordtype, (wordtype > 0 ? 0: UNLEAGL_S), numline, numline);ArrayChar [++i] = cbuffer;fp.get(cbuffer);实验结果:。

编译原理实验-词法分析

编译原理实验-词法分析

实验一词法分析有如下算术运算文法:1) E->E+T2) E->E-T3) E->T4) T->T*F5) T->T/F6) T->F7) F->(E)8) F->I9) I->十进制实数|十进制整数|十六进制实数|?十六进制整数|八进制实数|八进制整数10) 十进制实数->(0|(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*).(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9) *11) 八进制实数->0(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*.(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7) *12) 十六进制实数 ->0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b |c|d|e|f)* .(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6 |7|8|9|a|b|c|d|e|f) *13) 十进制整数->0 | (1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9) * 14) 八进制整数->¥0(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7) *15)十六进制整数->0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f) *单词分类:运算符:+ - * / ()常数:十进制实数十进制整数十六进制实数十六进制整数|八进制实数八进制整数1. 实验目的实现一个词法分析程序,将输入字符串流分解成单词流供语法分析使用。

2. 实验要求输入算术运算式,输出分解后的单词流,例如:输入(+)*12输出:运算符 (/八进制实数运算符 +十六进制实数运算符 )运算符 *十进制整数 12注意:输入可以是键盘输入,也可以是文件输入如果单词输入错误,必须有提示,例如:输入 12a+45*013468-0x23a3输出.错误数据12a运算符 +十进制整数 45运算符 *错误数据 0123468运算符 -十六进制整数 0x23a3){nowChar[a_long]=*a;doc=1;—*a++;a_long++;}nowChar[a_long]='\0'; ){nowChar[a_long]=*a;doc=1;*a++;a_long++;}nowChar[a_long]='\0';if(doc) ){|nowChar[a_long]=*a;doc=1;*a++;a_long++;}nowChar[a_long]='\0';if(doc) ||(*a=='_'))){ d=id; ind[i]=kinds[id][i];link[link_long].=y;} ind[i]=a[i];link[link_long].[0]='-';—link[link_long].[1]='\0';}link_long++; } ind[i]=kinds[id][i]; i]=a[i];link[link_long].[i]='\0'; }else x; }link_long++; ;i++)x=x*10+(a[i]-48);for(i=strlen(a)-1;i>=0&&a[i]!='.';i--)y=(y+(a[i]-48))/10;y=y+x; ;i++)x=x*8+(a[i]-48);for(i=strlen(a)-1;i>=0&&a[i]!='.';i--)'y=(y+(a[i]-48))/8;y=y+x; ;i++) ;i--)y=(y+(a[i]-48))/16;y=y+x; //整数部分与小数部分换算后相加printf("REAL16\t%f\n",y); //存入结构数组save(a,id,x,y);return;}printf("Wrong Enter"); //所得的具体类型值为,则输入有错误return;}。

实验一 词法分析

实验一 词法分析

实验一词法分析一、实验目的:通过本实验理解词法分析的整个过程,处理对象和处理的结果,了解词法分析在整个编译过程中的作用。

二、实验学时:2学时。

三、实验内容根据给出的简单语言的词法构成规则和单词集合,编制词法分析程序,要求能用给定的简单语言书写的源程序进行词法分析,同时建立相应的符号表文件存放正确的单词。

输出分析结果于文件中,包括:(1)正确的单词符号及其单词种类的序对二元组。

具体输出形式为:二元组:(单词种类,单词内码值)单词种类见五。

四、实验方法构造识别单词集的自动机,编写程序实现。

五、实验的处理单词集六、处理程序例和处理结果例例1:源程序:main(){y=x-1;}处理结果:(26,"main")(1,"(")(2,")")(3,"{")(0,"y")(6,"=")(0,"x")(100,"-")(20,"1")(5,";")(4,")")例2:源程序main(){int a,b;b!=a-1;}处理结果:(26,"main")(1,"(")(2,")")(3,"{" })(21,”int”)(0,"a")(11,",")(0,"b")(5,”;”)(0,"b")(100,"! ")(6,"=")(0,"a")(100,"-")(30,"1")(5,”;”)(4,”}”)七、实验报告要求给出单词识别的状态转换图;带有注释(简单说明)的源程序。

(完整word版)编译原理词法分析程序实现实验报告

(完整word版)编译原理词法分析程序实现实验报告

(完整word版)编译原理词法分析程序实现实验报告实验一词法分析程序实现一、实验内容选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。

输入:由无符号数和+,-,*,/, ( , ) 构成的算术表达式,如1.5E+2-100。

输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。

二、设计部分因为需要选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来,而其中的关键则为无符号数的识别,它不仅包括了一般情况下的整数和小数,还有以E为底数的指数运算,其中关于词法分析的无符号数的识别过程流程图如下:GOTO 1:(完整word版)编译原理词法分析程序实现实验报告GOTO 2:三、源程序代码部分#include <stdio.h>#include<stdlib.h>#include <math.h>#define MAX 100#define UNSIGNEDNUMBER 1#define PLUS 2#define SUBTRACT 3#define MULTIPLY 4#define DIVIDE 5#define LEFTBRACKET 6#define RIGHTBRACKET 7#define INEFFICACIOUSLABEL 8#define FINISH 111int count=0;int Class;void StoreType();int Type[100];char Store[20]={'\0'};void ShowStrFile();//已经将要识别的字符串存在文件a中void Output(int a,char *p1,char *p2);//字符的输出过程int Sign(char *p);//'+''-''*''/'整体识别过程int UnsignedNum(char *p);//是否适合合法的正整数0~9int LegalCharacter(char *p);//是否是合法的字符:Sign(p)||UnsignedNum(p)||'E'||'.' void DistinguishSign(char *p);//'+''-''*''/'具体识别过程void TypyDistinguish();//字符的识别过程void ShowType();//将类别码存储在Type[100]中,为语法分析做准备void ShowStrFile()//已经将要识别的字符串存在文件a中{FILE *fp_s;char ch;if((fp_s=fopen("a.txt","r"))==NULL){printf("The FILE cannot open!");exit(0);}elsech=fgetc(fp_s);while(ch!=EOF){putchar(ch);ch=fgetc(fp_s);}printf("\n");}void StoreStr()//将文件中的字符串存储到数组Store[i] {FILE *fp=fopen("a.txt","r");char str;int i=0;while(!feof(fp)){fscanf(fp,"%c",&str);if(str=='?'){Store[i]='\0';break;}Store[i]=str;i++;}Store[i]='\0';}void ShowStore(){int i;for (i=0;Store[i]!='\0';i++)printf("%c",Store[i]);printf("\n");}void Output(int a,char *p1,char *p2){printf("%3s\t%d\t%s\t","CLASS",a,"VALUE");while(p1<=p2){printf("%c",*p1);p1++;}printf("\n");}int Sign(char *p){char ch=*p;if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')') return 1;elsereturn 0;}int UnsignedNum(char *p){char ch=*p;if('0'<=ch&&ch<='9')return 1;elsereturn 0;}int LegalCharacter(char *p){char ch=*p;if(Sign(p)||UnsignedNum(p)||ch=='E'||ch=='.')。

词法分析实验报告(实验一)

词法分析实验报告(实验一)

编译原理词法分析实验报告软工082班兰洁200831104044一、实验内容二、实验目的三、实验预期四、程序规定五、实验原理●程序流程图●判别浮点功能扩展流程图●状态转换图六、程序代码与浮点判别功能扩展七、测试用例●扩展功能测试用例;●普通功能测试用例八、输出结果九、实验心得一、实验内容:词法分析:1、识别简单语言的单词符号;2、识别关键字、标识符、数字、运算符等。

并扩展浮点识别功能。

二、实验目的调试词法分析程序,加深对词法分析原理的理解,掌握编写简单词法分析程序的一般步骤。

三、实验预期结果:经过调试源代码程序,程序能够成功运行编译,对输入的简单字符串,能够别关键字、标识符、数字、运算符等,并且给出单词符号的对应编码。

四、程序规定:1、关键字:"function","if","then","while","do","endfunc";2、算术运算符:”+”,”-”,”*”,”/”,”=”;3、关系运算符:"<" ">" "<=" ">=" "==" "!=";4、界符:"(" ")" ";" "#";5、标识符规定以字母开头,字母均为小写;6、空格和换行符跳过;7、单词对应编码:十、实验原理:输入串--------------------〉词法分析程序————————〉单词符号串输入:字符串以#结束。

输出:单词的二元组(syn,token/sum)程序流程图分析浮点数功能扩展部分流程图:shuzi()函数状态转换图六、程序代码:备注:红色字体部分为程序功能的功能扩展,使程序能够分析浮点数!我把浮点数的syn设置为80!/*词法分析源代码*/#include<stdio.h>#include<string.h>scaner();char prog[80],token[8];char ch;int syn,p,m,n,sum;char * rwtab[6]={"function","if","then","while","do","endfunc"}; int i=0,k,c,sumint,f;char fenshu[80],sum1[80];double sumf=0,fudian;int shuzi(){if(ch>='0' && ch<='9')syn=80;elsesyn=-2;return syn;}main(){p=0;printf("\n please input string :\n");do{scanf("%c",&ch);prog[++p]=ch;}while(ch!='#');p=0;do{scaner();switch(syn){ case 11:printf("\n(%d,%d)",syn,sum);break;case -1:printf("\n error");break;case 80:printf("\n(%d,%f)",syn,fudian);break; default:printf("\n(%d,%s)",syn,token);}}while(syn!=0);}scaner(){for(n=0;n<8;n++)token[n]=NULL;//if(1+2!=3)ch=prog[++p];while(ch==' ' || ch=='\n')ch=prog[++p];//跳过空格if(ch>='a' && ch<='z'){m=0;while(ch>='a' && ch<='z' || ch>='0' && ch<='9') {token[m++]=ch;//token[0]=f,m=1ch=prog[++p];}token[m]='\0';ch=prog[--p];syn=10;for(n=0;n<6;n++){if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}}elseif(ch>='0' && ch<='9'){c=p;k=0;do{ sum1[k]=ch;ch=prog[++c]; //ch取后一个数字k++;shuzi();//这个函数用来分析浮点数的整数部分是否已经输入到数组里f=syn;} while(f==80)if(ch=='.'){for(n=0;n<k;n++){sumint=sumint*10+sum1[n]-'0';} //计算整数部分i=0;do{ch=prog[++c];fenshu[i]=ch;i++;shuzi();//这个函数用来分析浮点数的小数部分是否已经输入到数组里} while(syn==80);sumf=0;for(k=i-2;k>=0;k--){sumf=sumf*0.1+(fenshu[k]-'0')*0.1;} //计算浮点数的小数部分fudian=sumint+sumf; //浮点数计算syn=80;p=--c;}else{ch=prog[p];//若是整数,ch等于原来的值 sum=0;while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=prog[++p];}ch=prog[--p];syn=11;}}elseswitch(ch){case'<':m=0;token[m++]=ch;ch=prog[++p];if(ch=='='){syn=22;token[m++]=ch;}elseif(ch=='>'){syn=21;token[m++]=ch;}else{syn=20;ch=prog[--p];}break;case'>':m=0;token[m++]=ch;ch=prog[++p];if(ch=='='){syn=24;token[m++]=ch;}else{syn=23;ch=prog[--p];}break;case'=':m=0;token[m++]=ch;ch=prog[++p];if(ch=='='){syn=25;token[m++]=ch;}else{syn=18;ch=prog[--p];}break;case'!':m=0;token[m++]=ch;ch=prog[++p];if(ch=='='){syn=22;token[m++]=ch;}else{syn=-1;p--;}break;case'+':syn=13;token[0]=ch;break;case'-':syn=14;token[0]=ch;break;case'*':syn=15;token[0]=ch;break;case'/':syn=16;token[0]=ch;break;case';':syn=26;token[0]=ch;break;case'(':syn=27;token[0]=ch;break;case')':syn=28;token[0]=ch;break; case'#':syn=0;token[0]=ch;break;default:syn=-1;}}七、测试用例:补充:功能扩展测试用例:八、程序输出结果:功能扩展测试用例输出结果用例一:用例二:用例三:普通功能测试用例显示结果九、实验心得通过编译原理实验一词法分析实验,使得自己对词法分析的流程有了更深刻的了解,虽然源代码并非由自己设计,但是在调试程序的过程中,尤其是进行测序功能扩展的过程中,想了很多种办法,终于找到了最合适的方法,而且还进行了代码的优化,这个过程虽然有时有些枯燥,但是更多时候是欣喜的,不仅复习了c语言的许多内容,并且有了更深的理解。

实验一 词法分析报告

实验一  词法分析报告

实验一词法分析1.实验要求(1)从源程序文件中读取有效字符并将其转换成二元组内部表示形式输出。

(2)掌握词法分析的实现方法。

(3)实验时间4学时。

(4)实验完成后,要提交实验报告(包括源程序清单)。

2.实验内容2.1主程序设计考虑:主程序的说明部分为各种表格和变量安排空间(关键字和特殊符号表)。

id 和ci 数组分别存放标识符和常数;还有一些为造表填表设置的变量。

主程序的工作部分建议设计成便于调试的循环结构。

每个循环处理一个单词;调用词法分析过程;输出每个单词的内部码(种别编码,属性值)。

建议从文件中读取要分析的符号串。

2.2词法分析过程考虑该过程根据输入单词的第一个有效字符(有时还需读第二个字符),判断单词种别,产生种别编码。

对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组id 中,将三:主流程图如下:四:实验思路(1)我首先把这个单词的种类分成了五类,包括:关键字、标识符、常数、算符、界符。

然后利用状态转换图进行单词的识别(2)对于关键字、算符、界符。

因为这些单词的个数有限。

所以我单独给每个单词一个种别编码。

能够做到每个单词的种别编码是不一样的。

而对于常数和标识符,我先把它们分别单独的作为一类,然后定义一个二维数组,分别存放这个单词的名称和编码。

而这个编码就是这个单词在这个二维数组中的位置;当遇到新的标识符或常数,就把这个单词放入到相应的数组中。

(3)然后构造一个状态转换图的程序。

把每次得到的单词先暂时存放在temp 二维数组中。

然后用这个临时的二维数组去确定这个单词是何种类别五:实验代码using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace Word{public partial class Form1 : Form{public Form1(){InitializeComponent();}char[] receive; //从输入得到的源程序char ch; //这是从源程序读取的一个字符string cache; //暂存的单词int index; //记录取到哪个位置了key_word temp; //用来临时存放得到这个单词struct key_word{public string key_name;public int number;}struct num_word{public string num_name;public int number;}struct ID_word{public string ID_name;public int number;}public int num_index;public int ID_index;DataTable dt;private void button1_Click(object sender, EventArgs e){dt = new DataTable();dt.Columns.Add("助记符");dt.Columns.Add("外部编码");dt.Columns.Add("内部编码");dt.Columns.Add("类型");receive = textBox1.Text.ToCharArray();index = 0;num_index = 0;ID_index = 0;;while (index < receive.Length){cache = null;Get_Word();if (temp.number == 1){int i = 0;int flag = 0;if (num_index == 0){Num[num_index].num_name = temp.key_name;Num[num_index].number = num_index;num_index++;}else{for (i = 0; i < num_index; i++){if (Num[i].num_name == temp.key_name){flag = i;break;}}if (i >= num_index){Num[num_index].num_name = temp.key_name;Num[num_index].number = num_index;flag = num_index;num_index++;}}DataRow dr = dt.NewRow();dt.Rows.Add(dr);dr["助记符"] = temp.key_name;dr["内部编码"] = +Num[flag].number;dr["类型"] = "常数";}else if (temp.number == 0){int i = 0;int flag = 0;if (ID_index == 0){ID[ID_index].ID_name = temp.key_name;ID[ID_index].number = ID_index;ID_index++;}else{for (i = 0; i < ID_index; i++){if (ID[i].ID_name == temp.key_name){flag = i;break;}}if (i >= ID_index){ID[ID_index].ID_name = temp.key_name;ID[ID_index].number = ID_index;flag = ID_index;ID_index++;}}DataRow dr = dt.NewRow();dt.Rows.Add(dr);dr["助记符"] = temp.key_name;dr["外部编码"] = temp.number;dr["内部编码"] = ID[flag].number;dr["类型"] = "标识符";}else{DataRow dr = dt.NewRow();dt.Rows.Add(dr);dr["助记符"] = temp.key_name;if (temp.number >= 15 && temp.number <= 30){dr["类型"] = "运算符";}else if (temp.number >= 31 && temp.number <= 40){dr["类型"] = "界符";}else{dr["类型"] = "关键字";}}}this.dataGridView1.DataSource = dt;}key_word[] Key;num_word[] Num;ID_word[] ID;private void Form1_Load(object sender, EventArgs e){index = 0;Key = new key_word[41];Key[0].key_name = "$ID"; Key[0].number = 0; //标识符Key[1].key_name = "$INT"; Key[1].number = 1; //数Key[2].key_name = "int"; Key[2].number = 2; Key[3].key_name = "float"; K ey[3].number = 3;Key[4].key_name = "void"; Key[4].number = 4; Key[5].key_name = "const"; Key[5].number = 5; Key[6].key_name = "if"; Key[6].number = 6; Key[7].key_name = "el se"; Key[7].number = 7;Key[8].key_name = "do"; Key[8].number = 8; Key[9].key_name = "while"; Key[9].number = 9; Key[10].key_name = "scanf"; Key[10].number = 10; Key[11].key_nam e = "printf"; Key[11].number = 11;Key[12].key_name = "return"; Key[12].number = 12; Key[13].key_name = " main"; Key[13].number = 13; Key[14].key_name = "read"; Key[14].number = 14;Key[15].key_name = "+"; Key[15].number = 15;Key[16].key_name = "-"; Key[16].number = 16; Key[17].key_name = "*"; K ey[17].number = 17; Key[18].key_name = "/"; Key[18].number = 18; Key[19].key_name = "%"; Key[19].number = 19;Key[20].key_name = "="; Key[20].number = 20; Key[21].key_name = "=="; Key[21].number = 21; Key[22].key_name = ">"; Key[22].number = 22; Key[23].key_name = "<"; Key[23].number = 23;Key[24].key_name = "!="; Key[24].number = 24; Key[25].key_name = ">="; Key[25].number = 25; Key[26].key_name = "<="; Key[26].number = 26; Key[27].key_na me = "&&"; Key[27].number = 27;Key[28].key_name = "||"; Key[28].number = 28; Key[29].key_name = "!"; K ey[29].number = 29; Key[30].key_name = "<>";Key[30].number = 30;Key[31].key_name = "("; Key[31].number = 31;Key[32].key_name = ")"; Key[32].number = 32; Key[33].key_name = "{"; K ey[33].number = 33;Key[34].key_name = "}"; Key[34].number = 34; Key[35].key_name = ";"; K ey[35].number = 35;Key[36].key_name = ","; Key[36].number = 36; Key[37].key_name = "\""; K ey[37].number = 37; Key[38].key_name = "'"; Key[38].number = 38; Key[39].key_name = "++"; Key[39].number = 39;Key[40].key_name = "--"; Key[40].number = 40;Num = new num_word[1024];ID = new ID_word[1024];}public void GetChar() //得到一个字符{if (index < receive.Length){ch = receive[index];index++;}else{ch = '\0';}}public void GetNotKong() //得到一个不是空的字符{while (index < receive.Length){ch = receive[index];index++;if (ch != ' ' && ch != '\r' && ch != '\0' && ch != '\n'){break;}}}public void ConCat() //连接{cache += ch;}public bool IsLetter() //判断是不是字母{if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {return true;}else{return false;}}public bool IsDigit() //判断是不是数字{if (ch >= '0' && ch <= '9'){return true;}else{return false;}}public int Get_Number() //得到这个单词的编码{for (int i = 0; i < 41; i++){if (string.Equals(cache, Key[i].key_name)){return Key[i].number;}}{return 0;}}public void retrace() //退回一个单词{if (ch != '\0'){index--;}private void Get_Word(){int count;GetNotKong();if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {ConCat();GetChar();while (IsLetter() || IsDigit()){ConCat();GetChar();}retrace();count = Get_Number();temp.key_name = cache;if (count == 0){temp.number = 0;}else{temp.number = Key[count].number;}}else if (ch >= '0' && ch <= '9'){ConCat();GetChar();while (IsDigit()){ConCat();GetChar();}retrace();temp.key_name = cache;temp.number = 1;}else if (ch == '+')ConCat();GetChar();if (ch == '+'){ConCat();temp.key_name = cache;temp.number = 39;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '-'){ConCat();GetChar();if (ch == '-'){ConCat();temp.key_name = cache;temp.number = 40;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '<'){ConCat();GetChar();if (ch == '='){ConCat();temp.key_name = cache;temp.number = 26;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '>'){ConCat();GetChar();if (ch == '='){ConCat();temp.key_name = cache;temp.number = 25;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '='){ConCat();GetChar();if (ch == '='){ConCat();temp.key_name = cache;temp.number = 21;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '!'){ConCat();GetChar();if (ch == '='){ConCat();temp.key_name = cache;temp.number = 24;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '&'){ConCat();GetChar();if (ch == '&'){ConCat();temp.key_name = cache;temp.number = 27;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '|'){ConCat();GetChar();if (ch == '|'){ConCat();temp.key_name = cache;temp.number = 28;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else{ConCat();temp.key_name = cache;temp.number = Get_Number();}}}}六:实验截图(1)我测试的程序为void main(){ int a=20;int b=15;if(a==20)printf("A");if(b==20)printf("B");}七:实验心得通过这次实验、我对于词法分析需要做的任务有了一个更加深刻的理解。

实验一:词法分析

实验一:词法分析
实验一: 实验一:词法分析
实验内容:实现标准C语言词法分析器。 实验内容:实现标准C语言词法分析器。 实验要求: 实验要求:
(1)单词种别编码ቤተ መጻሕፍቲ ባይዱ求 基本字、运算符、界符: 基本字、运算符、界符:一符一种 标识符:统一为一种; 标识符:统一为一种; 常量:按类型编码; 常量:按类型编码; 词法分析工作过程中建立符号表、常量表。 (2)词法分析工作过程中建立符号表、常量表。 并以文本文件形式输出。 并以文本文件形式输出。 (3)词法分析的最后结果以文本文件形式输出。 词法分析的最后结果以文本文件形式输出。
• (2) 测试用例设计 • 设计测试用例,测试用例中包括测试数据、 操作方法、预期结果。为了检查函数是否 能抗拒意外,测试用例应包括合理的输入 和不合理的输入。
• 3. 上机调试 • 对程序进行编译,纠正可能出现的语法错 误,进行初步调试,能够正确运行后用测 试用例对系统进行全面的测试,直至能够 得出完全满意的结果。
• 1. 模块设计 • 将程序分成合理的多个模块(函数),每 个模块做具体的同一事情。
• 2.设计方案描述 设计方案描述 • 模块关系简图、流程图、全局变量、函数 接口等。 • (1) 函数设计 • 系统中每个函数的设计,包括调用方式和 数据传递方式设计、实现功能逻辑设计和 出错处理设计,给出输入、输出、处理流 程。如果是编译器已经提供的函数,可以 只做调用方式和数据传递方式设计。
• 4. 编程时注意编程风格 • 空行的使用、注释的使用、缩进的使用等。
• • • • • • • • • • • • • • • •
5. 整理实验报告 实验报告格式: 1. 姓名 班级 学号 2. 实验报告人 报告时间 3. 实验名称 4. 实验目的 5. 实验要求 6. 实验内容 (实验报告的主要部分 ) (1)功能描述:该程序具有什么功能? (2)写出试验方案 (3)程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;函数之间的 调用关系图。 (4)程序总体执行流程图 7. 实验过程记录: 出错次数、出错严重程度、解决办法摘要。 8. 实验总结 ( 实验心得 ) 实验过程中遇到了问题、如何克服的、收获有哪些?

词法分析实验报告心得(3篇)

词法分析实验报告心得(3篇)

第1篇一、实验背景词法分析是编译原理中的一项基本任务,它将源程序中的字符序列转换成一系列具有独立意义的记号(Token)。

本次实验旨在通过词法分析实验,加深对词法分析过程的理解,掌握词法分析器的实现方法,并提高编程能力。

二、实验目的1. 理解词法分析的基本概念和过程。

2. 掌握词法分析器的实现方法。

3. 提高编程能力,为后续编译原理的学习打下基础。

三、实验内容本次实验采用Java语言编写词法分析器,实现了对C语言源程序的词法分析功能。

具体实验内容包括:1. 定义词法分析器类,包含状态转移表、符号表等数据结构。

2. 设计状态转移函数,实现字符序列到Token的转换。

3. 实现词法分析器的入口函数,接收源程序字符串,输出Token序列。

四、实验步骤1. 创建词法分析器类,定义状态转移表、符号表等数据结构。

2. 设计状态转移函数,根据输入字符和当前状态,输出下一个状态和对应的Token。

3. 实现词法分析器的入口函数,接收源程序字符串,初始化状态和位置指针,遍历源程序字符序列。

4. 在遍历过程中,根据状态转移函数输出Token,并更新状态和位置指针。

5. 当遇到输入字符串结束时,输出剩余的Token,并结束词法分析过程。

五、实验心得1. 词法分析是编译过程中的第一步,它将源程序中的字符序列转换成具有独立意义的Token,为后续的语法分析和语义分析提供基础。

2. 在实现词法分析器时,需要仔细分析源程序中的字符序列,确定状态转移表和符号表的内容。

这有助于提高词法分析器的准确性和效率。

3. 在编写状态转移函数时,要考虑各种可能的输入情况,确保能够正确处理各种字符序列。

同时,要注意状态转移函数的健壮性,避免出现错误。

4. 在实现词法分析器时,需要关注数据结构的组织方式。

合理的数据结构可以提高程序的可读性和可维护性。

5. 通过本次实验,我深刻体会到编程的乐趣和挑战。

在实现词法分析器过程中,我不断学习新的知识,提高了解决问题的能力。

词法分析实验报告

词法分析实验报告

编译原理实验报告实验名称:______编译原理词法分析___实验类型:________________________ _指导教师:___ 曾立胜______________ 专业班级:___ _软件1105________ ___ 姓名:_____ 王永强______________ 学号:______ 20111598____________ 实验地点:______东六E109___ ________ 实验成绩:____________________________日期:2013 年4 月2日实验一词法分析一、实验目的运用理论课中的知识编写一段程序,此程序能对于给定的源程序,从组成源程序的字符行中寻找出单词,并给出它们的种别和属性——输出二元组序列。

以便提供给语法分析的时候使用。

要求能识别所有的关键字,标志符等,并且能够对出先的一些词法规则的错误进行判断和必要的处理。

通过此次试验能对实验环境更加熟悉,对程序的编写和调试更加熟练,能把理论知识和代码相结合。

二、实验设计1.原理:读入源程序,得到单词表如图所示源程序单词表2.设计方法:在扫描源程序字符串时一旦识别出关键字、分隔符、标识符、无符号之一,即以单词形式,各类单词均采用相同的结构,即二元式编码形式存储。

每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直至整个源程序全部扫描完毕并形成相应的单词表。

3.设计过程:通过test语言的词法规则,把规则转化为一种方法,再将此方法用代码编写出来。

4.设计结果:得到一个能识别test语言词法的源程序代码,可以通过此代码分析由test语言编写的源程序是否有语法错误,并且指出错误位置。

最终得到与源程序代码对应的单词表,为接下来的语法分析和语义分析奠基。

三、实验过程过程:1.根据书中test语言代码,得到一个基本的词法分析代码。

2.根据实验要求,修改词法分析代码得到符合要求的代码。

3.修改过程中遇到问题,及时更正。

实验一词法分析

实验一词法分析

实验一词法分析一、实验目的通过设计、编写和调试词法分析程序,了解词法分析程序的作用,组成结构,不同种类单词的识别方法,掌握由单词的词法规则出发,画出识别单词的状态转换图,然后在用程序实现词法分析程序设计方法。

二、词法规则1、注释用{和}括起来。

注释体中不能有{。

注释可以出现在任何记号的后面。

2、记号间的空格可有可无,但关键字前后必须有空格、换行、程序的开头或者结尾的原点。

3、标识符的记号id 与以字母开头的字母数字串相匹配:Letter->[a-zA-Z]Digit->[0-9]Id->letter (letter | digit)*4、记号num与无符号整数相匹配:Digits->digit digit*Optional_fraction -> . Digits | ɛOptional_exponent->(E(+ | - | ɛ ) digits) | ɛNum ->digits optional_fraction optional_exponent5、关键字要被保留且在文法中以黑体出现6、关系运算符(relop )指:=、<、<>、<=、>=、>7、Addop: + 、 - 、or8、Mulop :*、/ 、div 、mod 、and 9、Assignop : :=三、词法分析程序详细设计及判别状态图1、无符号数(可带小数和指数)的状态转换图:01234567数字数字数字E/e数字.E/e+/-数字数字其他数字其他其他2、3、标识符/关键字的状态转换图:21字母字母或数字其他程序详细设计:初始化打开源文件源程序结束?读入一行到StrLine中Fgets()缓冲区空?读取单词的第一个字符ch根据第一个字符进行分类JudgeFirstLetter(ch)识别数值常数RecogDigit()识别标识符/关键字RecogIdentifier()识别标点/操作符RecogPunc()是关键字?IsKey()是否合法?插入队列YNYN数字字母其他符号NY报错Error()N关闭源文件Y 词法分析结束四、开发环境本程序在Microsoft Visual C++ 6.0环境中编写,无特殊编译要求。

实验一(词法分析)

实验一(词法分析)

实验一词法分析一.实验目的1、学会针对DFA转换图实现相应的高级语言源程序。

2、深刻领会状态转换图的含义,逐步理解有限自动机。

3、掌握手工生成词法分析器的方法,了解词法分析器的内部工作原理。

二.实验内容计算机程序设计语言的编译程序的词法分析部分实现。

给出算法的流程图及有穷状态自动机的模型(可以用矩阵或者状态图表示)从左到右扫描每行该语言源程序的符号,拼成单词,换成统一的内部表示(token)送给语法分析程序。

为了简化程序的编写,有具体的要求如下:(1)数仅仅是整数。

(2)空白符仅仅是空格、回车符、制表符。

(3)代码是自由格式。

(4)注释应放在花括号之内,并且不允许嵌套三.实验要求要求实现编译器的以下功能:(1)按规则拼单词,并转换成二元式形式(2)删除注释行(3)删除空白符 (空格、回车符、制表符)(4)列表打印源程序,按照源程序的行打印,在每行的前面加上行号,并且打印出每行包含的记号的二元形式(5)发现并定位错误词法分析进行具体的要求:(1)记号的二元式形式中种类采用枚举方法定义;其中保留字和特殊字符是每个都一个种类,标示符自己是一类,数字是一类;单词的属性就是表示的字符串值。

(2)词法分析程序当识别一个单词完毕,采用返回值的形式返回符号的种类,同时采用程序变量的形式提供当前识别出记号的属性值。

(3)标示符和保留字的词法构成相同,为了更好的实现,把语言的保留字建立一个表格存储,这样可以把保留字的识别放在标示符之后,用识别出的标示符对比该表格,如果存在该表格中则是保留字,否则是一般标示符。

(选做)四.实验结果(1)测试用例(2)实验结果的屏幕截图五.实验总结。

实验一词法分析

实验一词法分析

编译原理实验一词法分析1.实验目的通过实验掌握词法分析的理论、原理和方法,为语法分析做准备。

2.实验内容:a)十六进制数识别器:规定是:必须以十六进制数字打头,以H结尾,十六进制数中允许使用的数字为0-9,字母为A,B,C,D,E, F(分别表示0~15)。

试设计一个DFA,使它能识别无符号的十六进制整数,并编制相应的识别程序。

输入:学生自行确定符号串的输入形式,如键盘输入、文本文件、字符数组等。

输出:标识出规范的符号串与不合规范的符号串。

b)词法分析:设计、编制、调试一个识别一个Little语言单词的词法分析程序(见附录1)。

输入:学生自行确定符号串的输入形式,如键盘输入、文本文件、字符数组等。

输出:二元组。

3.实验要求:(1)上机前编写完整的实验报告,报告中要体现分析→设计→实现等几个过程;如无实验报告,则取消本次上机资格,实验成绩以0分记。

(2)严禁相互抄袭,否则实验成绩以0分记;(3)有完整的源代码,源码有规范的注释,无明显的语法错误;4.实验步骤(1)分析与设计a、文法:该语言的十六进制,如:0aH,77H,7BH等由以数字打头及以H结尾;该语言的标识符,如:Num,a3,go等由A到Z(or a到z)和0至9所组成;该语言的无符号的十进制,如:8,90,123等由0到9之间的任意数字组成。

由以上可得出该语言的文法可表示如下:G(S) = (VN,VT,P,S)其中VN={S,X’,Y’,Z’,M’,W’,α,β,γ,μ,υ,ω}VT= {0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,G,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z}α= 0|1| 2|3|4|5|6|7|8|9β= a|b|c|d|e|f|A|B|C|D|E|Fγ=g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|G|H|I|G|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|ZS →X’|Y’|Z’X’→υ|υM’M’→ω|ωM’υ→β|γω→α|β|γY’→α|αY’Z’→αH|αW’HW’→μ|μW’μ→α|β可见,上式方法中,X’表示出了语言的标识符,而Y’表示出了语言的无符号的十进制,Z’表示出了语言中的十六进制。

实验一、词法分析

实验一、词法分析

实验一 词法分析目的:理解词法分析的功能,熟悉词法分析程序的构造。

内容:(1)定义语言子集的单词表1:单词-内码表模式1(2)构造自动机若考虑保留字和标识符,则可采用如下两种模式:① 模式1:将所有单词统一编制自动机(如右上图,识别int 、if 的自动机)② 模式2:将所有系统保留字和标识符统一识别,因保留字从构成规则上看是标识符的一个子集。

注:加*的终态使用了超前搜索。

说明: (a )关于运算符,这里只用前缀为+作为例子。

(b )非终态编号<100,终态>100,便于以后处理 (c )内码=状态编号-100实验要求分两个层次: (a )考虑到本实验不宜太难,基本要求只实现算术四则运算符、实数(和后续实验结合起来最终可实现一个文本计算器)。

(b )较高要求实现标识符及保留字,建立符号表登记标识,只考虑标识符的名称,类型属性。

(3)编码① 获取有效字符char getEffChar(){….}② 状态转换图的实现//硬编码法,此法代码冗长,不推荐。

int getNextState(int state, char input) { if(state==0 || input==’+’) return 1;if(state==1) {if( input==’+’) return 108;if( input==’=’) return 109;return 107;}…}//提示:数字标识符的判断可自定义函数。

建议用查表法(即转换成三元组),如下表。

表2:三元组表③实现跳转int getToken() {state=0;while(state<100) {c=getEffChar();state=getNextState(state,c);}return state-100; //将终态转换成内码。

}④主程序主程序必须考虑数据的录入,结果的输出。

这里不再详述,以下只是主要处理代码片段。

词法分析实验报告(实验一)

词法分析实验报告(实验一)

词法分析实验报告(鲍小伟20032320)一.实验目的:通过设计、编程、调试出一个具体词法分析程序,加深对词法分析原理的理解,掌握其设计方法。

二.实验内容:用C/C++实现对PASCAL的子集程序设计语言的词法识别程序。

三.实验要求与原理:(1)实验要求:将该语言的源程序,即相应字符流转换成内部表示,并对标识符填写相应的符号表供编译程序以后各阶段使用,输出的单词符号格式为二元组(单词种别,单词在标识符表中的地址),标识符表格式有“序号”和“标识符本身的值”两项。

写出设计报告,内容为:状态转换图、单词符号及内部表示、符号表、出错处理、编程方法等。

(2)实验原理:状态转换图:空白8923单词符号及内部表示:标志符表和常数表:void getchar();//将下一输入字符读到ch中,指针后移一字符位置void getbc();//保证ch是一个非空白字符void concat();//将ch连接到字符串stroken的末尾void retract();//置ch为空白字符,指针前移一字符位置int isdigit();//判断是否整数int isletter();//首字母的判断int reserve();//对stroken进行关键字表的查找,返回其编码值int insertid();//将stroken中的标识符插入符号表,返回在符号表中的位置int insertconst();//将stroken中的常数插入常数表,返回在常数表中的位置四.主要源代码:Scanner::Scanner(char str[], int n) //构造函数{strcpy(buffer, str);length = n;i = j = 0;}int Scanner::isdigit()//判断是否整数{if(ch>='0' && ch<='9')return 1;elsereturn 0;}int Scanner::isletter()//首字母的判断{if((ch>='a' && ch<='z') || (ch>='A' && ch<='Z'))return 1;elsereturn 0;}void Scanner::getchar() //将下一输入字符读到ch中,指针后移一字符位置{ch = buffer[i];i++;}void Scanner::getbc() //保证ch是一个非空白字符{while(ch == ' ')getchar();}void Scanner::concat() //将ch连接到字符串stroken的末尾{strtoken[j] = ch;j++;}void Scanner::retract() //置ch为空白字符,指针前移一字符位置{ch = ' ';i--;}int Scanner::reserve() //对stroken进行关键字表的查找,返回其编码值{int i, flag = 0;for(i=0; i<15; i++){if( strncmp(reservechar[i],strupr(strtoken), j) == 0 ){flag = 1;break;}}if(flag == 1) return i+1;else return 0;}int Scanner::insertid() //将stroken中的标识符插入符号表,返回在符号表中的位置{for(int a = 0; a < m; a++)for(int b = 0; b < x[a]; b++)if( strncmp(&id[a][0], strtoken, j) == 0 ){return m+1;break;}for(a = 0; a < j; a++)id[m][a] = strtoken[a];x[m] = j;m++;return m;}int Scanner::insertconst() //将stroken中的常数插入常数表,返回在常数表中的位置{for(int i = 0; i < j; i++)cst[n][i] = strtoken[i];y[n] = j;n++;return n;}void Scanner::scan(){while(i < length){j = 0;int code, value;strcpy(strtoken, " "); //置strtoken为空串getchar();getbc();if(isletter()) //如果打头的是字母{while(isletter() || isdigit()){concat();getchar();}retract();code = reserve();if(code == 0) //如果扫描到的是标识符{value = insertid();cout<<"<34,"<<value<<">"<<'\n';}else cout<<"<"<<code<<",*>"<<'\n'; //如果扫描到的是关键字}else if(isdigit()) //如果打头的是数字{while(isdigit()){concat();getchar();}retract();value = insertconst();cout<<"<33,"<<value<<">"<<'\n';}else if(ch == '+')cout<<"<16,*>"<<'\n';else if(ch == '-')cout<<"<17,*>"<<'\n';else if(ch == '*')cout<<"<18,*>"<<'\n';else if(ch == '/')cout<<"<19,*>"<<'\n';else if(ch == '=')cout<<"<20,*>"<<'\n';else if(ch == '<'){getchar();if(ch == '>')cout<<"<21,*>"<<'\n';else if(ch == '=')cout<<"<23,*>"<<'\n';else{retract();cout<<"<22,*>"<<'\n';}}else if(ch == '>'){getchar();if(ch == '=')cout<<"<25,*>"<<'\n';else{retract();cout<<"<24,*>"<<'\n';}}else if(ch == '.')cout<<"<26,*>"<<'\n';else if(ch == ',')cout<<"<27,*>"<<'\n';else if(ch == ';')cout<<"<28,*>"<<'\n';else if(ch == ':'){getchar();if(ch == '=')cout<<"<30,*>"<<'\n';else{retract();cout<<"<29,*>"<<'\n';}}else if(ch == '(')cout<<"<31,*>"<<'\n';else if(ch == ')')cout<<"<32,*>"<<'\n';else if(ch == '{'){while(ch != '}')getchar();}else cout<<"出错!"<<'\n';}}void main(void){fstream file;file.open("F:/20032320/20032320.txt", ios::in||ios::nocreate); //以只读方式打开file.unsetf(ios::skipws); //不跳过文本中的空格char buffer[100]; //缓冲区定义cout<<"扫描结果如下所示"<<'\n';while(file.getline(buffer, 100)){Scanner SS(buffer, strlen(buffer));SS.scan();}cout<<"标识符表如下:\n"<<"编号\t"<<"值\n";for(int i=0; i<m; i++){cout<<i+1<<'\t';for(int j=0; j<x[i]; j++)cout<<id[i][j];cout<<'\n';}cout<<"常数表如下:\n"<<"编号\t"<<"值\n";for(i=0; i<n; i++){cout<<i+1<<'\t';for(int j=0; j<y[i]; j++)cout<<cst[i][j];cout<<'\n';}}五.运行结果:程序的运行结果如下图所示:。

实验一词法分析

实验一词法分析
cout<<"输出该非标示符:";
for (int i=0;i<50;i++)
{
cout<<a[i];
}
cout<<endl;
cout<<"------------字符串判断完毕------------"<<endl;
}
system("pause");
return 0;
}
Vc6.0新建空工程+源文件
{
b[k]=a[t+1]; //存放是标识符的字符
k++;
}
else if((a[t+1]>='0')&&(a[t+1]<='9')) //识别是非标识符的字符
{
c[m]=a[t+1]; //存放是单个数字的字符
m++;
}
else{
e[p]=a[t+1]; //存放是非标识符的字符
p++;
}
}
cout<<"--------------判断结果----------------"<<endl;
char a[50]={0}; //存放字符串
char b[50]={0}; //存放标志符
char d[50]={0}; //存放非标识符
cout<<"请输入字符串(以$结束):"<<endl;
for(int i=0;i<50;i++)
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

编译原理实验一词法分析1.实验目的通过实验掌握词法分析的理论、原理和方法,为语法分析做准备。

2.实验内容:a)十六进制数识别器:规定是:必须以十六进制数字打头,以H结尾,十六进制数中允许使用的数字为0-9,字母为A,B,C,D,E, F(分别表示0~15)。

试设计一个DFA,使它能识别无符号的十六进制整数,并编制相应的识别程序。

输入:学生自行确定符号串的输入形式,如键盘输入、文本文件、字符数组等。

输出:标识出规范的符号串与不合规范的符号串。

b)词法分析:设计、编制、调试一个识别一个Little语言单词的词法分析程序(见附录1)。

输入:学生自行确定符号串的输入形式,如键盘输入、文本文件、字符数组等。

输出:二元组。

3.实验要求:(1)上机前编写完整的实验报告,报告中要体现分析→设计→实现等几个过程;如无实验报告,则取消本次上机资格,实验成绩以0分记。

(2)严禁相互抄袭,否则实验成绩以0分记;(3)有完整的源代码,源码有规范的注释,无明显的语法错误;4.实验步骤(1)分析与设计a、文法:该语言的十六进制,如:0aH,77H,7BH等由以数字打头及以H结尾;该语言的标识符,如:Num,a3,go等由A到Z(or a到z)和0至9所组成;该语言的无符号的十进制,如:8,90,123等由0到9之间的任意数字组成。

由以上可得出该语言的文法可表示如下:G(S) = (VN,VT,P,S)其中VN={S,X’,Y’,Z’,M’,W’,α,β,γ,μ,υ,ω}VT= {0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,G,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z}α= 0|1| 2|3|4|5|6|7|8|9β= a|b|c|d|e|f|A|B|C|D|E|Fγ=g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|G|H|I|G|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|ZS →X’|Y’|Z’X’→υ|υM’M’→ω|ωM’υ→β|γω→α|β|γY’→α|αY’Z’→αH|αW’HW’→μ|μW’μ→α|β可见,上式方法中,X’表示出了语言的标识符,而Y’表示出了语言的无符号的十进制,Z’表示出了语言中的十六进制。

∵上式G(S)文法中,各式右边只有单个的终结符号∴显然,以上文法G(S)已是正规文法。

(2)正规文法转成正规式:具体步骤如下:∵ M’→ω|ωM’可表示为M’→ω*ωW’→μ|μW’可表示为W’→μ*μZ’→α|αZ’可表示为Z’→α*α∴转换成正规表达式为:S=υ| υω*ω|αH | αμ*μH |α*α代入可得:S= (β|γ) | (β|γ) (α|β|γ)*(α|β|γ) |αH | α(α|β)* (α|β)H |α*α(3)正规式转成NFA(分裂法)初始的NFA图下所示:图1 初始NFA图经过替换规则替换后得到的最终NFA图如下所示:图2 最终的NFA图(4)NFA转成DFA及DFA最小化(造表法)对应以上的NFA图,我们可用造表法来表示如下:显然,由图可看出,状态2与状态5等价,而状态1与状态3等价,这里省去状态3和状态5,并将所以指向状态3的状态都指向状态1,指向状态5的都指向状态2。

由此可画出最小化的DFA图如下:图3 最小化的DFA图可见,终结状态1表示出了无符号的十进制,终结状态2表示出了标识符,状态6表示出了十六进制的整数。

b、单词的BNF表示<标识符>-> <字母><字母数字串><字母数字串>-><字母><字母数字串>|<数字><字母数字串>|<下划线><字母数字串>|ε<无符号整数>-> <数字><数字串><数字串>-> <数字><数字串> |ε<加法运算符>-> +<减法运算符>-> -<大于关系运算符>-> ><大于等于关系运算符>-> >=由此可知,需将单词分为五种:关键字1 标识符2 常数3 运算符4 分隔符5(2)编码实现a、#include <stdio.h>main(int argc,char *argv[]){int i,j,state,ERROR=-1;/* state控制状态的转移1表示0~9数字,2表示字母,4表示a~f,6表示H,0为未输入状态* ERROR=-1表示未输入任何字符串=1表示输入出错*/char c; /* 暂时存放所取得的一个字符*/char *string[]={"","Unsigned Integer","Identifier","","","","Hex"};/*输出结果时用*/ for(i=1;i<argc;i++){state=0; /* 初始态为0 */ERROR=0; /* 控制是否为可识别词or非法字符*/for(j=0;(c=argv[i][j])!='\0';j++){switch(state){case 0:if(c>='0'&&c<='9')state=1;else if((c>='a'&&c<='z')||(c>='A'&&c<='Z'))state=2;else ERROR=1;break;/* ERROR=1,表示当前字符c为非法字符。

* 即此时无状态可转向。

*/case 1:if(c>='0'&&c<='9')state=1;else if((c>='a'&&c<='f')||(c>='A'&&c<='F'))state=4;else if (c=='H')state=6;elseERROR=1;break;case 2:if((c>='a'&&c<='z')||(c>='A'&&c<='Z')||(c>='0'&&c<='9'))state=2;elseERROR=1;break;case 4:if((c>='0'&&c<='9')||(c>='a'&&c<='f')||(c>='A'&&c<='F'))state=4;else if(c=='H')state=6;elseERROR=1;break;case 6:ERROR=1;break;}/*end switch*/if(ERROR==1)break; /* 退出内for的循环,完成一个词的分析。

*/ }/*end inside-for*/if(ERROR==1)printf("%-15s is a un-identify word!\n",argv[i]);else if(ERROR==0)printf("%-15s is a %s\n",argv[i],string[state]);}/*end outside-for*//*未输入任何字符串时(除文件名外)*/if(ERROR==-1) printf("You input nothing!\n");exit(0); /*正常退出程序*/}/*end main*/b、#include<string.h>#include<stdio.h>#include<stdlib.h>#include<ctype.h>//定义关键字char *table[7]={"continue","main","int","if","then","else","return"},TOKEN[20],ch; bool zimu(char ch)//判断是否为字母{if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')return true;elsereturn false;}//判断是否为数字bool shuzi(char ch){if(ch>='0'&&ch<='9')return true;elsereturn false;}int lookup(char *TOKEN) //关键字匹配函数,查询所述程序中的关键字{int m,i;for(i=0;i<6;i++){if((m=strcmp(TOKEN,table[i]))==0)return 1;}return 0;}void out(int c,char *TOKEN) //输出函数{ printf("(%d,%s)\n",c,TOKEN);}void scanner(FILE *fp) //扫描函数{char TOKEN[20]={'\0'};char ch;int i;ch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符if(zimu(ch) //判断该字符是否是字母,若ch指的是字母,返回非0,否则返回0 { TOKEN[0]=ch;ch=fgetc(fp); //fgetc(fp)从数据流中区下一个字符i=1;while(shuzi(ch)|| zimu(ch)) //判断该字符是否是字母或数字{TOKEN[i]=ch;ch=fgetc(fp);i++;}fseek(fp,-1,1);if(lookup(TOKEN)) //判断是关键字还是普通的标识符out(1,TOKEN);elseout(2,TOKEN);}else if(shuzi(ch)){TOKEN[0]=ch;ch=fgetc(fp); //fgetc(fp)从数据流中区下一个字符i=1;while(shuzi(ch)) //判断该字符是否是字母或数字{TOKEN[i]=ch;ch=fgetc(fp);i++;}fseek(fp,-1,1);out(3,TOKEN);}//判断运算符并输出else if(ch=='+'){ TOKEN[0]=ch; out(4,TOKEN); }else if(ch=='-'){ TOKEN[0]=ch; out(4,TOKEN); }else if(ch=='*'){ TOKEN[0]=ch; out(4,TOKEN); }else if(ch=='/'){ TOKEN[0]=ch; out(4,TOKEN); }else if(ch=='='){ TOKEN[0]=ch; out(4,TOKEN); }else if(ch=='>'){ TOKEN[0]=ch; out(4,TOKEN); }else if(ch=='<'){ TOKEN[0]=ch; out(4,TOKEN); }else if(ch=='>='){ TOKEN[0]=ch; out(4,TOKEN); }else if(ch=='<='){ TOKEN[0]=ch; out(4,TOKEN); }else if(ch=='!='){ TOKEN[0]=ch; out(4,TOKEN); }//判断分隔符并输出else if(ch==','){ TOKEN[0]=ch; out(5,TOKEN); }else if(ch==';'){ TOKEN[0]=ch; out(5,TOKEN); }else if(ch=='{'){ TOKEN[0]=ch; out(5,TOKEN); }else if(ch=='}'){ TOKEN[0]=ch; out(5,TOKEN); }else if(ch=='('){ TOKEN[0]=ch; out(5,TOKEN); }else if(ch==')'){ TOKEN[0]=ch; out(5,TOKEN); }}main(){FILE *fp;//读取文件内容,并返回文件指针,该指针指向文件的第一个字符if((fp=fopen("E:\\222.txt","r"))==NULL){fprintf(stderr,"error opening.\n");exit(1);}do{ch=fgetc(fp);if(ch=='#') //文件以#结尾,作为扫描结束条件break;if(ch==' ') //如果是空格,自动跳到下个字符scanner(fp);else{fseek(fp,-1,1); //如果不是空格,则回退一个字符并扫描scanner(fp);}}while(ch!='#');return 0;}(3)系统调试a、b、5.实验总结通过此次实验,使我意识到在做实验之前一定要认真复习课本内容和老师的要求以此来确定该实验要我们实现的是什么,怎么实现,每一步的步骤都要按照流程图认真的去完成,做实验不能有半点马虎。

相关文档
最新文档