C - Make dcl recover from input errors

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

/*
 * Make dcl recover from input errors.
 *
 * Dcl.c - by FreeMan
 */

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

#define MAXTOKEN 100
 /* If you are doing this exercise for a course, you probably would
  * not be expected to do as much as you will find in this source file.
  *
  * You should be able to copy and paste most declarations from a
  * source file that you might find to the input to this dcl program.
  *
  * Notable limitations include: the reference operator '&' is not
  * handled, a symbolic constant that is in an array subscript
  * will be seen as an invalid subscript, type modifiers/qualifiers such as
  * static, const, long, short, unsigned, signed etc. are not handled.
  *
  * This dcl can handle multiple declarations on a line such as
  * char *p, line[MAXLEN];
  * dcl can also handle comments, and detects end of declaration indicators
  * such as ; or { or =.
  *
  * Recovery from errors is interpreted to mean that despite missing one of
  * [ or ] or ( or ) or NAME, an error message should be displayed and some
  * educated interpretation should be attempted. In the case of parentheses
  * it is sometimes difficult to know where they should have been so the
  * resulting interpretation will not necessarily be correct.
  *
  * In the case of a missing NAME, instead of outputting an error the name
  * is simply omitted from the output. The following for example:
  * char (*(*())[])()
  * will output:
  * function returning pointer to array[] of pointer to function returning char
  */

enum { NAME, PARENS, BRACKETS };

static void dcl(void);
static void dirdcl(void);

static int gettoken(void);
static int tokentype; /* Type of last token */
static int oldtoken; /* Previous tokentype */
static char token[MAXTOKEN]; /* Last token string */
static char name[MAXTOKEN]; /* Identifier name */
static char datatype[MAXTOKEN]; /* Data type = char, int, etc. */
static char out[1000]; /* Output string */
static int parenopen = 0; /* Count of open parentheses */
static int parenclose = 0; /* Count of unmatched close parentheses */
static int alphaseen = 0; /* Track alpha statis for subscript */

static int getch(void);
static void ungetch(void);

int main(void) /* Convert declaration to words */
{
	while (gettoken() != EOF) { /* 1st token on line */
		strcpy(datatype, token); /* Pull data type */
		while (tokentype != '\n') {
			out[0] = '\0';
			name[0] = '\0';
			token[0] = '\0';
			parenopen = 0;
			parenclose = 0;
			dcl(); /* Parse rest of line */
			if (parenopen > 0) {
				printf("Error: missing one or more )\n");
			}
			if (parenclose > 0) {
				printf("Error: missing one or more (\n");
			}
			printf("%s: %s %s\n", name, out, datatype);
		}
	}
	return 0;
}

/* dcl: Parse a declarator */
static void dcl(void)
{
	int ns;
	for (ns = 0; gettoken() == '*'; ) /* Count *'s */
	{
		ns++;
	}
	dirdcl();
	while (ns-- > 0)
	{
		strcat(out, " pointer to");
	}
}

/* dirdcl: Parse a direct declarator */
static void dirdcl(void)
{
	int tempparens;
	if (tokentype == ',') /* Allow multiple declarators on a line */
	{
		tokentype = '\n';
	}
	if (tokentype == '\n')
	{
		return;
	}
	if (tokentype == '(') /* ( dcl ) */
	{
		++parenopen;
		dcl();
		if (tokentype == ')')
		{
			--parenopen;
		}
		else
		{
			if (oldtoken == '(')
			{
				strcat(out, " function returning");
			}
			ungetch();
		}
	}
	else if (tokentype == NAME) /* variable name */
	{
		strcpy(name, token);
	}
	else if (tokentype == PARENS)
	{
		strcat(out, " function returning");
	}
	else if (tokentype == BRACKETS)
	{
		strcat(out, " array");
		strcat(out, token);
		strcat(out, " of");
	}
	else if (oldtoken == NAME && tokentype == ')')
	{
		++parenclose;
		strcat(out, " function returning");
	}
	else
	{
		printf("Error: expected name or (dcl)\n");
	}
	gettoken();
	while (tokentype == PARENS
		|| tokentype == BRACKETS
		|| tokentype == '('
		|| isdigit(tokentype)
		|| tokentype == NAME)
	{
		if (tokentype == PARENS)
		{
			strcat(out, " function returning");
		}
		else if (tokentype == BRACKETS)
		{
			strcat(out, " array");
			strcat(out, token);
			strcat(out, " of");
		}
		else if (tokentype == '(')
		{
			/* Process function with parameters... for now just ignoring them */
			/* Prevents detection of unmatched ) in gettoken() */
			++parenopen; /* Don't remove this! */
			tempparens = 1; /* Track balanced parentheses */
			strcat(out, " function returning");
			do
			{
				gettoken();
				if (tokentype == '(')
				{
					++tempparens;
				}
				else if (tokentype == ')')
				{
					--tempparens;
				}
				else if (tokentype == '\n')
				{
					return;
				}
			} while (tokentype != ')' || tempparens != 0);
			--parenopen;
		}
		else
		{
			/* Saw NAME or digit: it could be this was part of a parameter to
			 * a function or a subscript to an array */
			do
			{
				gettoken();
				if (tokentype == BRACKETS)
				{
					strcat(out, " array");
					strcat(out, token);
					strcat(out, " of");
					break; /* Exit do-while */
				}
				if (tokentype == PARENS)
				{
					strcat(out, " function returning");
					break; /* Exit do-while */
				}
			} while (tokentype != '\n');
			if (tokentype == '\n')
			{
				return;
			}
		}
		gettoken();
	}
}

