最近在看C专家编程,有一个编程挑战:编写一个程序,把C语言的声明翻译成通俗语言。很像编译原理中的词法分析部分与语法制导的部分。上个学期虽然自己也敲了编译器的各个环节但是自己写的C语言和书上的相比真的略显稚嫩。书上提供的代码真的很完美的感觉,记录在这里以后也方便品读。。。
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
#define MAXTOKENS 100
#define MAXTOKENLEN 64
//IDENTIFIER标识符,QUALIFIER限定符,TYPE类型
enum type_tag {IDENTIFIER, QUALIFIER, TYPE};
struct token
{
char type;//类型
char string[MAXTOKENLEN];//存储读取的字符串
};
int top = -1;
struct token stack[MAXTOKENS];//保存第一个标记之前的所有标记
struct token this;//保存刚读入的标记
#define pop stack[top --]
#define push(s) stack[++top] = s
//字符串分类
enum type_tag classify_string(void)
{
char *s = this.string;
if(!strcmp(s, "const"))
{
strcpy(s, "read-only");
return QUALIFIER;
}
if(!strcmp(s, "volatile")) return QUALIFIER;
if(!strcmp(s, "void")) return TYPE;
if(!strcmp(s, "char")) return TYPE;
if(!strcmp(s, "signed")) return TYPE;
if(!strcmp(s, "unsigned")) return TYPE;
if(!strcmp(s, "short")) return TYPE;
if(!strcmp(s, "int")) return TYPE;
if(!strcmp(s, "long")) return TYPE;
if(!strcmp(s, "float")) return TYPE;
if(!strcmp(s, "double")) return TYPE;
if(!strcmp(s, "struct")) return TYPE;
if(!strcmp(s, "union")) return TYPE;
if(!strcmp(s, "enum")) return TYPE;
return IDENTIFIER;
};
//读取一个词法记号
void gettoken(void)
{
char *p = this.string;
//跳过空格
while((*p = getchar()) == ' ');
if(isalnum(*p))
{
while(isalnum(*++p = getchar()));//判断字符是否时字母或者数字,读入到string数组中
ungetc(*p, stdin);//把一个字符退回到文件流
*p = '\0';
this.type = classify_string();
return ;
}
if(*p == '*')
{
strcpy(this.string, "pointer to");
this.type = '*';
return ;
}
this.string[1] = '\0';
this.type = *p;
return;
}
//读取声明直到读到第一个标识符
void read_to_first_identifier()
{
gettoken();
while(this.type != IDENTIFIER)
{
push(this);
gettoken();
}
printf("%s is ",this.string);
gettoken();
}
//处理数组
void deal_with_arrays()
{
while(this.type == '[')
{
printf("array ");
gettoken();
if(isdigit(this.string[0]))
{
printf("0..%d ",atoi(this.string)-1);
gettoken();
printf("of ");
}
}
}
//处理函数参数
void deal_with_function_args()
{
while(this.type != ')')
gettoken();
gettoken();
printf("function returning ");
}
//处理任何指针
void deal_with_pointers()
{
while(stack[top].type == '*')
printf("%s ",pop.string);
}
//处理声明器
void deal_with_declarator()
{
switch(this.type)
{
case '[':
deal_with_arrays();
break;
case '(':
deal_with_function_args();
}
deal_with_pointers();
while(top >= 0)
{
if(stack[top].type == '(')
{
pop;
gettoken();
deal_with_declarator();
}
else
{
printf("%s ",pop.string);
}
}
}
int main()
{
read_to_first_identifier();
deal_with_declarator();
putchar('\n');
return 0;
}