编译原理实验一 词法分析
实验目的
(1)根据 PL/0 语言的文法规范,编写PL/0语言的词法分析程序;或者调研词法分析程序的自动生成工具LEX或FLEX,设计并实现一个能够输出单词序列的词法分析器。
(2)通过设计调试词法分析程序,实现从源程序中分出各种单方法;加深对课堂教学的理解;提高词法分析方法的实践能力。
(3)掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的法。
(4)掌握词法分析的实现方法。
(5)上机调试编出的词法分析程序。
实验内容
根据PL/0语言的文法规范,编写PL/0语言的词法分析程序。要求:把词法分析器设计成一个独立一遍的过程。词法分析器的输出形式采用二元式序列,即:(单词种类, 单词的值)
实验步骤
(1) 根据PL/0语言的单词符号集,分析词法规则,画出识别单词的状态图。
PL/0语言的词汇表:
识别单词的状态图:
(2) 写出关键字、标识符、常数、运算符、界符各个表达式的正则式。
正规式:(设字母为Z,数字为D,运算符为Y,界符为J)
r = Z(Z|D)|D(D)|Y|J
(3)根据正规式画出NFA
r->NFA:
(4)NFA确定化为DFA,并对DFA最小化
DFA(已最小化)
各个终态含义:
2:界符匹配
3:运算符匹配
4:常数匹配
5:基本字匹配,除基本字外的为标识符
(5)程序的算法流程图:
源程序及调试运行
#include<iostream>
#include<string>
using namespace std;
int flag=1; //flag用于判断是关键字还是标识符,为0表示是标识符,为1表示是关键字
void reserved(string str);
int main()
{
string str1,str;
while(cin>>str1) //读入代码
{
str=str+' '+str1;
}
//开始处理读入的代码
int length=str.length();
for(int i=0; i<length; i++)
{
if(str[i]==' '||str[i]=='\n') //当遇到空格或者换行时,跳过该判断继续往下执行
continue;
// 识别常数
else if(isdigit(str[i])) //如果是数字
{
string numbers;
while(isdigit(str[i]))
{
numbers+=str[i];
i++;
}
i--;
cout<<"(number,"<<numbers<<")"<<endl;
}
// 识别基本字/标识符
else if(isalpha(str[i])) //如果是字母
{
string letters;
while(isalpha(str[i]))
{
letters+=str[i];
i++;
}
i--;
reserved(letters);
if(flag==0)
{
cout<<"(ident,"<<letters<<")"<<endl;
flag=1;
}
}
// 识别运算符、界符
else
{
switch(str[i])
// 识别运算符
{
case '+':
cout<<"(plus,+)"<<endl;
break;
case '-':
cout<<"(minus,-)"<<endl;
break;
case '*':
cout<<"(times,*)"<<endl;
break;
case '/':
cout<<"(slash,/)"<<endl;
break;
case '=':
cout<<"(eql,=)"<<endl;
break;
case '<':
i++;
if(str[i]=='>')
cout<<"(neq,<>)"<<endl;
else if(str[i]=='=')
cout<<"(leq,<=)"<<endl;
else
{
i--;
cout<<"(lss,<)"<<endl;
}
break;
case '>':
i++;
if(str[i]=='=')
cout<<"(geq,>=)"<<endl;
else
{
i--;
cout<<"(gtr,>)"<<endl;
}
break;
case ':':
i++;
if(str[i]=='=')
cout<<"(becomes,:=)"<<endl;
else
cout<<"illegal character!"<<endl;
break;
// 识别界符
case '(':
cout<<"(lparen,()"<<endl;
break;
case ')':
cout<<"(rparen,))"<<endl;
break;
case ',':
cout<<"(comma,,)"<<endl;
break;
case ';':
cout<<"(semicolon,;)"<<endl;
break;
case '.':
cout<<"(period,.)"<<endl;
break;
// 其他非法字符输出错误信息
default:
cout<<"illegal character!"<<endl;
break;
}
}
}
return 0;
}
// 识别关键字,若是关键字则直接输出对应的语句,否则说明是标识符,将flag置为0
void reserved(string str)
{
if(str=="begin")
cout<<"(beginsym,begin)"<<endl;
else if(str=="call")
cout<<"(callsym,call)"<<endl;
else if(str=="const")
cout<<"(constsym,const)"<<endl;
else if(str=="do")
cout<<"(dosym,do)"<<endl;
else if(str=="end")
cout<<"(endsym,end)"<<endl;
else if(str=="if")
cout<<"(ifsym,if)"<<endl;
else if(str=="odd")
cout<<"(oddsym,odd)"<<endl;
else if(str=="procedure")
cout<<"(proceduresym,procedure)"<<endl;
else if(str=="read")
cout<<"(readsym,read)"<<endl;
else if(str=="then")
cout<<"(thensym,then)"<<endl;
else if(str=="while")
cout<<"(whilesym,while)"<<endl;
else if(str=="var")
cout<<"(varsym,var)"<<endl;
else if(str=="write")
cout<<"(writesym,write)"<<endl;
else
flag=0;
}