词法分析综合实验

5.2k 词

题目描述

一、实验目的

通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

二、实验内容

编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示)。

三、实验原理或算法

1、****词法分析器的功能和输出格式

词法分析器的功能是输入源程序,输出单词符号。词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。本实验中,采用的是一类符号一种别码的方式。

2、单词的BNF****表示

<标识符>-> <字母><字母数字串>

<字母数字串>-><字母><字母数字串><数字><字母数字串><下划线><字母数字串>ε

<无符号整数>-> <数字><数字串>

<数字串>-> <数字><数字串> ε

<加法运算符>-> +

<减法运算符>-> -

<大于关系运算符>-> >

<大于等于关系运算符>-> >=

3****、“超前搜索”方法

词法分析时,常常会用到超前搜索方法。如当前待分析字符串为“a>=”或“a>b”,当前字符为’>’,此时,分析器倒底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。于是分析器读入下一个字符’=’或’b’,这时可知应将’>’解释为大于或大于等于运算符。但此时,超前读了一个字符’b’,所以要回退一个字符,词法分析器才能正常运行。在分析标识符,无符号整数等时也有类似情况。

4****、编程思路

这里以开始定义的C语言子集的源程序作为词法分析程序的输入数据。在词法分析中,自文件头开始扫描源程序字符,一旦发现符合“单词”定义的源程序字符串时,将它翻译成固定长度的单词内部表示,并查填适当的信息表。经过词法分析后,源程序字符串(源程序的外部表示)被翻译成具有等长信息的单词串(源程序的内部表示),并产生两个表格:常数表和标识符表,它们分别包含了源程序中的所有常数和所有标识符。

5、单词种别码要求:

识别保留字:if、int、for、while、do、return、break、continue;单词种别码为1。

分隔符包括:,、;、{、}、(、); 单词种别码为2。

运算符包括:+、-、*、/、=、;单词种别码为3。

关系运算符:>、<、==、>=、<=、!= ;单词种别码为4。

标识符;单词种别码为5。

常数为无符号整形数;单词种别码为6。

样例输入

1
2
3
4
5
6
main()
{
int a,b;
a = 10;
b = a + 20;
}

样例输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(main,6,1)
((,2,5)
(),2,6)
({,2,3)
(int,1,5)
(a,6,2)
(,,2,1)
(b,6,3)
(;,2,2)
(a,6,2)
(=,3,5)
(10,5,1)
(;,2,2)
(b,6,3)
(=,3,5)
(a,6,2)
(+,3,1)
(20,5,2)
(;,2,2)
(},2,4)
Anysis End

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include<iostream>
#include <cstring>


using namespace std;

char cBuffer;
const char *key[8] = {"if", "else", "for", "while", "int", "return", "break", "continue"};
const char *border[6] = {",", ";", "{", "}", "(", ")"};
const char *arithmetic[5] = {"+", "-", "*", "/", "="};
const char *relations[6] = {"<", "<=", "==", ">", ">=", "!="};
char *consts[20];
char *label[20];
int constNum = 0, labelNum = 0;

int search(char searchChar[], int wordType) {
int i ;
switch (wordType) {
case 1:
for (i = 0; i <= 7; i++)
if (strcmp(key[i], searchChar) == 0) return (i + 1);
return 0;
case 2:
for (i = 0; i <= 5; i++)
if (strcmp(border[i], searchChar) == 0) return (i + 1);
return (0);
case 3:
for (i = 0; i <= 4; i++)
if (strcmp(arithmetic[i], searchChar) == 0) return (i + 1);
return (0);
case 4:
for (i = 0; i <= 5; i++)
if (strcmp(relations[i], searchChar) == 0) return (i + 1);
return (0);
case 5:
for (i = 0; i < constNum; i++)
if (strcmp(consts[i], searchChar) == 0) return (i + 1);
consts[i] = (char *) malloc(sizeof(searchChar));
strcpy(consts[i], searchChar);
constNum++;
return (i + 1);
case 6:
for (i = 0; i < labelNum; i++)
if (strcmp(label[i], searchChar) == 0) return (i + 1);
label[i] = (char *) malloc(sizeof(searchChar));
strcpy(label[i], searchChar);
labelNum++;
return (i + 1);
default:
return (0);
}
}


char alphaProcess(char buffer)//字母开头串的处理(可能是保留字或标识符)
{
int aType;
int i = -1;
char alphaTP[20];
while ((isalpha(buffer)) (isdigit(buffer))) {
alphaTP[++i] = buffer;
buffer = getchar();
}
alphaTP[i + 1] = '\0';
if ((aType = search(alphaTP, 1)))
printf("(%s,1,%d)\n", alphaTP, aType);
else {
aType = search(alphaTP, 6);
printf("(%s,6,%d)\n", alphaTP, aType);
}
return (buffer);
}

char digitProcess(char buffer) //常量串
{
int i = -1;
char digittp[20];
int dType;
while ((isdigit(buffer))) {
digittp[++i] = buffer;
buffer = getchar();
}
digittp[i + 1] = '\0';
dType = search(digittp, 5);
printf("(%s,5,%d)\n", digittp, dType);
return (buffer);
}

char otherProcess(char buffer) //其它符号的处理
{

char othertp[20];
int otype, otypetp;
othertp[0] = buffer;
othertp[1] = '\0';
if ((otype = search(othertp, 3))) {
printf("(%s,3,%d)\n", othertp, otype);
buffer = getchar();
goto out;
}
if ((otype = search(othertp, 4))) {
buffer = getchar();
othertp[1] = buffer;
othertp[2] = '\0';
if ((otypetp = search(othertp, 4))) {
printf("(%s,4,%d)\n", othertp, otypetp);
goto out;
} else {
othertp[1] = '\0';
printf("(%s,4,%d)\n", othertp, otype);
goto out;
}
}
if (buffer == ':') {
buffer = getchar();
if (buffer == '=')
printf(":= (2,2)\n");
buffer = getchar();
goto out;
} else if ((otype = search(othertp, 2))) {
printf("(%s,2,%d)\n", othertp, otype);
buffer = getchar();
goto out;
}

if ((buffer != '\n') && (buffer != ' '))
printf("%c error,not a word\n", buffer);
buffer = getchar();
out:
return (buffer);
}

int main() {
int i;
for (i = 0; i <= 20; i++) {
label[i] = nullptr;
consts[i] = nullptr;
}
cBuffer = getchar();
while (cBuffer != EOF) {
if (isalpha(cBuffer))
cBuffer = alphaProcess(cBuffer);
else if (isdigit(cBuffer))
cBuffer = digitProcess(cBuffer);
else cBuffer = otherProcess(cBuffer);
}
printf("Anysis End\n");
getchar();
return 0;
}