C++用來檢測數據類型的聲明工具代碼
#include <stdio.h>include <stdlib.h>
include <ctype.h>
include <string.h>
define MAXTOKENS 100
define MAXTOKENLEN 64
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
define STRCMP(a,R,b) (strcmp(a,b) R 0)
/推斷標識符類型/ 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,==,"double")) return TYPE; if (STRCMP(s,==,"float")) 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(void) { char *p = this.string;
/*略過空白字符*/ while((*p = (char)getchar()) == ' ') ; /*是字母或數字*/ if (isalnum(*p)) { while(isalnum(*++p = (char)getchar())) ; /*讀到下一個不是字母或數字為止*/ ungetc(*p,stdin); /*將一個字符回退到輸入流*/ *p = ''; this.type = (char)classify_string(); return; } if (*p == '*') { strcpy(this.string,"pointer to"); this.type = '*'; return; } this.string[1] = ''; this.type = *p; return;
}
/理解所有分析過程的代碼段/ int read_to_first_identifier(void) { gettoken(); /取第一個標記/ while(this.type != (char)IDENTIFIER) / 取到標識符終止,標識符未壓入棧 / { push(this); gettoken(); }
printf("%s is ",this.string); gettoken();/*再取標識符右邊一個符號*/ return 0;
}
int deal_with_arrays(void) { while(this.type == '[') { printf("array "); gettoken();/數字域或']'/ if (isdigit(this.string[0])) { printf("0..%d ",atoi(this.string)-1); gettoken(); /取']'/ }
gettoken(); /* 讀取']'后的下一個標記,可能還是一個'[' */ printf("of "); } return 0;
}
int deal_with_function_args(void) { while(this.type != ')') / 把函數參數取出來丟棄 / { gettoken(); }
gettoken(); /* 讀取')'后的下一個標記 */ printf("function returning "); return 0;
}
int deal_with_pointers(void) { while(stack[top].type == '*') { printf("%s ",pop.string); } return 0; }
int deal_with_declarator(void) { /處理標識符后可能存在的數組或函數/ switch(this.type) { case '[' : deal_with_arrays();break; case '(' : deal_with_function_args();break; default : break; }
deal_with_pointers(); /* 棧頂元素是'*' */ /*處理在讀到標識符之前壓入堆棧的符號*/ while(top >= 0) { if (stack[top].type == '(') { pop; gettoken(); /* 讀取')'之后的符號,可能是'('或'[' */ deal_with_declarator(); /* 遞歸調用 */ } else { printf("%s ",pop.string); } } return 0;
}
int main(void) { /將標記壓入堆棧中,直到遇見標識符/ read_to_first_identifier(); deal_with_declarator(); printf("n");
return 0;
}</pre>