已开启
提交作业-廖志宏-18-词法分析 #28
Alica_lzh创建于 2025年11月30日
提交作业-廖志宏-18-词法分析 #28
已开启
Alica_lzh创建于 2025年11月30日
19 个文件变更+4324-0
@@ -0,0 +1,461 @@
1+#define _CRT_SECURE_NO_WARNINGS
2+#include <stdio.h>
3+#include <stdlib.h>
4+#include <string.h>
5+#include <ctype.h>
6+#include <stdbool.h>
7+ 
8+// Token类型定义
9+typedef enum {
10+ // 关键字
11+ TOKEN_AS, TOKEN_BREAK, TOKEN_CASE, TOKEN_CONST, TOKEN_CONTINUE,
12+ TOKEN_DO, TOKEN_ELSE, TOKEN_FOR, TOKEN_FROM, TOKEN_FUNC,
13+ TOKEN_IF, TOKEN_IN, TOKEN_LET, TOKEN_MAIN, TOKEN_MATCH,
14+ TOKEN_VAR, TOKEN_WHERE, TOKEN_WHILE,
15+ 
16+ // 标识符和字面量
17+ TOKEN_ID, TOKEN_NUM,
18+ 
19+ // 单字符运算符
20+ TOKEN_PLUS, TOKEN_MINUS, TOKEN_STAR, TOKEN_SLASH, TOKEN_ASSIGN,
21+ TOKEN_LPAREN, TOKEN_RPAREN, TOKEN_LBRACE, TOKEN_RBRACE,
22+ TOKEN_LBRACKET, TOKEN_RBRACKET, TOKEN_COMMA, TOKEN_SEMICOLON,
23+ TOKEN_LT, TOKEN_GT, TOKEN_NOT, TOKEN_COLON,
24+ 
25+ // 双字符运算符
26+ TOKEN_NE, TOKEN_GE, TOKEN_LE, TOKEN_EQ,
27+ TOKEN_ELLIPSIS, TOKEN_ELLIPSIS_EQ,
28+ 
29+ // 注释和特殊标记
30+ TOKEN_COMMENT_SINGLE, TOKEN_COMMENT_MULTI,
31+ TOKEN_EOF, TOKEN_ERROR
32+} TokenType;
33+ 
34+// Token结构体
35+typedef struct {
36+ TokenType type;
37+ char lexeme[256];
38+ int line;
39+ int column;
40+} Token;
41+ 
42+// 关键字查找表
43+typedef struct {
44+ char* keyword;
45+ TokenType type;
46+} Keyword;
47+ 
48+Keyword keywords[] = {
49+ {"as", TOKEN_AS},
50+ {"break", TOKEN_BREAK},
51+ {"case", TOKEN_CASE},
52+ {"const", TOKEN_CONST},
53+ {"continue", TOKEN_CONTINUE},
54+ {"do", TOKEN_DO},
55+ {"else", TOKEN_ELSE},
56+ {"for", TOKEN_FOR},
57+ {"from", TOKEN_FROM},
58+ {"func", TOKEN_FUNC},
59+ {"if", TOKEN_IF},
60+ {"in", TOKEN_IN},
61+ {"let", TOKEN_LET},
62+ {"main", TOKEN_MAIN},
63+ {"match", TOKEN_MATCH},
64+ {"var", TOKEN_VAR},
65+ {"where", TOKEN_WHERE},
66+ {"while", TOKEN_WHILE},
67+ {NULL, TOKEN_ERROR}
68+};
69+ 
70+// 词法分析器状态
71+typedef struct {
72+ const char* source;
73+ int current_pos;
74+ int line;
75+ int column;
76+ bool has_error;
77+} Lexer;
78+ 
79+// 初始化词法分析器
80+void init_lexer(Lexer* lexer, const char* source) {
81+ lexer->source = source;
82+ lexer->current_pos = 0;
83+ lexer->line = 1;
84+ lexer->column = 1;
85+ lexer->has_error = false;
86+}
87+ 
88+// 获取当前字符
89+char current_char(Lexer* lexer) {
90+ return lexer->source[lexer->current_pos];
91+}
92+ 
93+// 查看下一个字符(不移动位置)
94+char peek_char(Lexer* lexer, int offset) {
95+ return lexer->source[lexer->current_pos + offset];
96+}
97+ 
98+// 前进到下一个字符
99+void advance(Lexer* lexer) {
100+ if (current_char(lexer) == '\n') {
101+ lexer->line++;
102+ lexer->column = 1;
103+ }
104+ else {
105+ lexer->column++;
106+ }
107+ lexer->current_pos++;
108+}
109+ 
110+// 跳过空白字符
111+void skip_whitespace(Lexer* lexer) {
112+ while (isspace(current_char(lexer))) {
113+ advance(lexer);
114+ }
115+}
116+ 
117+// 检查关键字
118+TokenType check_keyword(const char* lexeme) {
119+ for (int i = 0; keywords[i].keyword != NULL; i++) {
120+ if (strcmp(lexeme, keywords[i].keyword) == 0) {
121+ return keywords[i].type;
122+ }
123+ }
124+ return TOKEN_ID;
125+}
126+ 
127+// 识别标识符或关键字
128+Token identifier_or_keyword(Lexer* lexer) {
129+ Token token;
130+ token.line = lexer->line;
131+ token.column = lexer->column;
132+ 
133+ int i = 0;
134+ while (isalnum(current_char(lexer))) {
135+ if (i < 255) {
136+ token.lexeme[i++] = current_char(lexer);
137+ }
138+ advance(lexer);
139+ }
140+ token.lexeme[i] = '\0';
141+ 
142+ token.type = check_keyword(token.lexeme);
143+ return token;
144+}
145+ 
146+// 识别数字字面量 - 修复版本
147+Token number(Lexer* lexer) {
148+ Token token;
149+ token.type = TOKEN_NUM;
150+ token.line = lexer->line;
151+ token.column = lexer->column;
152+ 
153+ int i = 0;
154+ while (isdigit(current_char(lexer))) {
155+ if (i < 255) {
156+ token.lexeme[i++] = current_char(lexer);
157+ }
158+ advance(lexer);
159+ }
160+ token.lexeme[i] = '\0';
161+ 
162+ return token;
163+}
164+ 
165+// 处理单行注释
166+void skip_single_line_comment(Lexer* lexer) {
167+ while (current_char(lexer) != '\n' && current_char(lexer) != '\0') {
168+ advance(lexer);
169+ }
170+}
171+ 
172+// 处理多行注释
173+bool skip_multi_line_comment(Lexer* lexer) {
174+ advance(lexer); // 跳过 '*'
175+ 
176+ while (true) {
177+ if (current_char(lexer) == '\0') {
178+ return false; // 未闭合的注释
179+ }
180+ if (current_char(lexer) == '*' && peek_char(lexer, 1) == '/') {
181+ advance(lexer); // 跳过 '*'
182+ advance(lexer); // 跳过 '/'
183+ return true;
184+ }
185+ advance(lexer);
186+ }
187+}
188+ 
189+// 获取下一个token - 修复版本
190+Token next_token(Lexer* lexer) {
191+ skip_whitespace(lexer);
192+ 
193+ Token token;
194+ token.line = lexer->line;
195+ token.column = lexer->column;
196+ token.lexeme[0] = current_char(lexer);
197+ token.lexeme[1] = '\0';
198+ 
199+ if (current_char(lexer) == '\0') {
200+ token.type = TOKEN_EOF;
201+ return token;
202+ }
203+ 
204+ char c = current_char(lexer);
205+ 
206+ // 识别标识符(必须以字母开头)
207+ if (isalpha(c)) {
208+ return identifier_or_keyword(lexer);
209+ }
210+ 
211+ // 识别数字
212+ if (isdigit(c)) {
213+ return number(lexer);
214+ }
215+ 
216+ // 处理注释和运算符
217+ switch (c) {
218+ case '+':
219+ token.type = TOKEN_PLUS;
220+ advance(lexer);
221+ break;
222+ 
223+ case '-':
224+ token.type = TOKEN_MINUS;
225+ advance(lexer);
226+ break;
227+ 
228+ case '*':
229+ token.type = TOKEN_STAR;
230+ advance(lexer);
231+ break;
232+ 
233+ case '/':
234+ if (peek_char(lexer, 1) == '/') {
235+ // 单行注释
236+ skip_single_line_comment(lexer);
237+ return next_token(lexer);
238+ }
239+ else if (peek_char(lexer, 1) == '*') {
240+ // 多行注释
241+ if (!skip_multi_line_comment(lexer)) {
242+ token.type = TOKEN_ERROR;
243+ strcpy(token.lexeme, "Unclosed multi-line comment");
244+ lexer->has_error = true;
245+ }
246+ return next_token(lexer);
247+ }
248+ else {
249+ token.type = TOKEN_SLASH;
250+ advance(lexer);
251+ }
252+ break;
253+ 
254+ case '=':
255+ if (peek_char(lexer, 1) == '=') {
256+ token.type = TOKEN_EQ;
257+ strcpy(token.lexeme, "==");
258+ advance(lexer);
259+ advance(lexer);
260+ }
261+ else {
262+ token.type = TOKEN_ASSIGN;
263+ advance(lexer);
264+ }
265+ break;
266+ 
267+ case '!':
268+ if (peek_char(lexer, 1) == '=') {
269+ token.type = TOKEN_NE;
270+ strcpy(token.lexeme, "!=");
271+ advance(lexer);
272+ advance(lexer);
273+ }
274+ else {
275+ token.type = TOKEN_NOT;
276+ advance(lexer);
277+ }
278+ break;
279+ 
280+ case '>':
281+ if (peek_char(lexer, 1) == '=') {
282+ token.type = TOKEN_GE;
283+ strcpy(token.lexeme, ">=");
284+ advance(lexer);
285+ advance(lexer);
286+ }
287+ else {
288+ token.type = TOKEN_GT;
289+ advance(lexer);
290+ }
291+ break;
292+ 
293+ case '<':
294+ if (peek_char(lexer, 1) == '=') {
295+ token.type = TOKEN_LE;
296+ strcpy(token.lexeme, "<=");
297+ advance(lexer);
298+ advance(lexer);
299+ }
300+ else {
301+ token.type = TOKEN_LT;
302+ advance(lexer);
303+ }
304+ break;
305+ 
306+ case '(':
307+ token.type = TOKEN_LPAREN;
308+ advance(lexer);
309+ break;
310+ 
311+ case ')':
312+ token.type = TOKEN_RPAREN;
313+ advance(lexer);
314+ break;
315+ 
316+ case '{':
317+ token.type = TOKEN_LBRACE;
318+ advance(lexer);
319+ break;
320+ 
321+ case '}':
322+ token.type = TOKEN_RBRACE;
323+ advance(lexer);
324+ break;
325+ 
326+ case '[':
327+ token.type = TOKEN_LBRACKET;
328+ advance(lexer);
329+ break;
330+ 
331+ case ']':
332+ token.type = TOKEN_RBRACKET;
333+ advance(lexer);
334+ break;
335+ 
336+ case ',':
337+ token.type = TOKEN_COMMA;
338+ advance(lexer);
339+ break;
340+ 
341+ case ';':
342+ token.type = TOKEN_SEMICOLON;
343+ advance(lexer);
344+ break;
345+ 
346+ case ':':
347+ token.type = TOKEN_COLON;
348+ advance(lexer);
349+ break;
350+ 
351+ case '.':
352+ if (peek_char(lexer, 1) == '.' && peek_char(lexer, 2) == '.') {
353+ if (peek_char(lexer, 3) == '=') {
354+ token.type = TOKEN_ELLIPSIS_EQ;
355+ strcpy(token.lexeme, "...=");
356+ advance(lexer);
357+ advance(lexer);
358+ advance(lexer);
359+ advance(lexer);
360+ }
361+ else {
362+ token.type = TOKEN_ELLIPSIS;
363+ strcpy(token.lexeme, "...");
364+ advance(lexer);
365+ advance(lexer);
366+ advance(lexer);
367+ }
368+ }
369+ else {
370+ token.type = TOKEN_ERROR;
371+ strcpy(token.lexeme, "Invalid token: single dot not supported");
372+ lexer->has_error = true;
373+ advance(lexer);
374+ }
375+ break;
376+ 
377+ default:
378+ token.type = TOKEN_ERROR;
379+ sprintf(token.lexeme, "Unknown character: '%c'", c);
380+ lexer->has_error = true;
381+ advance(lexer);
382+ break;
383+ }
384+ 
385+ return token;
386+}
387+ 
388+// 打印token信息
389+void print_token(Token token) {
390+ const char* type_names[] = {
391+ "AS", "BREAK", "CASE", "CONST", "CONTINUE", "DO", "ELSE", "FOR", "FROM", "FUNC",
392+ "IF", "IN", "LET", "MAIN", "MATCH", "VAR", "WHERE", "WHILE",
393+ "ID", "NUM",
394+ "PLUS", "MINUS", "STAR", "SLASH", "ASSIGN", "LPAREN", "RPAREN", "LBRACE", "RBRACE",
395+ "LBRACKET", "RBRACKET", "COMMA", "SEMICOLON", "LT", "GT", "NOT", "COLON",
396+ "NE", "GE", "LE", "EQ", "ELLIPSIS", "ELLIPSIS_EQ",
397+ "COMMENT_SINGLE", "COMMENT_MULTI", "EOF", "ERROR"
398+ };
399+ 
400+ if (token.type == TOKEN_ERROR) {
401+ printf("Line %d, Column %d: ERROR - %s\n",
402+ token.line, token.column, token.lexeme);
403+ }
404+ else {
405+ printf("Line %d, Column %d: %-20s %s\n",
406+ token.line, token.column, type_names[token.type], token.lexeme);
407+ }
408+}
409+ 
410+// 主函数 - 测试词法分析器
411+int main() {
412+ const char* corrected_test_code =
413+ "func main() {\n"
414+ " let x = 123;\n"
415+ " let userName = testValue; // 修正:使用合法标识符\n"
416+ " let abc123 = 456; // 修正:标识符以字母开头\n"
417+ " let count = 100; // 修正:使用整数而不是浮点数\n"
418+ " if x > 100 {\n"
419+ " break;\n"
420+ " }\n"
421+ " for i in 1...10 { // 修正:使用正确的区间运算符\n"
422+ " const totalScore = 789; // 修正:使用合法标识符\n"
423+ " }\n"
424+ " let result = value; // 修正:使用合法标识符\n"
425+ " let range = 1...10; // 修正:使用正确的区间运算符\n"
426+ " /* 这是一个正常的多行注释 */\n"
427+ " let validName = value; // 正常代码\n"
428+ " // 单行注释:计算总和\n"
429+ " let sum = a + b * c;\n"
430+ "}\n";
431+ 
432+ printf("Analyzing corrected code (no lexical errors):\n%s\n", corrected_test_code);
433+ printf("Tokens:\n");
434+ 
435+ Lexer lexer;
436+ init_lexer(&lexer, corrected_test_code);
437+ 
438+ Token token;
439+ int token_count = 0;
440+ int max_tokens = 200;
441+ int error_count = 0;
442+ 
443+ do {
444+ token = next_token(&lexer);
445+ print_token(token);
446+ if (token.type == TOKEN_ERROR) {
447+ error_count++;
448+ }
449+ token_count++;
450+ } while (token.type != TOKEN_EOF && token_count < max_tokens);
451+ 
452+ printf("\nTotal errors detected: %d\n", error_count);
453+ if (error_count > 0) {
454+ printf("Lexical analysis completed with errors.\n");
455+ }
456+ else {
457+ printf("Lexical analysis completed successfully.\n");
458+ }
459+ 
460+ return 0;
461+}
A廖志宏-2025001/编译原理实验/README.txt+176-0文件内容审核中,请稍后刷新重试
Binary files do not support preview
A廖志宏-2025001/编译原理实验/include/lexer.h+68-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/include/parser.h+66-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/include/semantic.h+68-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/include/vm.h+57-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/src/lexer.c+479-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/src/main.c+169-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/src/parser.c+1076-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/src/semantic.c+1066-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/src/vm.c+468-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/test_all.txt+77-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/test_correct.txt+41-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/test_func_param.txt+8-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/test_func_param_error.txt+10-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/test_func_vars.txt+14-0文件内容审核中,请稍后刷新重试
A廖志宏-2025001/编译原理实验/test_nested_funcs.txt+20-0文件内容审核中,请稍后刷新重试