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