自己编写cdecl:
//char * const *(*next)();示例
//结果:identifier is(标识符是)next
//指向next的指针函数返回指向const的指针指向char的指针error:stack empty
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#define MAXTOKENLEN 100
#define MAXTOKEN 100
#define BUFSIZE 100
#define MAXVAL 100
#define DATATYPE "int short long char float double void"
struct token {
char type;
char string[MAXTOKENLEN];
};
int getch(void);
void ungetch(int c);
void push(double f);
double pop(void);
char read_to_first_identifier();
char deal_with_function_args();
void deal_with_declarator();
char deal_with_arrays();
void deal_with_any_pointers(int c);
struct token stack[MAXTOKENLEN];
struct token that;
char* p = that.string;
int bufp = 0;
int i = 1;
int j = 0;
int sp = 0;
double val[MAXVAL];
char buf[BUFSIZE];
int main() {
read_to_first_identifier();
deal_with_declarator();
}
//限定符返回1,类型符返回2,标识符返回3
int classify_string() {//类型名分类
if (!strcmp(that.string, "const"))//比对类型名是否为const
{
strcpy(stack[j++].string, "const");//复制类型名const给datatype
return 1;
}
else if (!strcmp(that.string, "volatile"))//比对类型名是否为const
{
strcpy(stack[j++].string, "volatile");//复制类型名const给datatype
return 1;
}
else if (strstr(DATATYPE, that.string) != NULL)//在DATATYPE中匹配数据类型
{
strcat(stack[j++].string,that.string);//正常情况下声明的第一个符号是数据类型,即int.
return 2;
}
else printf("can not identify the \"%s\" datatype\n", that.string);
strcat(stack[j++].string, that.string);
return 3;
}
char gettoken(void) /* 返回下一个符号 */
{
int c;
int num;
while ((c = getch()) == ' ' || c == '\t');
if (isalpha(c)) {
for (*p = c, i = 1; isalnum(c = getch()) && c != ' '; i++)
{
*(p + i) = c;
}
ungetch(c);
*(p+i) = '\0';
num=classify_string();
//printf("%s\n", that.string);
return num;
}
else {
push(c);
*that.string = NULL;
//printf("%s\n", that.string);
//printf("1");
return 2;
}
}
char read_to_first_identifier() {//独至第一个标识符
int c1;
do {
c1 = gettoken();
} while (c1 != 3);//读取第一个输入的符号
printf("identifier is(标识符是)%s \n", that.string);
return 0;
}
char deal_with_function_args() {//处理函数参数
char c;
if ((c = getch()) == ')') //判断是否为()
printf("函数返回");
else
push(c);//将‘(’压入堆栈
return 0;
}
char deal_with_arrays() {//处理函数数组
char c=0;
for (*p++ = c; (*p++ = getch()) != ']'; )//从[开始读取,直到读取]退出循环
;
*p = '\0';
return 0;
}
void deal_with_any_pointers(int c) {//处理任何指针
int b;
for(;(b=pop())=='*';) {
printf("指向%s的指针",stack[--j].string);
}
push(b);
if (c == '*')
printf("指向%s的指针",stack[--j].string);
}
void deal_with_declarator() {//处理声明器
char c;
if ((c = getch()) == '[')
deal_with_arrays();
//else push(c);
if (c == '(')
deal_with_function_args();
//else push(c);
deal_with_any_pointers(c);
if((c = pop()) != NULL) {
if (c == '(')
{
//gettoken();
deal_with_declarator();
}
else printf("%c", c);
}
}
void push(double f)
{
if (sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can't push %g\n", f);
return;
}
double pop(void)
{
if (sp > 0)
return val[--sp];
else
{
printf("error:stack empty\n");
return 0;
}
}
int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if (bufp >= BUFSIZE)
printf("ungetch:too many characters");
else buf[bufp++] = c;
}
书中解析cdecl:
//C专家编程代码
//测试用例 char * const *(*next)();
//输出 next is pointer to function returning pointer to read-only pointer to char
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#define MAXTOKENLEN 64
#define MAXTOKENS 100
enum type_tag{IDENTIFIER,QUALIFIER,TYPE};
struct token {
char type;
char string[MAXTOKENLEN];
};
int top = -1;
struct token stack[MAXTOKENS];
struct token that;
#define pop stack[top--] //宏定义堆栈取出
#define push(s) stack[++top]=s //宏定义堆栈压入
enum type_tag classify_string(void){
/*推断标识符的类型*/
char *s = that.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)/*读取下一个标记到“that”*/
{
char* p = that.string;
/*掠过空白符*/
while ((*p = getchar()) == ' ');
if (isalpha(*p)||*p=='_') {//判定标识符、限定符、定义类型符
/*读入标识符以A-Z,a-z或_开头*/
while (isalnum(*++p = getchar()));
ungetc(*p, stdin);//将最后一个判定不是数字或字母或_的字符放到输入流中,以便它是下一个被读取的字符
*p = '\0';
that.type = classify_string();
return;
}
if (*p == '*') {//处理*
strcpy(that.string, "pointer to");
that.type = '*';
return;
}
that.string[1] = '\0';
that.type = *p;
return;
}
/*理解所有分析过程的代码*/
void read_to_first_identifer() {
gettoken();
while (that.type != IDENTIFIER) {//标识符判定
push(that);
gettoken();
}
printf("%s is", that.string);
gettoken();
}
void deal_with_arrays() {
while (that.type == '[') {//处理数组
printf("array");
gettoken();/*数字或']'*/
if (isdigit(that.string[0])) {
printf("0..%d", atoi(that.string) - 1);
gettoken();/*读取']'*/
}
gettoken();/*读取']'之后的再一个标记*/
printf("of ");
}
}
void deal_with_function_args() {//处理函数参数
while (that.type != ')') {
gettoken();
}
gettoken();
printf("function returning");
}
void deal_with_pointers() {//处理任何指针
while (stack[top].type == '*') {
printf(" %s ", pop.string);
}
}
void deal_with_declarator() {
/*处理标识符之后可能存在的数组/函数*/
switch (that.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_identifer();
deal_with_declarator();
printf("\n");
return 0;
}
FMS实现cdecl:
/*用FMS实现cdecl*/
//示例 char*(*c[10])(int **p);
//输出结果 c is array 0..9 of pointer to function returning pointer to char
/*用FMS实现cdecl*/
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
//#define this that
#define MAXTOKENS 100
#define MAXTOKENLEN 64
enum type_tag { IDENTIFIER, QUALIFIER, TYPE };
struct token {
char type;
char string[MAXTOKENLEN];
};
int top = -1;
/*在第一个标识符(identifier)前保存所有的标记(token)*/
struct token stack[MAXTOKENS];
/*保存刚读入的标记*/
struct token that;
#define pop stack[top--]
#define push(s) stack[++top]=s
enum type_tag;
int classify_string(void)
/*判断标识符的类型*/
{
char* s = that.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)
{/*读入下一个标记,保存在“this”中*/
char* p = that.string;
char c = 0;
/*略过所有的空白符*/
while ((c = getchar()) == ' ') ;
*p = c;
/*在标识符中读入A-Z,1-9字符*/
if (isalpha(*p)) {
while (isalnum(*++p = getchar())) ;
ungetc(*p, stdin);//将标记压栈
*p = '\0';
that.type = classify_string();//将标记进行匹配
return;
}
/*对数组中数字进行判断*/
if (isdigit(*p)) {
while (isdigit(*++p = getchar()));
ungetc(*p, stdin);//将标记压栈
*p = '\0';
return;
}
that.string[1] = '\0';
that.type = *p;
return;
}
void initialize(), get_array(), get_params(),
get_lparen(), get_ptr_part(), get_type();
void (*nextstate)(void) = initialize;
int main()
/*用有限机状态实现Cdecl*/
{
/*在不同的状态间转换,直到指针为null*/
while (nextstate != NULL)
(*nextstate)();
return 0;
}
void initialize()
{
gettoken();
while (that.type != IDENTIFIER) {
push(that);//将标记压入堆栈stack[]
gettoken();
}
printf("%s is ", that.string);
gettoken();
nextstate = get_array;
}
/*数组处理*/
void get_array()
{
nextstate = get_params;
while (that.type == '[') {
printf("array ");
gettoken();/*一个数字或‘]'*/
if(isdigit(that.string[0])) {
printf("0..%d ", atoi(that.string) - 1);
gettoken();/*读取’]‘*/
}
gettoken();/*在']'之后读取*/
printf("of ");
nextstate = get_lparen;
}
}
/*函数处理*/
void get_params() {
nextstate = get_lparen;
if (that.type == '(') {
while (that.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");
}
由于前文代码由本人自己撰写,与书中略有出处,如有问题,欢迎私信本人,愿共勉;