#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版。