cdecl程序

#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#define MAXTOKENS 100			
#define	MAXTOKENLEN 64
int top=-1;
enum type_tag{IDENTIFIER,QUALIFIER,TYPE};
//标识符,限定符,类型 
struct token
{
	char type;
	char string[MAXTOKENLEN];
};
#define pop stack[top--]			
#define	push(s) stack[++top]=s
struct token THIS;//保存刚读入的标记 
struct token stack[MAXTOKENS];//保存第一个标记之前的标记 

enum type_tag classify_string()//推断标识符的类型
{
	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;
}

//读取下一个标记到this
void gettoken()
{
	char *p=THIS.string;
	//略过空白字符
	while((*p=getchar())==' ');
	if(isalnum(*p))
	{
		//读入的标识符以A-Z,0-9开头
		while(isalnum(*++p=getchar()));
		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]))
		{
			int temp;
			sscanf(THIS.string,"%d",&temp);
			printf("0..%d ",temp-1);
			gettoken();//读取']'
		}
		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();
				 break;
	}
	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();
	printf("\n");
	return 0;
}

#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#define MAXTOKENS 100
#define MAXTOKENLEN 64
int top=-1;
enum type_tag{IDENTIFIER, QUALIFIER, TYPE};
//标识符,限定符,类型
struct token 
{
    char type;
    char string[MAXTOKENLEN];
};
#define pop stack[top--]
#define push(s) stack[++top]=s
struct token stack[MAXTOKENS];
struct token THIS;

enum type_tag classify_string()//推断标识符的类型 
{ 
	char *s=THIS.string;
	if(!strcmp(s,"const")) 
	{
        strcpy(s,"read-only");
        return QUALIFIER;
    }
    if(strcmp(s,"volatile")==0) return QUALIFIER;
    if(strcmp(s,"void")==0) return TYPE;
    if(strcmp(s,"char")==0) return TYPE;
    if(strcmp(s,"signed")==0) return TYPE;
    if(strcmp(s,"unsigned")==0) return TYPE;
    if(strcmp(s,"short")==0) return TYPE;
    if(strcmp(s,"int")==0) return TYPE;
    if(strcmp(s,"long")==0) return TYPE;
    if(strcmp(s,"float")==0) return TYPE;
    if(strcmp(s,"double")==0) return TYPE;
    if(strcmp(s,"struct")==0) return TYPE;
    if(strcmp(s,"union")==0) return TYPE;
    if(strcmp(s,"enum")==0) return TYPE;
    return IDENTIFIER;
}

//读取下一个标记到this
void gettoken()
{
	char *p=THIS.string;
	//略过空白字符
	while((*p=getchar())==' ');
	if(isalnum(*p))
	{
		//读入的标识符以A-Z,0-9开头
		while(isalnum(*++p=getchar()));
		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 initialize(),get_array(),get_params(),get_lparen(),get_ptr_part(),get_type();
//初始化,处理数组,处理参数,处理括弧,处理指针,处理类型 
void (*nextstate)()=initialize;

int main() 
{
    //在不同的状态间切换直到指针值为NULL 
    while(nextstate!=NULL)
		(*nextstate)();
    return 0;
}

void initialize()
{
	gettoken();
    while(THIS.type!=IDENTIFIER) 
	{
        push(THIS);
        gettoken();
    }
    printf("%s is ",THIS.string);
    gettoken();
    nextstate=get_array;
}

void get_array() 
{
    nextstate=get_params;
    while(THIS.type == '[')
	{
		printf("array ");
        gettoken(); 
        if(isdigit(THIS.string[0])) 
		{
            printf("0..%d ",atoi(THIS.string)-1);
            gettoken(); 
        }
        gettoken(); 
        printf("of ");
        nextstate=get_lparen;
	}
}

void get_params()
{
    nextstate=get_lparen;
    if(THIS.type=='(') 
	{
        while(THIS.type != ')')
		{
            gettoken();
        }
        gettoken();
        printf("function returning ");
    }
}

void get_lparen()
{
    nextstate=get_ptr_part;
    if(top>=0)
	{
		if(stack[top].type=='(') 
		{
            pop;
            gettoken(); 
            nextstate=get_array;
        }
    }
}

void get_ptr_part() 
{
    nextstate=get_type;
    if(stack[top].type=='*') 
	{
        printf("pointer to ");
        pop;
        nextstate=get_lparen;
    } 
	else if(stack[top].type==QUALIFIER)
	{
        printf("%s ",pop.string);
        nextstate=get_lparen;
    }
}

void get_type() 
{
    nextstate=NULL;
    while(top>=0) 
	{
        printf("%s ",pop.string);
    }
    printf("\n");
}

参考《C专家编程》写的cdecl声明解析程序。第一个是非FSM版,第二个是FSM版。

你可能感兴趣的:(cdecl程序)