C - Expand dcl to handle declarations with function argument types, qualifiers like const, and so on

分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击人工智能教程

/*
 * Expand dcl to handle declarations with function argument types,
 * qualifiers like const, and so on.
 *
 * ExpandDcl.c - by FreeMan
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define MAXSYMBL (1 << 7)
#define MAXMSG (1 << 10)
#define MAXCHBUF (1 << 1)
#define MAXTKBUF (1 << 1)
#define MAXBOILER (1 << 4)

enum { STORE, QUAL, TYPE, VAR, BRACKETS };
enum { OK = 0, ERROR };
enum { NO = 0, YES };

int declaration(char *dec, int ispara);
int dcl(char *name, char *out, int allowanon);
int dirdcl(char *name, char *out, int allowanon);
int args(char *out);
int gettoken(void);
void ungettoken(int ttype, char *tk);
int ws(void);
int name(char *p);
int brackets(char *p);
int oparens(char *p);
int contains(char **names, int count, char *name);
void nextdef(void);
int getch(void);
void ungetch(int c);

int tokentype;
char token[MAXSYMBL];
int chbuf[MAXCHBUF];
int chbufp = 0;
int ttbuf[MAXTKBUF];
char tkbuf[MAXTKBUF][MAXSYMBL];
int tkbufp = 0;
char *types[] = { "void", "char", "short", "int", "long", "float", "double", "signed", "unsigned" };
int ntypes = 9;
char *stores[] = { "auto", "register", "static", "extern" };
int nstores = 4;
char *quals[] = { "const", "volatile" };
int nquals = 2;

int main(void)
{
	char dec[MAXMSG];
	while (gettoken() != EOF)
	{
		if (declaration(dec, NO) != OK)
		{
			nextdef();
		}
	}
	return 0;
}

int declaration(char *dec, int ispara)
{
	char store[MAXSYMBL + MAXBOILER];
	char qual[MAXSYMBL + MAXBOILER];
	char type[MAXMSG];
	char name[MAXSYMBL];
	char out[MAXMSG];

	store[0] = '\0';
	qual[0] = '\0';
	type[0] = '\0';

	if (tokentype == STORE)
	{
		sprintf(store, " in %s storage", token);
		gettoken();
	}
	if (tokentype == QUAL)
	{
		sprintf(qual, " %s", token);
		gettoken();
	}
	if (tokentype != TYPE)
	{
		printf("\nERROR: Expected a type\n");
		return ERROR;
	}

	do
	{
		if (type[0] != '\0')
		{
			strcat(type, " ");
		}
		strcat(type, token);
	} while (gettoken() == TYPE);
	ungettoken(tokentype, token);

	do
	{
		out[0] = '\0';
		if (dcl(name, out, ispara) != OK)
		{
			return ERROR;
		}
		else if (tokentype != ';' && tokentype != ',' && tokentype != ')')
		{
			printf("\nSytax error, got %d/%c\n", tokentype, tokentype);
			return ERROR;
		}
		else
		{
			sprintf(dec, "%s:%s%s %s%s", name, qual, out, type, store);
			if (!ispara)
			{
				printf("\n%s\n", dec);
			}
		}
	} while (!ispara && tokentype == ',');
	return OK;
}

int dcl(char *name, char *out, int allowanon)
{
	int ns, rslt;

	for (ns = 0; gettoken() == '*';)
	{
		ns++;
	}
	if ((rslt = dirdcl(name, out, allowanon)) != OK)
	{
		return rslt;
	}
	while (ns-- > 0)
	{
		strcat(out, " pointer to");
	}
	return OK;
}

int dirdcl(char *name, char *out, int allowanon)
{
	int rslt;

	if (tokentype == VAR)
	{
		strcpy(name, token);
	}
	else if (tokentype == '(')
	{
		if ((rslt = dcl(name, out, allowanon)) != OK)
		{
			return rslt;
		}
		if (tokentype != ')')
		{
			printf("\nerror: missing )\n");
			return ERROR;
		}
	}
	else if (allowanon)
	{
		strcpy(name, "<unnamed>");
		allowanon = NO;
		ungettoken(tokentype, token);
	}
	else
	{
		printf("\nERROR: expected variable name or (dcl)\n");
		return ERROR;
	}
	while (gettoken() == '(' || tokentype == BRACKETS)
	{
		if (tokentype == '(')
		{
			strcat(out, " function taking");
			if ((rslt = args(out)) != NO)
			{
				return rslt;
			}
		}
		else {
			strcat(out, " array");
			strcat(out, token);
			strcat(out, " of");
		}
	}
	return OK;
}

int args(char *out)
{
	char dec[MAXMSG];
	int argcount = 0;
	char *seperator = " argument ";
	int expectarg = YES;

	if (gettoken() == ')')
	{
		/* fun() */
		expectarg = NO;
	}
	else if (tokentype == TYPE && strcmp(token, "void") == 0)
	{
		if (gettoken() == ')')
		{
			/* fun(void) */
			expectarg = NO;
		}
		else
		{
			ungettoken(tokentype, token);
			tokentype = TYPE;
			strcpy(token, "void");
		}
	}

	if (expectarg)
	{
		do
		{
			if (argcount++ > 0)
			{
				gettoken();
			}
			if (declaration(dec, YES) != OK)
			{
				return ERROR;
			}
			strcat(out, seperator);
			strcat(out, dec);
			seperator = " and argument ";
		} while (tokentype == ',');
	}
	if (tokentype == ')')
	{
		if (argcount == 0)
		{
			strcat(out, " no arguments");
		}
		strcat(out, " returning");
	}
	else
	{
		printf("\nError: expected closing parentheses after arguments (got %d/%c)\n",
			tokentype, tokentype);
		return ERROR;
	}
	return OK;
}

