Microsoft Visual Studio 2005版本 8.0.50727.4
Microsoft Visual C++ 2005版本77983-009-0000007-41481
1
/********************************* scanner.h *********************************/
2
3
#ifndef SCANNER_H
4
#pragma warning (disable:4996) // 屏蔽4996警告
5
#pragma warning (disable:4313) // 屏蔽4313警告
6
7
#define SCANNER_H
8
9
#include <string.h>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <ctype.h>
13
#include <stdarg.h>
14
#include <math.h>
15
16
enum Token_Type /* 记号种类 */
17
{
18
ORIGIN, SCALE, ROT, IS, TO, STEP, DRAW, FOR, FROM, // 保留字
19
T, // 参数
20
SEMICO, L_BRACKET, R_BRACKET, COMMA, // 分隔符号
21
PLUS, MINUS, MUL, DIV, POWER, // 运算符
22
FUNC, // 函数
23
CONST_ID, // 常数
24
NONTOKEN, // 空记号
25
ERRTOKEN // 出错记号
26
};
27
28
typedef double (*MathFuncPtr)(double); /* 函数指针类型 */
29
30
struct Token /* 记号与符号表结构 */
31
{
32
Token_Type type; // 记号的类别
33
char *lexeme; // 构成记号的字符串
34
double value; // 若为常数,则是常数的值
35
MathFuncPtr FuncPtr; // 若为函数,则是函数的指针
36
};
37
38
static Token TokenTab[] = { /* 符号表内容 */
39
{CONST_ID, "PI", 3.1415926, 0 },
40
{CONST_ID, "E", 2.71828, 0 },
41
{T, "T", 0.0, 0 },
42
{FUNC, "SIN", 0.0, sin },
43
{FUNC, "COS", 0.0, cos },
44
{FUNC, "TAN", 0.0, tan },
45
{FUNC, "LN", 0.0, log },
46
{FUNC, "EXP", 0.0, exp },
47
{FUNC, "SQRT", 0.0, sqrt},
48
{ORIGIN, "ORIGIN", 0.0, 0 },
49
{SCALE, "SCALE", 0.0, 0 },
50
{ROT, "ROT", 0.0, 0 },
51
{IS, "IS", 0.0, 0 },
52
{FOR, "FOR", 0.0, 0 },
53
{FROM, "FROM", 0.0, 0 },
54
{TO, "TO", 0.0, 0 },
55
{STEP, "STEP", 0.0, 0 },
56
{DRAW, "DRAW", 0.0, 0 }
57
};
58
59
extern unsigned int LineNo; /* 跟踪记号所在源文件行号 */
60
extern int InitScanner(const char *); /* 初始化词法分析器 */
61
extern Token GetToken(); /* 获取记号 */
62
extern void CloseScanner(); /* 关闭词法分析器 */
63
64
#endif

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

