1. 实验要求
手工设计c语言的词法分析器(可以式c语言子集) 处理c语言源程序,过滤掉无用符号,判断源程序中单词的合法性,并分解出正确的单词,以二元组形式存放在文件中
2. 分析与设计
2.1 构造c语言子集
第一类:标识符 letter(letter | digit)* 无穷集 第二类:常数 (digit)+ 无穷集 第三类:保留字 main,int,char,if,else,for,while 第四类:界符 () { } [ ] , ; 第五类:运算符 <、<=、>、>=、=、+、-、*、/,==
2.2 单词符号表
2.3 状态转换图
3. 程序描述
3.1 数据结构
typedef struct
{
string code;
string attr;
}node;
3.2 主要函数
bool isdigit(char c);
bool ischar(char s);
bool isremain(string s);
string read_filter(char *filename);
queue<node> LEX(string s);
void print(queue<node> res);
3.3 算法描述
1.打开源文件source.txt,读取文件所有内容,存放在string s中。 2.对读取的文件进行预处理,从头到尾进行扫描,去除//注释的内容,以及换行符、回车符、制表符。 3.创建队列res(元素为node),用于返回分析结果。 4.对s每个字符从头到尾进行扫描 若当前的字符是空格,则继续扫描下一个字符。 若不是空格: 判断字符是不是字母,若是则进行标识符和保留字的识别; 若这个字符为数字,则进行数字的判断。 否则,依次对这个字符可能的情况进行判断。 每次成功识别了一个单词后,创建新的node t,将单词种别码和单词属性值存入其中,然后将t加入队列res中。 5.将结果存入result.txt文件中
4. 运行测试
5. 源代码
#include <iostream>
#include <string>
#include <vector>
#include<queue>
#include <fstream>
#include <iomanip>
using namespace std;
typedef struct
{
string code;
string attr;
}node;
string remained[7]={"main","int","char","if","else","for","while"};
bool isdigit(char c);
bool ischar(char s);
bool isremain(string s);
string read_filter(char *filename);
queue<node> LEX(string s);
void print(queue<node> res);
bool isdigit(char c)
{
if(c>='0'&&c<='9')
return 1;
return 0;
}
bool ischar(char c)
{
if(c>='a'&&c<='z'||c>='A'&&c<='Z')
return 1;
return 0;
}
bool isremain(string s)
{
for(int i=0;i<7;i++)
{
if(s==remained[i])
return 1;
}
return 0;
}
string read_filter(string filename)
{
string s="";
ifstream infile;
infile.open(filename);
while(!infile.eof())
{
char temp[90];
infile.getline(temp,80);
s+=temp;
s+='\n';
}
string res="";
int len=s.length ();
for(int i=0;i<len-1;i++)
{
if(s[i]=='/'&&s[i+1]=='/')
{
while(s[i]!='\n')
{
i++;
}
}
if(s[i]!='\n'&&s[i]!='\t'&&s[i] != '\r')
res+=s[i];
}
cout<<res;
return res;
}
queue<node> LEX(string s)
{
queue<node> res;
int len=s.length();
node t;
for(int i=0;i<len;i++)
{
if(s[i]!=' ')
{
string temp="";
if(isdigit(s[i]))
{
temp+=s[i];
i++;
while(isdigit(s[i]))
{
temp+=s[i];
i++;
}
i--;
t.code="2";t.attr =temp;
res.push(t);
}
else if(ischar(s[i]))
{
temp+=s[i];
i++;
while(ischar(s[i])||isdigit(s[i]))
{
temp+=s[i];
i++;
}
i--;
if(isremain(temp))
{
t.code=temp;t.attr ="--";
res.push(t);
}
else
{
t.code="1";t.attr =temp;
res.push(t);
}
}
else
{
switch(s[i])
{
case '(':{t.code="10";t.attr ="(";res.push(t);break;}
case ')':{t.code="11";t.attr =")";res.push(t);break;}
case '{':{t.code="12";t.attr ="{";res.push(t);break;}
case '}':{t.code="13";t.attr ="}";res.push(t);break;}
case '[':{t.code="14";t.attr ="[";res.push(t);break;}
case ']':{t.code="15";t.attr ="]";res.push(t);break;}
case ',':{t.code="16";t.attr =",";res.push(t);break;}
case ';':{t.code="17";t.attr =";";res.push(t);break;}
case '<':{
i++;
if(s[i]=='=')
{t.code="19";t.attr ="<=";res.push(t);break;}
else
{t.code="18";t.attr ="<";res.push(t);i--;break;}
}
case '>':{
i++;
if(s[i]=='=')
{t.code="21";t.attr =">=";res.push(t);break;}
else
{t.code="20";t.attr =">";res.push(t);i--;break;}
}
case '=':{
i++;
if(s[i]=='=')
{t.code="23";t.attr ="==";res.push(t);break;}
else
{t.code="22";t.attr ="=";res.push(t);i--;break;}
}
case '+':{t.code="24";t.attr ="+";res.push(t);break;}
case '-':{t.code="25";t.attr ="-";res.push(t);break;}
case '*':{t.code="26";t.attr ="*";res.push(t);break;}
case '/':{t.code="27";t.attr ="/";res.push(t);break;}
default:{t.code="ERROR";t.attr ="--";res.push(t);}
}
}
}
}
return res;
}
void print(queue<node> res)
{
ofstream out("result.txt",ios::out);
int i=0;
while(!res.empty())
{
node temp;
temp=res.front();
res.pop();
out<<setw(4)<<"( "<<setw(4)<<temp.code<<setw(4)<<","<<setw(4)<<temp.attr <<setw(4)<<" )";
out<<" ";
i++;
if(i%5==0)
out<<endl;
}
out.close();
}
void main()
{
string s;
string filename="source.txt";
s=read_filter(filename);
queue<node> res=LEX(s);
}
|