实验一 词法分析器的设计与实现
【实验目的】
通过设计编制一个具体的词法分析程序,加深对词法分析原理的理解,并掌握在对程序
设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
【实验要求】
- 本实验将词法分析器作为一个独立的子程序进行设计,完成词法分析任务。
- 给出进行词法分析的源语言(本实验是 C 语言)或其子集的识别状态转换图。
- 设计单词种别表,采用二元组输出识别出来的单词符号(具体要求见实验内容)。
- 用 C++ 语言(编写词法分析器的程序设计语言)实现上述识别状态转换图,能识别出该源语言或其子集的单词符号。
【实验内容】
- 关键字:main,return,if,else,int,char
- 运算符和界符:(){},;= != > < >= <= == + * /
- 标识符<id>和整数参数<num>
【实验过程和结果】
一、单词种别表设计
单词 |
内部编码 |
单词 |
内部编码 |
单词 |
内部编码 |
单词 |
内部编码 |
main |
0 |
<id> |
1 |
<num> |
2 |
return |
3 |
if |
4 |
else |
5 |
int |
6 |
char |
7 |
( |
8 |
) |
9 |
{ |
10 |
} |
11 |
, |
12 |
; |
13 |
= |
14 |
!= |
15 |
> |
16 |
< |
17 |
>= |
18 |
<= |
19 |
== |
20 |
+ |
21 |
* |
22 |
/ |
23 |
二、构造识别源语言(C语言)单词的状态转换图
图1 状态转换图
三、词法分析器实现
1.流程图设计
图2 程序流程图
2.源程序关键代码
#include<bits/stdc++.h>
using namespace std;
map<string, string> word;
std::map<string, string>::iterator it;
///初始化
void map_init() {
word["main"] = "0";
word["return"] = "3";
word["if"] = "4";
word["else"] = "5";
word["int"] = "6";
word["char"] = "7";
word["("] = "8";
word[")"] = "9";
word["{"] = "10";
word["}"] = "11";
word[","] = "12";
word[";"] = "13";
word["="] = "14";
word["!="] = "15";
word[">"] = "16";
word["<"] = "17";
word[">="] = "18";
word["<="] = "19";
word["=="] = "20";
word["+"] = "21";
word["*"] = "22";
word["/"] = "23";
}
struct node {
string id;
string s;
}aa[10000];
int main() {
map_init();
char ch;
char a;
int len = 0;
string word1;//string变量识别单词
string str;//string变量进行字符识别
cout << "-----------------词法分析器-----------------" << endl;
string dir;
cout << "请输入源文件地址:(路径中请不要包含中文)" << endl;
cin >> dir;
ifstream infile(dir);//文件输入流,文件路径
cout << "请输入目标文件地址:" << endl;
cin >> dir;
ofstream outfile(dir);//文件输出流
ostringstream buf;
while (buf && infile.get(ch)) buf.put(ch);//将文件中的字符读出来
str = buf.str();//将得到的字符储存到string类型变量中
int csize = str.length();
for (int i = 0; i < csize; i++) {//对整个字符串进行遍历
while (str[i] == ' ' || str[i] == '\n') i++;//若最开始为空格或换行符,则将指针的位置往后移
if (isalpha(str[i])) {//对标识符和基本字进行识别,调用库函数isalpha()
word1 = str[i++];
while (isalpha(str[i]) || isdigit(str[i])) {
word1 += str[i++];
}
it = word.find(word1);
if (it != word.end()) {//判断是不是基本字,若为基本字则进行输出
cout << "(" << word[word1] << "," << word1 << ")" << endl;
aa[len].id = word[word1];
aa[len++].s = word1;
}
else {//否则直接输出
cout << "(1" << "," << word1 << ")" << endl;
aa[len].id = "1";
aa[len++].s = word1;
}
i--;
}
else if (isdigit(str[i])) {//判断是不是常数,调用库函数isdigit()
word1 = str[i++];
while (isdigit(str[i])) {
word1 += str[i++];
}
if (isalpha(str[i])) {
cout << "error1!" << endl;
break;
}
else {
cout << "(2" << "," << word1 << ")" << endl;
aa[len].id = "2";
aa[len++].s = word1;
}
i--;
}
else if (str[i] == '<') {//对<,<=分别进行判断
word1 = str[i++];
if (str[i] == '>') {
word1 += str[i];
cout << "(" << word[word1] << "," << word1 << ")" << endl;
aa[len].id = word[word1];
aa[len++].s = word1;
}
else if (str[i] == '=') {
word1 += str[i];
cout << "(" << word[word1] << "," << word1 << ")" << endl;
aa[len].id = word[word1];
aa[len++].s = word1;
}
else if (str[i] != ' ' || !isdigit(str[i]) || !isalpha(str[i])) {
cout << "(" << word[word1] << "," << word1 << ")" << endl;
aa[len].id = word[word1];
aa[len++].s = word1;
}
else {
cout << "error2!" << endl;
break;
}
i--;
}
else if (str[i] == '>') {//对>,>=分别进行判断
word1 = str[i++];
if (str[i] == '=') {
word1 += str[i];
cout << "(" << word[word1] << "," << word1 << ")" << endl;
aa[len].id = word[word1];
aa[len++].s = word1;
}
else if (str[i] != ' ' || !isdigit(str[i]) || !isalpha(str[i])) {
cout << "(" << word[word1] << "," << word1 << ")" << endl;
aa[len].id = word[word1];
aa[len++].s = word1;
}
else {
cout << "error3!" << endl;
break;
}
i--;
}
else if (str[i] == ':') {//对:=进行判断
word1 = str[i++];
if (str[i] == '=') {
word1 += str[i];
cout << "(" << word[word1] << "," << word1 << ")" << endl;
aa[len].id = word[word1];
aa[len++].s = word1;
}
else if (str[i] != ' ' || !isdigit(str[i]) || !isalpha(str[i])) {
cout << "(" << word[word1] << "," << word1 << ")" << endl;
aa[len].id = word[word1];
aa[len++].s = word1;
}
else {
cout << "error4!" << endl;
break;
}
i--;
}
else {//对其他的基本字依次进行判断
word1 = str[i];
it = word.find(word1);
if (it != word.end()) {
cout << "(" << word[word1] << "," << word1 << ")" << endl;
aa[len].id = word[word1];
aa[len++].s = word1;
}
//else {
// cout << "error5!" << endl;
// break;
//}
}
}
//输出流,输出到对应的结果文件中
if (outfile.is_open())
{
for (int i = 0; i < len; i++) {
outfile << "(" << aa[i].id << "," << aa[i].s << ")" << '\n';
}
outfile.close();
}
infile.close();
cout << "输入任意键关闭" << endl;
string s;
cin >> s;
return 0;
}
3.词法分析器运行效果
图3 运行结果图
图4 源文件图
图4 目标文件图
四、实验过程中出现的问题及其解决
程序打包成.exe后在自己的电脑上可以运行,但是在其他电脑上运行失败。通过查找资料,发现可能原因是目标主机没有相关的dll或系统及处理器问题,打包时要把相关的dll也打包进来;
五、C++程序打包
vs是没有#include<bits/stdc++.h>这个万能库的,要自己配置一下。。,去网上随便搜搜就有方法了。
(1)
(2)
(3)
(4)
(5)运行一下,去Debug文件找,不放心发给好基友试试