|
1 | 1 | /*
|
2 | 2 | * Exercise 5-19. Modify undcl so that it does not add redundant parentheses to
|
3 | 3 | * declaration.
|
| 4 | + * |
4 | 5 | * By Faisal Saadatmand
|
5 |
| - * */ |
| 6 | + */ |
6 | 7 |
|
| 8 | +#include <ctype.h> |
7 | 9 | #include <stdio.h>
|
8 | 10 | #include <string.h>
|
9 |
| -#include <ctype.h> |
10 |
| - |
11 |
| -#define MAXTOKEN 100 |
12 |
| -#define BUFSIZE 100 |
13 | 11 |
|
14 |
| -#define SKIP_BLANKS(c) while (((c) = getch()) == ' ' || (c) == '\t') |
| 12 | +#define BUFSIZE 100 |
| 13 | +#define MAXLEN 1000 |
| 14 | +#define MAXTOKEN 100 |
15 | 15 |
|
16 | 16 | enum { NAME, PARENS, BRACKETS };
|
| 17 | +enum { GOOD, FAIL }; |
17 | 18 |
|
18 | 19 | /* functions */
|
19 |
| -int gettoken(void); |
20 |
| -int getch(void); |
21 |
| -void ungetch(int); |
| 20 | +void undcl(void); |
| 21 | +int gettoken(); |
22 | 22 |
|
23 | 23 | /* 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 */ |
65 | 32 |
|
66 | 33 | /* getch: get a (possibly pushed back) character */
|
67 | 34 | int getch(void)
|
68 | 35 | {
|
69 |
| - return (bufp > 0) ? buf[--bufp] : (pushedEOF) ? EOF : getchar(); |
| 36 | + return (bufp > 0) ? buf[--bufp] : getchar(); |
70 | 37 | }
|
71 | 38 |
|
72 | 39 | /* ungerch: push character back on input */
|
73 | 40 | void ungetch(int c)
|
74 | 41 | {
|
75 |
| - if (c == EOF) { |
76 |
| - pushedEOF = 1; |
77 |
| - return; |
78 |
| - } |
79 |
| - |
80 | 42 | if (bufp >= BUFSIZE)
|
81 | 43 | printf("ungetch: too many characters\n");
|
82 | 44 | else
|
83 | 45 | buf[bufp++] = c;
|
84 | 46 | }
|
85 | 47 |
|
| 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 | + |
86 | 59 | /* undcl: convert word descriptions to declarations */
|
87 | 60 | void undcl(void)
|
88 | 61 | {
|
89 |
| - int type, is_dcl, error; |
90 |
| - char temp[1100]; /* increased size to avoid potential overflow */ |
| 62 | + int type; |
| 63 | + char temp[MAXTOKEN]; |
91 | 64 |
|
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) |
101 | 67 | strcat(out, token);
|
102 |
| - } else if (type == '*') { |
103 |
| - sprintf(temp, "*%s", out); |
| 68 | + else if (type == '*') { |
| 69 | + sprintf(temp, needsParens() ? "(*%s)" : "*%s", out); |
104 | 70 | strcpy(out, temp);
|
105 |
| - is_dcl = 1; |
106 | 71 | } else if (type == NAME) {
|
107 | 72 | sprintf(temp, "%s %s", token, out);
|
108 | 73 | strcpy(out, temp);
|
109 |
| - } else { |
| 74 | + } else |
110 | 75 | 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; |
112 | 95 | }
|
| 96 | + ungetch(c); |
| 97 | + return tokentype = '('; |
| 98 | + } |
| 99 | + if (c == '[') { |
| 100 | + for (*p++ = c; (*p++ = getch()) != ']'; ) |
| 101 | + ; |
| 102 | + *p = '\0'; |
| 103 | + return tokentype = BRACKETS; |
113 | 104 | }
|
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; |
116 | 113 | }
|
117 | 114 |
|
118 |
| -int main(void) |
| 115 | +int main(void) |
119 | 116 | {
|
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 | + } |
123 | 124 | return 0;
|
124 | 125 | }
|
0 commit comments