📄 main.c
字号:
/*编译和运行环境 * gcc4.3.2 * Archlinux-2.6.26 * 使用方法 * 命令行输入 gcc main.c && ./a.out Test.cmm*/#include "cmm.h"int main (int argc, char * argv[]) { fname = argv[1]; fin = fopen(fname,"r"); /* 只读打开文件 */ if (fin) { init(); while (getsym() != -1) { printsym(6); } } else{ printf("Can't open file! \n"); } return 0;}void init() { int i; /* 初始化单字符的Token值 */ for (i = 0; i <= 255; i++) { ssym[i] = nul; } ssym['+'] = plus; ssym['-'] = minus; ssym['*'] = times; ssym['/'] = slash; ssym['('] = lparen; ssym[')'] = rparen; ssym['['] = lbracket; ssym[']'] = rbracket; ssym['{'] = lbrace; ssym['}'] = rbrace; ssym['='] = assign; ssym[','] = comma; ssym['.'] = period; ssym[';'] = semicolon; /* 设置保留字的名字,按照字母顺序,便于折半查找 */ strcpy(&(word[0][0]), "const"); strcpy(&(word[1][0]), "else"); strcpy(&(word[2][0]), "if"); strcpy(&(word[3][0]), "int"); strcpy(&(word[4][0]), "read"); strcpy(&(word[5][0]), "real"); strcpy(&(word[6][0]), "while"); strcpy(&(word[7][0]), "write"); /* 设置保留字对应的symbol */ wsym[0] = constsym; wsym[1] = elsesym; wsym[2] = ifsym; wsym[3] = intsym; wsym[4] = readsym; wsym[5] = realsym; wsym[6] = whilesym; wsym[7] = writesym;}/* * 漏掉空格,读取一个字符 * 每次读一行,存入line缓冲区,line被getsym取空后再读一行 * 被函数getsym调用 */int getch() { if ( cc == ll ) { /* cc == ll说明当前行已经分析完成,或者开始分析第一行 */ if ( feof(fin) ) { /* 文件结束 */ printf("program incomplete"); return -1; } ll = 0; cc = 0; ch = ' '; /* 清空上一行余留的字符 */ memset(line,0,sizeof(line)); while (ch != 10) { /* 碰到换行符停止循环 */ if (EOF == fscanf(fin,"%c",&ch)) { /* 文件结束 */// printf("文件结束了!此时ch=%d,ll=%d,cc=%d,linenum=%d\n",ch,ll,cc,linenum); return -1; } line[ll] = ch; ll++; } linenum++; printline();// printf("while循环结束后ch=%d,ll=%d,cc=%d,linenum=%d,line=%s\n",ch,ll,cc,linenum,line); } ch = line[cc]; cc++;// printf("最后ch=%d,ll=%d,cc=%d,linenum=%d\n",ch,ll,cc,linenum); return 0;}/* 词法分析,获取下一个Token */int getsym() { int i, j, k; while ( ch == ' ' || ch == 10 || ch == 9) { /* 忽略空格,换行符和TAB */ getchdo; /* 忽略后获取下个字符 */ } if (ch >= 'a' && ch <= 'z') { /* 检测标识符和关键字 */ k = 0; do { if (k < al) { a[k] = ch; k++; } getchdo; }while (ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9'); a[k] = 0; strcpy(id,a); strcpy(value,a); i = 0; j = norw - 1; while (i <= j) { k = (i+j)/2; if (strcmp(id,word[k]) < 0) { /* word[k] 表示 word[k][0]的地址 */ j = k-1; } else if (strcmp(id,word[k]) > 0) { i = k+1; } else { break; } } if (i > j) { sym = ident; /* 设置当前符号为ident */ } else { sym = wsym[k]; /* 设置当前符号为某保留字的symbol */ } } else { if (ch >= '0' && ch <= '9') { /* 检测数字 */ k = 0; /* 当前number的位数 */ num = 0; sym = number; do { /* 继续检查后面的数字 */ if (ch == '.') { /* 处理小数部分 */ sym = real; realvalue = num; e = 0.1; k++; getchdo; while (ch >= '0' && ch <= '9') { int ich = ch-'0'; realvalue += e*ich; e*=0.1; getchdo; } } else { /* 处理整数部分 */ num=10*num+ch-'0'; k++; getchdo; } } while(ch >= '0' && ch <= '9' || ch == '.'); k--; if( k > nmax){ printf("number too long!\n"); exit(0); } } else { if (ch == '=') { /* 检测赋值符号和等于号 */ getchdo; if (ch == '=') { sym = eql; getchdo; } else { sym = assign; } } else { if (ch == '<') { /* 检测小于号和小于等于号*/ getchdo; if (ch == '=') { sym = leq; getchdo; } else { sym = lss; } } else { if (ch == '>') { /* 检测大于号和大于等于号*/ getchdo; if (ch == '=') { sym = geq; getchdo; } else { sym = gtr; } } else { if (ch == '!') { /* 检测不等号 */ getchdo; if (ch == '=') { sym = neq; getchdo; } else { sym = ssym['!']; } } else { /* 当前符号不满足上述条件时,全部按照单字符号处理 */ sym = ssym[ch]; getchdo; } } } } } } return 0; }/* 打印当前Token的值 */void printsym (int offset) { int i; if (sym != 0) { for (i = 0; i< offset; i++) { printf(" "); } switch (sym) { case ident : printf("identifier : %s\n",value);break; case number : printf("number : %d\n",num);break; case real : printf("real : %f\n",realvalue);break; case plus : printf("plus : +\n");break; case minus : printf("minus : -\n");break; case times : printf("times : *\n");break; case slash : printf("slash : /\n");break; case eql : printf("equal : ==\n");break; case neq : printf("not equal : !=\n");break; case lss : printf("less than : <\n");break; case leq : printf("less equal : <=\n");break; case gtr : printf("greater than : >=\n");break; case geq : printf("greater equal : >=\n");break; case lparen : printf("lparen : (\n");break; case assign : printf("assign : =\n");break; case rparen : printf("rparen : )\n");break; case lbracket : printf("lbracket : [\n");break; case rbracket : printf("rbracket : ]\n");break; case lbrace : printf("lbrace : {\n");break; case rbrace : printf("rbrace : }\n");break; case comma : printf("comma : ,\n");break; case semicolon : printf("semicolon : ;\n");break; case period : printf("period : .\n");break; case constsym : printf("keyword : const\n");break; case elsesym : printf("keyword : else\n");break; case ifsym : printf("keyword : if\n");break; case intsym : printf("keyword : int\n");break; case readsym : printf("keyword : read\n");break; case realsym : printf("keyword : real\n");break; case whilesym : printf("keyword : while\n");break; case writesym : printf("keyword : write\n");break; } }}/* 打印当前行 */void printline () { int i; printf(" %d: ",linenum); for (i = 0; i < sizeof(line); i++) { if (line[i] != 32 && line[i] != 10 && line[i] != 9) { break; } } for (i;i < sizeof(line) && line[i] != '\n'; i++) { printf("%c",line[i]); } printf("\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -