1、实 验 报 告 学号: 姓名: 专业:计算机科学和技术 班级:2班 第9周 课程名称 编译原理课程设计 试验课时 8 试验项目 手工结构Tiny语言词法分析器 试验时间 7-10周 试验目标 熟悉Tiny语言词法;结构DFA;设计数据类型、数据结构;用C++实现Tiny语言词法分析器 试验环境 Windows 10 专业版 Microsoft Visual Studio 试验内容(算法、程序、步骤和方法) 一、Tiny语言记号 Reserved words Special Symbols Other if + n
2、umber(1 or more digits)
then
-
else
*
end
<
repeat
=
until
/
identifier(1 or more letters)
read
(
write
)
;
:=
二、结构Tiny语言DFA
ID:letter(letter)*
Number: digit(digit)*
三、依据DFA编写词法分析器
#include
3、 static int rowCounter = 1;//静态变量,用于存放行数 static bool bracketExist = false;//判定注释存在是否,false为不存在 class Lex { public: ofstream output; string line = ""; Lex(string inputLine) { line = inputLine; scan(Trim(line)); rowCounter++; } string Trim(string &str)//函数用于去除每行前后空格 {
4、 int s = str.find_first_not_of(" \t"); int e = str.find_last_not_of(" \t"); str = str.substr(s, e - s + 1); str += "\0"; return str; } void scan(string inputLine) { ofstream output; output.open("SampleOutput.txt", ios::app); string line = inputLine; int i = 0; s
5、tring str = ""; int temp; string token = ""; output << rowCounter << ": " << line << endl;//输出每行 while (line[i] != '\0')//依据DFA扫描并判定 { if (line[i] == '{')//注释 { bracketExist = true; } if (bracketExist == true) { output << "\t" << rowCounter << ": ";
6、
while (line[i] != '}')
{
output << line[i];//不处理,直接输出
if (line[i + 1] != NULL)
{
i++;
}
else
break;
}
if (line[i] == '}')//注释结束
{
output << line[i]< 7、 false)
{
//数字
while (isdigit(line[i]))
{
temp = temp * 10 + line[i];
if (!isdigit(line[i + 1]))
{
output << "\t" << rowCounter << ": " << "NUM, val= " << temp - '0' << endl;
}
if (line[i + 1] != NULL&&isdigit(line[i + 1]))
i++;
8、 else
break;
}
temp = 0;
//符号
while (!(isdigit(line[i]) || (line[i] >= 'a'&&line[i] <= 'z') || (line[i] >= 'A'&&line[i] <= 'Z') || line[i] == ' ' || line[i] == '{' || line[i] == '}'))
{
token = token + line[i];
if (isdigit(line[i + 1]) || (line[i + 9、1] >= 'a'&&line[i + 1] <= 'z') || (line[i + 1] >= 'A'&&line[i + 1] <= 'Z') || line[i + 1] == ' ' || line[i + 1] == '{' || line[i + 1] == '}' || line[i + 1] == NULL)
{
if (isToken(token))
{
output << "\t" << rowCounter << ": " << token << endl;
}
else
10、 {
int j = 0;
while (token[j] != '\0')
{
output << "\t" << rowCounter << ": " << token[j] << endl;
j++;
}
}
}
else
{
i++;
continue;
}
if (line[i + 1] != NULL)
i++;
else
break;
11、
}
token = "";
//字母
while ((line[i] >= 'a'&&line[i] <= 'z') || (line[i] >= 'A'&&line[i] <= 'Z'))
{
str = str + line[i];
if (!((line[i + 1] >= 'a'&&line[i + 1] <= 'z') || (line[i + 1] >= 'A'&&line[i + 1] <= 'Z')))
{
if (isResearvedWord(str)) //判定 12、是否是保留字
{
output << "\t" << rowCounter << ": " << "Reversed Word: " << str << endl;
break;
}
else
{
output << "\t" << rowCounter << ": " << "ID, name= " << str << endl;
break;
}
}
if (line[i + 1] != NULL)
i++;
13、 }
str = "";
if (line[i + 1] != NULL)
{
i++;
}
else
break;
}
if (line[i + 1] == NULL)
{
if (line[i] == ';')
output << "\t" << rowCounter << ": " << line[i];
break;
}
}
//清空,以备下一行读取
line = "";
str = "";
t 14、emp = 0;
token = "";
output << endl;
output.close();
}
bool isResearvedWord(string s)//存放保留字,并判定
{
string reservedWord[8] = { "if", "then", "else", "end", "repeat", "until", "read", "write" };
bool judge = false;
for (int i = 0; i < 8; i++)
{
if (s == reservedWord[i] 15、)
{
judge = true;
break;
}
}
return judge;
}
bool isToken(string s)//存放符号,并判定
{
string token[10] = { "+", "-", "*", "/", "=", "<", "(", ")", ";", ":=" };
bool judge = false;
for (int i = 0; i < 10; i++)
{
if (s == token[i])
{
judge = true;
16、break;
}
}
return judge;
}
};
int main()
{
ifstream input;
input.open("SampleInput.tny");
string line[50];
int i = 0;
while (getline(input, line[i]))
{
//cout << line[i] << endl;
i++;
}
input.close();
cout << endl << endl << "Reading source file completed!!" 17、<< endl;
int j = 0;
remove("SampleOutput.txt");
for (j = 0; j < i; j++)
{
Lex lex(line[j]);
}
cout << endl << endl << "Writing file completed!!" << endl << endl << endl;
return 0;
}
四、关键数据结构
string line[]:用于存放每一行字符,并逐一读取分析。
string token[]:用于存放TINY语言符号,并调用遍历进行判定。
string rese 18、rvedWord[]:用于存放TINY语言保留字,遍历进行判定,若为真,则输出Reserved word。
static int rowCounter:静态变量,存放行号,每创建一个类实例便加一。
int temp:用于存放数字,并输出。
static int bracketExist:静态变量,标识注释是否存在。
string token, str分别用于临时存放读取符号字母串。
五、算法总结
建立Lex class,并读取每一行,创建Lex实例,在Lex中处理。先判定是否在注释范围内,若是,则输出注释内容,直至产生“}”字符。若不在注释区内,则读取单个字符,依据DF 19、A进行判定。若为符号,则当下一个字符不是符号时输出;若为数字,则继续往下读,直至下一个字符不是数字为止,输出。若为字母,继续读取,直至下一个字符不是字母,把这一串字母和预先定义保留字比对,若是,则输出“Reserved word”,若不是,则输出“ID,name=”字样。一行处理完成,便开始创建下一行实例,直至文件尾。
数据统计
和计算
Tiny测试程序
结 论
(结 果)
1: { Sample program
1: { Sample program
2: in TINY language -
2: in TINY language - 20、
3: computes factorial
3: computes factorial
4: }
4: }
5: read x; { input an integer }
5: Reversed Word: read
5: ID, name= x
5: ;
5: { input an integer }
6: if 0 < x then { don't compute if x <= 0 }
6: Reversed Word: if
6: NUM, val= 0
6: <
6: ID, n 21、ame= x
6: Reversed Word: then
6: { don't compute if x <= 0 }
7: fact := 1;
7: ID, name= fact
7: :=
7: NUM, val= 1
7: ;
8: repeat
8: Reversed Word: repeat
9: fact := fact * x;
9: ID, name= fact
9: :=
9: ID, name= fact
9: *
9: ID, name= x
9: 22、 ;
10: x := x - 1;
10: ID, name= x
10: :=
10: ID, name= x
10: -
10: NUM, val= 1
10: ;
11: until x = 0;
11: Reversed Word: until
11: ID, name= x
11: =
11: NUM, val= 0
11: ;
12: write fact { output factorial of x }
12: Reversed Word: write
12: 23、 ID, name= fact
12: { output factorial of x }
13: end
13: Reversed Word: end
小 结
顺利完成试验,熟悉了Tiny语言和其词法。
依据语言和词法规则,顺利结构DFA。
成功用C++语言,依据结构DFA,实现了Tiny词法分析器。
增强了自己编程能力和水平技巧,尝试了很多以前没有尝试过方法学习到了新知识。
指导老师评 议
成绩评定: 指导老师署名:






