![](https://csdnimg.cn/release/download_crawler_static/89158029/bg1.jpg)
中北大学大数据学院
实验报告
……………
第
一
针
…………
装
订
线
……………
第
二
针
…………
课程名称 编译原理 学号 学生姓名 教师
专业
计算机科学
实验地点
504
实验时间
2021 年 4 月 16 日
开发环境
软、硬件:软件
开发语言:C++
开发环境:windows10 64 位
实验一名称 词法分析程序(2 学时)
实验目的
理解词法分析在编译程序中的作用;加深对有穷自动机模型的理解; 掌握词法
分析程序的实现方法和技术。
实验内容
选择部分 C 语言的语法成分,设计其词法分析程序,要求能够识别关键字、运算
符、分界符、标识符、常量(至少是整型常量,可以自己扩充识别其他常量)等,并
能处理注释、部分复合运算符(如>=等)。单词以二元式形式输出、输出有词法错误
的单词及所在行号。
实验要求
(1)待分析的简单的语法
关键字:begin if then while do end …
运算符和界符::= + - * / < <= > >= <> = == ; ( ) # , …
其他单词是标识符 id 和整型常数 num,通过以下正规式定义:
id=l(l|d)* (l:letter d:digit)
num=dd*
空格、注释:在词法分析中要去掉。
(2)各种单词符号对应的种别编码(参考这张表,可以不同)
(3)待分析的源程序:
(a)int main()
{
![](https://csdnimg.cn/release/download_crawler_static/89158029/bg2.jpg)
中北大学大数据学院
实验报告
int a=1,b=2;
b/a;
/* 注释部分*/
b>a;
c=a+b;
cout<<c;
return 0;
}
(b)这个待分析程序有词法错误(选做)
while ((a+15)>0)
{
if (2x = = 7)
i3=z;
}
核心代码:(按模块顺序,每一个模块先做简要功能说明及输入输出介绍,再附核心
代码,如果只有代码,没有说明,酌情减分)
#include <iostream>
#include<string>
using namespace std;
char ch = ' ';
//关键字
string key[10] = { "begin","if","then","while","do","end","int","main","return","cout" };
/*判断是否为关键字
输入:字符串
返回:若是,返回关键字种别码;否则返回0*/
int Iskey(string c) {
for (int i = 0; i < 10; i++)
{
//关键字的种别码依次为 begin=1,if=2,then=3,while=4,do=5,end=6 ,int=7,main=8 ,即为 i+1
的值
if (i < 8){
if (c==key[i])
{
return i+1;
}
}
//关键字种别码 return=12,cout=13 ,即为 i+4 的值
else {
if (c == key[i])
{
return i+4;
}
![](https://csdnimg.cn/release/download_crawler_static/89158029/bg3.jpg)
中北大学大数据学院
实验报告
}
}
return 0;
}
/*判断是否为字母
输入:字符
返回:若是,返回1;否则返回0*/
int IsLetter(char c) {
if (((c <= 'z') && (c >= 'a')) || ((c <= 'Z') && (c >= 'A'))) return 1;
else return 0;
}
/*判断是否为数字
输入:字符
返回:若是,返回1;否则返回0*/
int IsDigit(char c) {
if (c >= '0'&&c <= '9') return 1;
else return 0;
}
/*核心子程序
输入:文件读入
功能:对文件中的待分析程序进行词法分析
读入一个字符,对该字符进行判断:
①若为空格或换行,则忽略
②若为字母,则继续往后看直至该字母串或字母数字串结束,并用数组保存该字符串
若为关键字,则输出其关键字及其种别码;
若为标识符,则输出该标识符及标识符的统一种别码。
③若为数字,则继续往后看直至数字串结束,并用数组保存该字符串
输出该整型常数及整型常数的统一种别码。
④为运算符和界符,则看该字符后面是否还有其他的运算符和界符,
若是双字节字符,输出该双字节字符及其种别码(若是/*则为注释,忽略所有注释
内容)
若是单字节字符,输出该运算符或界符及其种别码*/
void analyse(FILE *fpin) {
string arr = "";
while ((ch = fgetc(fpin)) != EOF) {
arr = "";
if (ch == ' ' || ch == '\n') {}
else if (IsLetter(ch)) {
while (IsLetter(ch) || IsDigit(ch)) {
arr = arr + ch;
ch = fgetc(fpin);
}
![](https://csdnimg.cn/release/download_crawler_static/89158029/bg4.jpg)
中北大学大数据学院
实验报告
fseek(fpin, -1L, SEEK_CUR);
if (Iskey(arr)) { cout << "(" << arr << "," << Iskey(arr) << ")" << endl; }
else cout << "(" << arr << "," << "10" << ")" << endl;
}
else if (IsDigit(ch)) {
while (IsDigit(ch) || IsDigit(fgetc(fpin))) {
arr = arr + ch;
ch = fgetc(fpin);
}
fseek(fpin, -1L, SEEK_CUR);
cout << "(" << arr << "," << "20" << ")" << endl;
}
else switch (ch) {
case'+':cout << "(" << ch << ",22" << ")" << endl; break;
case'-':cout << "(" << ch << ",23" << ")" << endl; break;
case'*':cout << "(" << ch << ",24" << ")" << endl; break;
case'(':cout << "(" << ch << ",26" << ")" << endl; break;
case')':cout << "(" << ch << ",27" << ")" << endl; break;
case'[':cout << "(" << ch << ",28" << ")" << endl; break;
case']':cout << "(" << ch << ",29" << ")" << endl; break;
case';':cout << "(" << ch << ",34" << ")" << endl; break;
case',':cout << "(" << ch << ",32" << ")" << endl; break;
case'{':cout << "(" << ch << ",30" << ")" << endl; break;
case'}':cout << "(" << ch << ",31" << ")" << endl; break;
case'=': {ch = fgetc(fpin);
if (ch == '=') cout << "(" << "==" << ",21" << ")" << endl;
else {
cout << "(" << "=" << ",19" << ")" << endl;;
fseek(fpin, -1L, SEEK_CUR);
}
}break;
case'!': {ch = fgetc(fpin);
if (ch == '=') cout << "(" << "!=" << ",40" << ")" << endl;
else {
cout << "(" << "=" << ",-1" << ")" << endl;;
fseek(fpin, -1L, SEEK_CUR);
}
}break;
case':': {ch = fgetc(fpin);
if (ch == '=') cout << "(" << ":=" << ",18" << ")" << endl;
else {
cout << "(" << ":" << ",33" << ")" << endl;;
![](https://csdnimg.cn/release/download_crawler_static/89158029/bg5.jpg)
中北大学大数据学院
实验报告
fseek(fpin, -1L, SEEK_CUR);
}
}break;
case'>': {ch = fgetc(fpin);
if (ch == '=') cout << "(" << ">=" << ",37" << ")" << endl;
if (ch == '>')cout << "(" << ">>" << ",43" << ")" << endl;
else {
cout << "(" << ">" << ",35" << ")" << endl;
fseek(fpin, -1L, SEEK_CUR);
}
}break;
case'<': {ch = fgetc(fpin);
if (ch == '=')cout << "(" << "<=" << ",38" << ")" << endl;
else if (ch == '<')cout << "(" << "<<" << ",42" << ")" << endl;
else {
cout << "(" << "<" << ",36" << ")" << endl;
fseek(fpin, -1L, SEEK_CUR);
}
}break;
case'/': {ch = fgetc(fpin);
if (ch == '*')
{
ch = fgetc(fpin);
while (!((ch == '*' )&& (ch = fgetc(fpin) == '/')))
{
ch = fgetc(fpin);
}
ch = fgetc(fpin);
fseek(fpin, -1L, SEEK_CUR);
}
else {
cout << "(" << "/" << ",25" << ")" << endl;;
fseek(fpin, -1L, SEEK_CUR);
}
}break;
default: cout << ch << "\t无法识别字符" << endl;
}
}
}
/*主函数
功能:打开存放待分析程序的文件,并进行分析,分析结束后关闭文件*/
void main() {