要求
输入:源程序文件
输出:二元组(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] = ' ';
fseek(fp,-1,1);
c = lookup(TOKEN);
if (c != 0)
fprintf(wfp,"(%d,%s)
",c,TOKEN); // 关键字
else
fprintf(wfp,"(10,%s)
",TOKEN); // 标识符
} else if (isdigit(ch)) { // 数字开头
TOKEN[i++] = ch;
while (isdigit(ch=getc(fp))) {
TOKEN[i++] = ch;
}
TOKEN[i] = ' ';
fseek(fp,-1,SEEK_CUR);
fprintf(wfp,"(20,%s)
",TOKEN); // 数字
} else { // 其它符号开头
switch (ch) {
case ' ': break;
case '
': break;
case ' ': break;
case EOF: break;
case '=': ch=getc(fp);
if (ch == '=') {
fprintf(wfp,"(36,==)
"); break;
}
else {
fprintf(wfp,"(21,=)
"); break;
}
case '+': fprintf(wfp,"(22,+)
"); break;
case '-': fprintf(wfp,"(23,-)
"); break;
case '*': fprintf(wfp,"(24,*)
"); break;
case '/': fprintf(wfp,"(25,/)
"); break;
case '(': fprintf(wfp,"(26,()
"); break;
case ')': fprintf(wfp,"(27,))
"); break;
case '{': fprintf(wfp,"(28,{)
"); break;
case '}': fprintf(wfp,"(29,})
"); break;
case ',': fprintf(wfp,"(30,,)
"); break;
case ';': fprintf(wfp,"(31,;)
"); break;
case '>': ch=fgetc(fp);
if (ch == '=') {
fprintf(wfp,"(34,>=)
"); break;
}
else {
fprintf(wfp,"(32,>)
"); break;
}
case '<': ch=fgetc(fp);
if (ch == '=') {
fprintf(wfp,"(35,<=)
"); break;
}
else {
fprintf(wfp,"(33,<)
"); break;
}
case '!': tmp = ch;
ch=getc(fp);
if(ch == '=')
{
fprintf(wfp,"(37,!=)
");
break;
}
else
{
fprintf(wfp,"error:(0,%c)
",tmp);
fseek(fp,-1,1);
break;
}
default:
fprintf(wfp,"error:(0,%c)
",ch); break;
}
}
}
fclose(wfp);
}
int main(){
FILE* fp;
char ch;
if ((fp=fopen("input.txt","r")) == NULL){
printf("文件打开错误!
");
return 0;
}
scanner(fp);
fclose(fp);
return 0;
}