实验一词法分析.docx
- 文档编号:9293412
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:23
- 大小:72.34KB
实验一词法分析.docx
《实验一词法分析.docx》由会员分享,可在线阅读,更多相关《实验一词法分析.docx(23页珍藏版)》请在冰豆网上搜索。
实验一词法分析
实验一词法分析
1.实验要求
(1)从源程序文件中读取有效字符并将其转换成二元组内部表示形式输出。
(2)掌握词法分析的实现方法。
(3)实验时间4学时。
(4)实验完成后,要提交实验报告(包括源程序清单)。
2.实验内容
2.1主程序设计考虑:
主程序的说明部分为各种表格和变量安排空间(关键字和特殊符号表)。
id和ci数组分别存放标识符和常数;还有一些为造表填表设置的变量。
主程序的工作部分建议设计成便于调试的循环结构。
每个循环处理一个单词;调用词法分析过程;输出每个单词的内部码(种别编码,属性值)。
建议从文件中读取要分析的符号串。
2.2词法分析过程考虑
该过程根据输入单词的第一个有效字符(有时还需读第二个字符),判断单词种别,产生种别编码。
对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组id中,将常数存入数组中ci中,并记录其在表中的位置。
编号
1
2
3
4
5
6
7
8
9
10
名字
int
char
float
void
const
if
else
do
while
scanf
编号
11
12
13
14
15
16
17
18
19
20
名字
printf
return
main
read
+
–
*
/
%
=
编号
21
22
23
24
25
26
27
28
29
30
名字
==
>
<
!
=
>=
<=
&&
||
!
<>
编号
31
32
33
34
35
36
37
38
39
40
名字
(
)
{
}
;
“
‘
++
--
三:
主流程图如下:
四:
实验思路
(1)我首先把这个单词的种类分成了五类,包括:
关键字、标识符、常数、算符、界符。
然后利用状态转换图进行单词的识别
(2)对于关键字、算符、界符。
因为这些单词的个数有限。
所以我单独给每个单词一个种别编码。
能够做到每个单词的种别编码是不一样的。
而对于常数和标识符,我先把它们分别单独的作为一类,然后定义一个二维数组,分别存放这个单词的名称和编码。
而这个编码就是这个单词在这个二维数组中的位置;当遇到新的标识符或常数,就把这个单词放入到相应的数组中。
(3)然后构造一个状态转换图的程序。
把每次得到的单词先暂时存放在temp二维数组中。
然后用这个临时的二维数组去确定这个单词是何种类别
五:
实验代码
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Threading.Tasks;
usingSystem.Windows.Forms;
namespaceWord
{
publicpartialclassForm1:
Form
{
publicForm1()
{
InitializeComponent();
}
char[]receive;//从输入得到的源程序
charch;//这是从源程序读取的一个字符
stringcache;//暂存的单词
intindex;//记录取到哪个位置了
key_wordtemp;//用来临时存放得到这个单词
structkey_word
{
publicstringkey_name;
publicintnumber;
}
structnum_word
{
publicstringnum_name;
publicintnumber;
}
structID_word
{
publicstringID_name;
publicintnumber;
}
publicintnum_index;
publicintID_index;
DataTabledt;
privatevoidbutton1_Click(objectsender,EventArgse)
{
dt=newDataTable();
dt.Columns.Add("助记符");
dt.Columns.Add("外部编码");
dt.Columns.Add("内部编码");
dt.Columns.Add("类型");
receive=textBox1.Text.ToCharArray();
index=0;
num_index=0;
ID_index=0;;
while(index { cache=null; Get_Word(); if(temp.number==1) { inti=0; intflag=0; if(num_index==0) { Num[num_index].num_name=temp.key_name; Num[num_index].number=num_index; num_index++; } else { for(i=0;i { if(Num[i].num_name==temp.key_name) { flag=i; break; } } if(i>=num_index) { Num[num_index].num_name=temp.key_name; Num[num_index].number=num_index; flag=num_index; num_index++; } } DataRowdr=dt.NewRow(); dt.Rows.Add(dr); dr["助记符"]=temp.key_name; dr["外部编码"]=temp.number; dr["内部编码"]=+Num[flag].number; dr["类型"]="常数"; } elseif(temp.number==0) { inti=0; intflag=0; if(ID_index==0) { ID[ID_index].ID_name=temp.key_name; ID[ID_index].number=ID_index; ID_index++; } else { for(i=0;i { if(ID[i].ID_name==temp.key_name) { flag=i; break; } } if(i>=ID_index) { ID[ID_index].ID_name=temp.key_name; ID[ID_index].number=ID_index; flag=ID_index; ID_index++; } } DataRowdr=dt.NewRow(); dt.Rows.Add(dr); dr["助记符"]=temp.key_name; dr["外部编码"]=temp.number; dr["内部编码"]=ID[flag].number; dr["类型"]="标识符"; } else { DataRowdr=dt.NewRow(); dt.Rows.Add(dr); dr["助记符"]=temp.key_name; dr["外部编码"]=temp.number; if(temp.number>=15&&temp.number<=30) { dr["类型"]="运算符"; } elseif(temp.number>=31&&temp.number<=40) { dr["类型"]="界符"; } else { dr["类型"]="关键字"; } } } this.dataGridView1.DataSource=dt; } key_word[]Key; num_word[]Num; ID_word[]ID; privatevoidForm1_Load(objectsender,EventArgse) { index=0; Key=newkey_word[41]; Key[0].key_name="$ID";Key[0].number=0;//标识符 Key[1].key_name="$INT";Key[1].number=1;//数 Key[2].key_name="int";Key[2].number=2;Key[3].key_name="float";Key[3].number=3; Key[4].key_name="void";Key[4].number=4;Key[5].key_name="const";Key[5].number=5;Key[6].key_name="if";Key[6].number=6;Key[7].key_name="else";Key[7].number=7; Key[8].key_name="do";Key[8].number=8;Key[9].key_name="while";Key[9].number=9;Key[10].key_name="scanf";Key[10].number=10;Key[11].key_name="printf";Key[11].number=11; Key[12].key_name="return";Key[12].number=12;Key[13].key_name="main";Key[13].number=13;Key[14].key_name="read";Key[14].number=14; Key[15].key_name="+";Key[15].number=15; Key[16].key_name="-";Key[16].number=16;Key[17].key_name="*";Key[17].number=17;Key[18].key_name="/";Key[18].number=18;Key[19].key_name="%";Key[19].number=19; Key[20].key_name="=";Key[20].number=20;Key[21].key_name="==";Key[21].number=21;Key[22].key_name=">";Key[22].number=22;Key[23].key_name="<";Key[23].number=23; Key[24].key_name="! =";Key[24].number=24;Key[25].key_name=">=";Key[25].number=25;Key[26].key_name="<=";Key[26].number=26;Key[27].key_name="&&";Key[27].number=27; Key[28].key_name="||";Key[28].number=28;Key[29].key_name="! ";Key[29].number=29;Key[30].key_name="<>";Key[30].number=30; Key[31].key_name="(";Key[31].number=31; Key[32].key_name=")";Key[32].number=32;Key[33].key_name="{";Key[33].number=33; Key[34].key_name="}";Key[34].number=34;Key[35].key_name=";";Key[35].number=35; Key[36].key_name=",";Key[36].number=36;Key[37].key_name="\"";Key[37].number=37;Key[38].key_name="'";Key[38].number=38;Key[39].key_name="++";Key[39].number=39; Key[40].key_name="--";Key[40].number=40; Num=newnum_word[1024]; ID=newID_word[1024]; } publicvoidGetChar()//得到一个字符 { if(index { ch=receive[index]; index++; } else { ch='\0'; } } publicvoidGetNotKong()//得到一个不是空的字符 { while(index { ch=receive[index]; index++; if(ch! =''&&ch! ='\r'&&ch! ='\0'&&ch! ='\n') { break; } } } publicvoidConCat()//连接 { cache+=ch; } publicboolIsLetter()//判断是不是字母 { if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z') { returntrue; } else { returnfalse; } } publicboolIsDigit()//判断是不是数字 { if(ch>='0'&&ch<='9') { returntrue; } else { returnfalse; } } publicintGet_Number()//得到这个单词的编码 { for(inti=0;i<41;i++) { if(string.Equals(cache,Key[i].key_name)) { returnKey[i].number; } } { return0; } } publicvoidretrace()//退回一个单词 { if(ch! ='\0') { index--; } } privatevoidGet_Word() { intcount; GetNotKong(); if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z') { ConCat(); GetChar(); while(IsLetter()||IsDigit()) { ConCat(); GetChar(); } retrace(); count=Get_Number(); temp.key_name=cache; if(count==0) { temp.number=0; } else { temp.number=Key[count].number; } } elseif(ch>='0'&&ch<='9') { ConCat(); GetChar(); while(IsDigit()) { ConCat(); GetChar(); } retrace(); temp.key_name=cache; temp.number=1; } elseif(ch=='+') { ConCat(); GetChar(); if(ch=='+') { ConCat(); temp.key_name=cache; temp.number=39; } else { retrace(); temp.key_name=cache; temp.number=Get_Number(); } } elseif(ch=='-') { ConCat(); GetChar(); if(ch=='-') { ConCat(); temp.key_name=cache; temp.number=40; } else { retrace(); temp.key_name=cache; temp.number=Get_Number(); } } elseif(ch=='<') { ConCat(); GetChar(); if(ch=='=') { ConCat(); temp.key_name=cache; temp.number=26; } else { retrace(); temp.key_name=cache; temp.number=Get_Number(); } } elseif(ch=='>') { ConCat(); GetChar(); if(ch=='=') { ConCat(); temp.key_name=cache; temp.number=25; } else { retrace(); temp.key_name=cache; temp.number=Get_Number(); } } elseif(ch=='=') { ConCat(); GetChar(); if(ch=='=') { ConCat(); temp.key_name=cache; temp.number=21; } else { retrace(); temp.key_name=cache; temp.number=Get_Number(); } } elseif(ch=='! ') { ConCat(); GetChar(); if(ch=='=') { ConCat(); temp.key_name=cache; temp.number=24; } else { retrace(); temp.key_name=cache; temp.number=Get_Number(); } } elseif(ch=='&') { ConCat(); GetChar(); if(ch=='&') { ConCat(); temp.key_name=cache; temp.number=27; } else { retrace(); temp.key_name=cache; temp.number=Get_Number(); } } elseif(ch=='|') { ConCat(); GetChar(); if(ch=='|') { ConCat(); temp.key_name=cache; temp.number=28; } else { retrace(); temp.key_name=cache; temp.number=Get_Number(); } } else { ConCat(); temp.key_name=cache; temp.number=Get_Number(); } } } } 六: 实验截图 (1)我测试的程序为v oidmain() {inta=20; intb=15; if(a==20) printf("A"); if(b==20) printf("B"); } 七: 实验心得 通过这次实验、我对于词法分析需要做的任务有了一个更加深刻的理解。 将课本上的理论实践到实际上使我对课本有了很好的理解。 但是,这次实验中我也发现了我很多的小缺点,这个实验也挺考验一个学生的分析能力的。 因为这个实验需要做的判断是非常多的、稍微漏掉一点就有可能导致整个程序的错误。 而且、开始的时候我还把实验给理解错了。 这让我更加知道了做实验之前好好分析的重要性。 因为如果连要求都没有搞明白就去做实验的话。 带来的麻烦更多。 今后一定多加注意。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验一 词法分析 实验 词法 分析