/* gettoken: Return next token.*/
static int gettoken(void)
{
	int c;
	int i;
	char *p = token;
	oldtoken = tokentype; /* Back up tokentype */
	while ((c = getch()) == ' ' || c == '\t')
		;
	/* Remove comments */
	while (c == '/')
	{
		c = getch();
		if (c == '/')
		{
			while (c != '\n')
			{
				c = getch();
			}
		}
		if (c == '*') /* Start of comment */
		{
			do
			{
				c = getch();
				if (c == '*')
				{
					c = getch();
					if (c == '/')
					{
						c = getch();
						break;
					}
				}
			} while (c != '\n');
		}
	}
	/* Assume anything past one of these characters is something
	 * we do not care to process. */
	if (c == ';' || c == '{' || c == '=')
	{
		while (c != '\n')
		{
			c = getch();
		}
	}
	/* Count unmatched closing parentheses */
	if (c == ')' && parenopen == 0)
	{
		++parenclose;
		return tokentype = PARENS;
	}
	if (c == '(')
	{
		if ((c = getch()) == ')')
		{
			strcpy(token, "()");
			return tokentype = PARENS;
		}
		else
		{
			ungetch();
			return tokentype = '(';
		}
	}
	else if (c == '[') /* We sort of know what should be in here */
	{
		alphaseen = 0;
		for (*p++ = c, i = 0; (c = getch()); ++i)
		{
			while (c == ' ' || c == '\t') /* Allow for space */
			{
				c = getch();
			}
			if (i == 0 && isalpha(c))
			{
				*p++ = c;
				alphaseen = 1;
			}
			else if (isdigit(c) && alphaseen == 0)
			{
				*p++ = c;
			}
			else if (i > 0 && isalpha(c))
			{
				printf("Error: invalid array subscript\n");
				while (isalnum(c = getch()))
					;
				ungetch();
			}
			else if (isdigit(c) && alphaseen)
			{
				printf("Error: invalid array subscript\n");
				while (isalnum(c = getch()))
					;
				ungetch();
			}
			else if (c == ']')
			{
				*p++ = c;
				break;
			}
			else
			{
				printf("Error: missing ]\n");
				*p++ = ']';
				ungetch();
				break;
			}
		}
		*p = '\0';
		return tokentype = BRACKETS;
	}
	else if (c == ']') /* Unmatched closing bracket? */
	{
		printf("Error: missing [\n");
		*p++ = '[';
		*p++ = ']';
		*p = '\0';
		return tokentype = BRACKETS;
	}
	else if (isalpha(c) || c == '_') /* An _ is a valid char too */
	{
		for (*p++ = c; isalnum(c = getch()) || c == '_'; )
		{
			*p++ = c;
		}
		*p = '\0';
		ungetch();
		return tokentype = NAME;
	}
	else
	{
		return tokentype = c;
	}
}


#define BUFSIZE 1000

static char line[BUFSIZE]; /* Buffer for line */
static int bufp = 0; /* Position in buf */
static int readflag = 1;
static int get_line(char *s, int max_length);

/* getch: Read a character */
int getch(void)
{
	int length = 0;
	do
	{
		if (readflag == 1)
		{
			/* Prime the line array */
			if ((length = get_line(line, BUFSIZE)) > 0)
			{
				if (length >= (BUFSIZE - 1))
				{
					printf("Error: line buffer exceeded\n");
					return EOF;
				}
			}
			else
			{
				return EOF;
			}
			bufp = 0;
			readflag = 0;
		}
		if (line[bufp] == '\0')
		{
			readflag = 1; /* Need to read a new line */
		}
	} while (readflag);
	return line[bufp++];
}

/* ungetch: Push character back on input */
void ungetch(void)
{
	if (bufp > 0)
	{
		--bufp;
	}
}

/* print_source: Print out the contents of the line read */
void print_source(void)
{
	printf("%s", line);
}

/* getline: This version will read a line up to a maximum number of characters
 * (max_length - 1) and store a '\0' at the end. The number of characters
 * read is returned, if that is a 0 then we are done reading lines.
 */
int get_line(char *s, int max_length)
{
	int c;
	char *start = s; /* Save pointer to start of buffer s */
	char *end = s + (max_length - 2); /* Point near to end of buffer s */
	while ((c = getchar()) != EOF && c != '\n' && s < end) {
		*s++ = c;
	}
	/* Store last character read */
	if (c != EOF)
	{
		*s++ = c;
	}
	*s = '\0'; /* Terminate the line */
	return s - start; /* Number of characters read */
}

// Output:
/*
int *(*foo(void * p, int i, float f)[6]) x[66]
foo:  function returning array[6] of pointer to array[66] of pointer to int

*/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值