Skip to content

Commit e704ec7

Browse files
committed
rewrite
Simplified the code and used the revised error recovery approach from 5-18.
1 parent 3c6c063 commit e704ec7

File tree

1 file changed

+79
-78
lines changed

1 file changed

+79
-78
lines changed

chapter05/5-19.c

+79-78
Original file line numberDiff line numberDiff line change
@@ -1,124 +1,125 @@
11
/*
22
* Exercise 5-19. Modify undcl so that it does not add redundant parentheses to
33
* declaration.
4+
*
45
* By Faisal Saadatmand
5-
* */
6+
*/
67

8+
#include <ctype.h>
79
#include <stdio.h>
810
#include <string.h>
9-
#include <ctype.h>
10-
11-
#define MAXTOKEN 100
12-
#define BUFSIZE 100
1311

14-
#define SKIP_BLANKS(c) while (((c) = getch()) == ' ' || (c) == '\t')
12+
#define BUFSIZE 100
13+
#define MAXLEN 1000
14+
#define MAXTOKEN 100
1515

1616
enum { NAME, PARENS, BRACKETS };
17+
enum { GOOD, FAIL };
1718

1819
/* functions */
19-
int gettoken(void);
20-
int getch(void);
21-
void ungetch(int);
20+
void undcl(void);
21+
int gettoken();
2222

2323
/* globals */
24-
char token[MAXTOKEN]; /* last token string */
25-
int tokentype; /* type of last token */
26-
char name[MAXTOKEN]; /* identifier name */
27-
char out[1000];
28-
int buf[BUFSIZE]; /* buffer from ungetch */
29-
int bufp; /* next free position in buf */
30-
int pushedEOF; /* signals EOF has been pushed-back */
31-
32-
/* gettoekn: return next token */
33-
int gettoken(void)
34-
{
35-
int c, getch(void);
36-
void ungetch(int);
37-
char *p = token;
38-
39-
SKIP_BLANKS(c);
40-
41-
if (c == '(') {
42-
SKIP_BLANKS(c); /* allow spaces in parens */
43-
if (c == ')') {
44-
strcpy(token, "()");
45-
return tokentype = PARENS;
46-
} else {
47-
ungetch(c);
48-
return tokentype = '(';
49-
}
50-
} else if (c == '[') {
51-
for (*p++ = c; (*p = getch()) != ']'; p++)
52-
if (*p == '\n') /* error check: missing ']' */
53-
return *p;
54-
*++p = '\0';
55-
return tokentype = BRACKETS;
56-
} else if (isalpha(c)) {
57-
for (*p++ = c; isalnum(c = getch()); p++)
58-
*p = c;
59-
*p = '\0';
60-
ungetch(c);
61-
return tokentype = NAME;
62-
} else
63-
return tokentype = c;
64-
}
24+
int buf[BUFSIZE]; /* buffer from ungetch */
25+
int bufp = 0; /* next free position in buf */
26+
int tokentype; /* type of last token */
27+
char token[MAXTOKEN]; /* last token string */
28+
char name[MAXTOKEN]; /* identifier name */
29+
char datatype[MAXTOKEN]; /* data type = char, int, etc. */
30+
char out[MAXLEN]; /* composed output string */
31+
char state; /* flag to propagate the current state of parsing */
6532

6633
/* getch: get a (possibly pushed back) character */
6734
int getch(void)
6835
{
69-
return (bufp > 0) ? buf[--bufp] : (pushedEOF) ? EOF : getchar();
36+
return (bufp > 0) ? buf[--bufp] : getchar();
7037
}
7138

7239
/* ungerch: push character back on input */
7340
void ungetch(int c)
7441
{
75-
if (c == EOF) {
76-
pushedEOF = 1;
77-
return;
78-
}
79-
8042
if (bufp >= BUFSIZE)
8143
printf("ungetch: too many characters\n");
8244
else
8345
buf[bufp++] = c;
8446
}
8547

48+
/* needsParens: check if the next token is a parenthesis or a bracket */
49+
int needsParens()
50+
{
51+
void ungettokken(int);
52+
int nextType;
53+
54+
nextType = gettoken(); /* peek ahead */
55+
state = FAIL; /* signal token push back */
56+
return nextType == PARENS || nextType == BRACKETS;
57+
}
58+
8659
/* undcl: convert word descriptions to declarations */
8760
void undcl(void)
8861
{
89-
int type, is_dcl, error;
90-
char temp[1100]; /* increased size to avoid potential overflow */
62+
int type;
63+
char temp[MAXTOKEN];
9164

92-
is_dcl = error = 0;
93-
strcpy(out, token);
94-
while ((type = gettoken()) != '\n') {
95-
if (type == PARENS || type == BRACKETS) {
96-
if (is_dcl) { /* check if previous token is the start of dcl */
97-
sprintf(temp, "(%s)", out);
98-
strcpy(out, temp);
99-
is_dcl = 0;
100-
}
65+
while ((type = gettoken()) != '\n')
66+
if (type == PARENS || type == BRACKETS)
10167
strcat(out, token);
102-
} else if (type == '*') {
103-
sprintf(temp, "*%s", out);
68+
else if (type == '*') {
69+
sprintf(temp, needsParens() ? "(*%s)" : "*%s", out);
10470
strcpy(out, temp);
105-
is_dcl = 1;
10671
} else if (type == NAME) {
10772
sprintf(temp, "%s %s", token, out);
10873
strcpy(out, temp);
109-
} else {
74+
} else
11075
printf("invalid input at %s\n", token);
111-
error = 1;
76+
}
77+
78+
/* gettoken: return next token */
79+
int gettoken(void)
80+
{
81+
int c, getch(void);
82+
void ungetch(int);
83+
char *p = token;
84+
85+
if (state == FAIL) {
86+
state = GOOD;
87+
return tokentype; /* push back the previous token */
88+
}
89+
while ((c = getch()) == ' ' || c == '\t')
90+
;
91+
if (c == '(') {
92+
if ((c = getch()) == ')') {
93+
strcpy(token, "()");
94+
return tokentype = PARENS;
11295
}
96+
ungetch(c);
97+
return tokentype = '(';
98+
}
99+
if (c == '[') {
100+
for (*p++ = c; (*p++ = getch()) != ']'; )
101+
;
102+
*p = '\0';
103+
return tokentype = BRACKETS;
113104
}
114-
if (!error)
115-
printf("%s\n", out);
105+
if (isalpha(c)) {
106+
for (*p++ = c; isalnum(c = getch()); )
107+
*p++ = c;
108+
*p = '\0';
109+
ungetch(c);
110+
return tokentype = NAME;
111+
}
112+
return tokentype = c;
116113
}
117114

118-
int main(void)
115+
int main(void)
119116
{
120-
while (gettoken() != EOF)
121-
if (tokentype != '\n') /* skip empty input lines */
122-
undcl();
117+
while (gettoken() != EOF) { /* first token on line */
118+
if (tokentype == '\n') /* skip empty input lines */
119+
continue;
120+
strcpy(out, token); /* is the datatype */
121+
undcl();
122+
printf("%s\n", out);
123+
}
123124
return 0;
124125
}

0 commit comments

Comments
 (0)