1
/********************************* scanner.cpp *********************************/
2
3
#include "scanner.h"
4
5
#define TOKEN_LEN 100 // 记号最大长度
6
7
unsigned int LineNo; // 跟踪源文件行号
8
static FILE *InFile; // 输入文件流
9
static char TokenBuffer[TOKEN_LEN]; // 记号字符缓冲
10
11
/* 初始化词法分析器 */
12
extern int InitScanner(const char *FileName)
13
{
14
LineNo = 1;
15
InFile = fopen(FileName, "r");
16
return ((InFile != 0) ? 1 : 0);
17
}
18
19
/* 关闭词法分析器 */
20
extern void CloseScanner()
21
{
22
if(InFile != 0) fclose(InFile);
23
}
24
25
/* 从输入源程序读入一个字符 */
26
static char GetChar()
27
{
28
int Char = getc(InFile);
29
return toupper(Char);
30
}
31
32
/* 把预读的字符退回到输入源程序中 */
33
static void BackChar(char Char)
34
{
35
if(Char != EOF) ungetc(Char, InFile);
36
}
37
38
/* 加入字符到记号缓冲区 */
39
static void AddCharTokenString(char Char)
40
{
41
int TokenLength = (int)strlen(TokenBuffer);
42
if(TokenLength + 1 >= sizeof(TokenBuffer)) return;
43
TokenBuffer[TokenLength] = Char;
44
TokenBuffer[TokenLength + 1] = '\0';
45
}
46
47
/* 清空记号缓冲区 */
48
static void EmptyTokenString()
49
{
50
memset(TokenBuffer, 0, TOKEN_LEN);
51
}
52
53
/* 判断所给的字符串是否在符号表中 */
54
static Token JudgeKeyToken(const char *IDString)
55
{
56
for(int loop = 0; loop < sizeof(TokenTab) / sizeof(sizeof(TokenTab[0])) / 6; ++loop)
57
/* 注意:需要"
/ 6",否则 TokenTab 中的元素个数扩大了 6 倍 */
58
{
59
if(strcmp(TokenTab[loop].lexeme, IDString) == 0) return TokenTab[loop];
60
}
61
Token errortoken;
62
memset(&errortoken, 0, sizeof(Token));
63
errortoken.type = ERRTOKEN;
64
return errortoken;
65
}
66
67
/* 获取一个记号 */
68
extern Token GetToken()
69
{
70
Token token;
71
int Char;
72
73
memset(&token, 0, sizeof(Token));
74
EmptyTokenString();
75
token.lexeme = TokenBuffer;
76
77
for(;;) // 过滤源程序中的空格、TAB、回车等,遇到文件结束符返回空记号
78
{
79
Char = GetChar();
80
if(Char == EOF)
81
{
82
token.type = NONTOKEN;
83
return token;
84
}
85
if(Char == '\n') LineNo++;
86
if(!isspace(Char)) break;
87
}
88
89
AddCharTokenString(Char); // 若不是空格、TAB、回车、文件结束符等,则先加入到记号的字符缓冲区中
90
91
if(isalpha(Char)) // 若Char是A-Za-z,则一定是函数、关键字、PI、E等
92
{
93
for(;;)
94
{
95
Char = GetChar();
96
if(isalnum(Char)) AddCharTokenString(Char);
97
else break;
98
}
99
BackChar(Char);
100
token = JudgeKeyToken(TokenBuffer);
101
token.lexeme = TokenBuffer;
102
return token;
103
}
104
else if(isdigit(Char)) // 若是一个数字,则一定是常量
105
{
106
for(;;)
107
{
108
Char = GetChar();
109
if(isdigit(Char)) AddCharTokenString(Char);
110
else break;
111
}
112
if(Char == '.')
113
{
114
AddCharTokenString(Char);
115
for(;;)
116
{
117
Char = GetChar();
118
if(isdigit(Char)) AddCharTokenString(Char);
119
else break;
120
}
121
}
122
BackChar(Char);
123
token.type = CONST_ID;
124
token.value = atof(TokenBuffer);
125
126
return token;
127
}
128
else
129
{
130
switch(Char)
131
{
132
case ';' : token.type = SEMICO; break;
133
case '(' : token.type = L_BRACKET; break;
134
case ')' : token.type = R_BRACKET; break;
135
case ',' : token.type = COMMA; break;
136
case '+' : token.type = PLUS; break;
137
case '-' :
138
Char = GetChar();
139
if(Char == '-')
140
{
141
while(Char != '\n' && Char != EOF) Char = GetChar();
142
BackChar(Char);
143
return GetToken();
144
}
145
else
146
{
147
BackChar(Char);
148
token.type = MINUS;
149
break;
150
}
151
case '/' :
152
Char = GetChar();
153
if(Char == '/')
154
{
155
while(Char != '\n' && Char != EOF) Char = GetChar();
156
BackChar(Char);
157
return GetToken();
158
}
159
else
160
{
161
BackChar(Char);
162
token.type = DIV;
163
break;
164
}
165
case '*' :
166
Char = GetChar();
167
if(Char == '*')
168
{
169
token.type = POWER;
170
AddCharTokenString(Char);
171
break;
172
}
173
else
174
{
175
BackChar(Char);
176
token.type = MUL;
177
break;
178
}
179
default : token.type = ERRTOKEN; break;
180
}
181
}
182
return token;
183
}

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

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

1
/********************************* scannermain.cpp *********************************/
2
3
#include "scanner.h"
4
5
int main(int argc, char *argv[])
6
{
7
Token token;
8
if(!InitScanner("test.txt"))
9
{
10
printf("Open Source File Error !\n");
11
return -1;
12
}
13
printf("记号类别 字符串 常数值 函数指针\n");
14
printf("________________________________________________\n");
15
while(1)
16
{
17
token = GetToken();
18
if(token.type != NONTOKEN)
19
printf("%4d, %12s, %12f, %12x\n", token.type, token.lexeme, token.value, token.FuncPtr);
20
else break;
21
};
22
printf("________________________________________________\n");
23
CloseScanner();
24
return 0;
25
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25
