C专家编程 模块化与有限机编写cdecl声明程序

本文介绍了如何使用C语言实现cdecl函数声明的解析器。通过示例和代码,展示了从输入的函数声明如`char*const*(*next)()`,解析出如`next is pointer to function returning read-only pointer to char`的解释。文章包含三个不同实现:作者自编、书中解析和FMS实现,每个实现都详细解释了其工作原理和流程。
摘要由CSDN通过智能技术生成

自己编写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");
}

由于前文代码由本人自己撰写,与书中略有出处,如有问题,欢迎私信本人,愿共勉;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

入世浮尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值