要求
输入:源程序文件
输出:二元组(syn,token或sum)构成的序列(文件),其中:syn为单词种别码,token为存放的单词自身字符串,sum为整型常量。
已知待分析的C语言子集的词法:
1、关键字: main if else int while char 均为小写。
2、专用符号: = + - * / < <= > >= == != ; , { } ( )
3、其他标记ID和NUM通过以下正则式定义:
ID: letter(letter|digit)*
NUM: digit digit*
letter→a|b|c|d…|z|A|B|C…|Z
digit →0|1|2|3|4|5|6|7|8|9
4、空格由空白、制表符、换行符组成,用来分隔ID、NUM、专用符号与关键字,词法分析阶段常被忽略。
各种单词符号对应的种别码如下表:
源程序
程序中涉及两个文件:
input.txt 程序测试数据
output.txt 输出测试结果
#include <stdio.h> #include <ctype.h> #include <string.h> char TOKEN[20]; char TABLE[6][10] = {{"main"},{"int"},{"char"},{"if"},{"else"},{"while"}}; int lookup(char arr[]) { int i; for (int i = 0; i < 6; ++i) { if (!strcmp(arr,TABLE[i])) return i+1; } return 0; } // 扫描器 void scanner(FILE* fp) { char ch, tmp; int i, c; FILE* wfp = fopen("output.txt","w"); while (ch != EOF) { // 一次循环即扫描一个词 i = 0; ch = getc(fp); if (isalpha(ch)){ // 字母开头 TOKEN[i++] = ch; while (isalpha(ch=getc(fp))|| isdigit(ch)) { TOKEN[i++] = ch; } TOKEN[i] = '\0'; fseek(fp,-1,1); c = lookup(TOKEN); if (c != 0) fprintf(wfp,"(%d,%s)\n",c,TOKEN); // 关键字 else fprintf(wfp,"(10,%s)\n",TOKEN); // 标识符 } else if (isdigit(ch)) { // 数字开头 TOKEN[i++] = ch; while (isdigit(ch=getc(fp))) { TOKEN[i++] = ch; } TOKEN[i] = '\0'; fseek(fp,-1,SEEK_CUR); fprintf(wfp,"(20,%s)\n",TOKEN); // 数字 } else { // 其它符号开头 switch (ch) { case ' ': break; case '\n': break; case '\t': break; case EOF: break; case '=': ch=getc(fp); if (ch == '=') { fprintf(wfp,"(36,==)\n"); break; } else { fprintf(wfp,"(21,=)\n"); break; } case '+': fprintf(wfp,"(22,+)\n"); break; case '-': fprintf(wfp,"(23,-)\n"); break; case '*': fprintf(wfp,"(24,*)\n"); break; case '/': fprintf(wfp,"(25,/)\n"); break; case '(': fprintf(wfp,"(26,()\n"); break; case ')': fprintf(wfp,"(27,))\n"); break; case '{': fprintf(wfp,"(28,{)\n"); break; case '}': fprintf(wfp,"(29,})\n"); break; case ',': fprintf(wfp,"(30,,)\n"); break; case ';': fprintf(wfp,"(31,;)\n"); break; case '>': ch=fgetc(fp); if (ch == '=') { fprintf(wfp,"(34,>=)\n"); break; } else { fprintf(wfp,"(32,>)\n"); break; } case '<': ch=fgetc(fp); if (ch == '=') { fprintf(wfp,"(35,<=)\n"); break; } else { fprintf(wfp,"(33,<)\n"); break; } case '!': tmp = ch; ch=getc(fp); if(ch == '=') { fprintf(wfp,"(37,!=)\n"); break; } else { fprintf(wfp,"error:(0,%c)\n",tmp); fseek(fp,-1,1); break; } default: fprintf(wfp,"error:(0,%c)\n",ch); break; } } } fclose(wfp); } int main(){ FILE* fp; char ch; if ((fp=fopen("input.txt","r")) == NULL){ printf("文件打开错误!\n"); return 0; } scanner(fp); fclose(fp); return 0; }