int gettoken(void)
{
	if (tkbufp > 0)
	{
		--tkbufp;
		tokentype = ttbuf[tkbufp];
		strcpy(token, tkbuf[tkbufp]);
	}
	else
	{
		ws();
		if (!(oparens(token) || brackets(token) || name(token)))
		{
			token[0] = tokentype = getch();
			token[1] = '\0';
		}
	}
	return tokentype;
}

void ungettoken(int ttype, char *tk)
{
	if (tkbufp >= MAXTKBUF)
	{
		printf("ungettoken: Too many tokens\n");
	}
	else
	{
		ttbuf[tkbufp] = ttype;
		strcpy(tkbuf[tkbufp], tk);
		tkbufp++;
	}
}

int ws(void)
{
	char c;
	int rslt = NO;

	while (isspace(c = getch()))
	{
		rslt = YES;
	}
	ungetch(c);
	return rslt;
}

int name(char *p)
{
	char c, *tkn;
	int rslt = NO;
	tkn = p;
	if (isalpha(c = getch()) || c == '_')
	{
		rslt = YES;
		for (*p++ = c; isalnum(c = getch()) || c == '_';)
		{
			*p++ = c;
		}
		*p = '\0';
		if (contains(types, ntypes, tkn))
		{
			tokentype = TYPE;
		}
		else if (contains(stores, nstores, tkn))
		{
			tokentype = STORE;
		}
		else if (contains(quals, nquals, tkn))
		{
			tokentype = QUAL;
		}
		else
		{
			tokentype = VAR;
		}
	}
	ungetch(c);
	return rslt;
}

int brackets(char *p)
{
	char c;

	if ((c = getch()) == '[')
	{
		for (*p++ = c; (*p++ = (c = getch())) != ']';)
			;
		*p = '\0';
		tokentype = BRACKETS;
		return YES;
	}
	ungetch(c);
	return NO;
}

int oparens(char *p)
{
	char c;

	if ((c = getch()) == '(')
	{
		*p++ = tokentype = '(';
		*p = '\0';
		return YES;
	}
	ungetch(c);
	return NO;
}

void nextdef(void)
{
	int c;

	while ((c = getch()) != ';' && c != EOF)
		;
	if (c == EOF)
	{
		ungetch(c);
	}
}

int contains(char **names, int count, char *name)
{
	int i;

	for (i = 0; i < count; i++)
	{
		if (strcmp(name, names[i]) == 0)
		{
			return YES;
		}
	}
	return NO;
}

int getch(void)
{
	return (chbufp > 0) ? chbuf[--chbufp] : getchar();
}

void ungetch(int c)
{
	if (chbufp >= MAXCHBUF)
	{
		printf("ungetch: Too many characters\n");
	}
	else
	{
		chbuf[chbufp++] = c;
	}
}

// Output:
/*
void arguments(char *name, double time);

arguments: function taking argument name: pointer to char and argument time: double returning void
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值