Exercise 5.19 - undcl does not add redundant parentheses

Question

Modify undcl so that it does not add redundant parentheses to declarations.

/* Modify undcl so that it does not add redundant parenthesiss to declarations */

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

#define MAXTOKEN 100

enum {
    NAME, PARENS, BRACKETS
};

void dcl(void);

void dirdcl(void);


int gettoken(void);

int nexttoken(void);

int tokentype;
char token[MAXTOKEN];    /* last token string */
char out[1000];

/* undcl: convert word description to declaration */

int main(void) {
    int type;
    char temp[MAXTOKEN];

    while (gettoken() != EOF) {
        strcpy(out, token);

        while ((type = gettoken()) != '\n')
            if (type == PARENS || type == BRACKETS)
                strcat(out, token);
            else if (type == '*') {
                if ((type = nexttoken()) == PARENS || type == BRACKETS)
                    sprintf(temp, "(*%s)", out);
                else
                    sprintf(temp, "*%s", out);
                strcpy(out, temp);
            } else if (type == NAME) {
                sprintf(temp, " %s %s", token, out);
                strcpy(out, temp);
            } else
                printf("invalid input at %s \n", token);
        printf("%s\n", out);
    }
    return 0;
}

enum {
    NO, YES
};

int gettoken(void);

/* nexttoken: get the next token and push it back */
int nexttoken(void) {
    int type;
    extern int prevtoken;

    type = gettoken();
    prevtoken = YES;
    return type;
}

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


extern int tokentype;    /* type of last token */
extern char token[];    /* last token string */
int prevtoken = NO;    /* there is no previous token */

int gettoken(void)    /* return next token */
{
    int c, getch(void);
    void ungetch(int);
    char *p = token;

    if (prevtoken == YES) {
        prevtoken = NO;
        return tokentype;
    }

    while ((c = getch()) == ' ' || c == '\t');

    if (c == '(') {
        if ((c = getch()) == ')') {
            strcpy(token, "()");
            return tokentype = PARENS;
        } else {
            ungetch(c);
            return tokentype = '(';
        }
    } else if (c == '[') {
        for (*p++ = c; (*p++ = getch()) != ']';);
        *p = '\0';
        return tokentype = BRACKETS;
    } else if (isalpha(c)) {
        for (*p++ = c; isalnum(c = getch());)
            *p++ = c;
        *p = '\0';
        ungetch(c);
        return tokentype = NAME;
    } else
        return tokentype = c;
}

#define BUFSIZE 100
char buf[BUFSIZE];    /* buffer for ungetch */
int bufp = 0;

int getch(void)        /* get a(possibly pushed back) character */
{
    return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) {
    if (bufp >= BUFSIZE)
        printf("ungetch: too many characters \n");
    else
        buf[bufp++] = c;
}
    

Explanation

The book provides this undcl implementation

/* undcl:  convert word descriptions to declarations */
main() {
  int type;
  char temp[MAXTOKEN];
  while (gettoken() != EOF) {
    strcpy(out, token);
    while ((type = gettoken()) != '\n')
  }
  if (type == PARENS || type == BRACKETS)
    strcat(out, token);
  else if (type == '*') {
    sprintf(temp, "(*%s)", out);
    strcpy(out, temp);
  } else if (type == NAME) {
    sprintf(temp, "%s %s", token, out);
    strcpy(out, temp);
  } else
    printf("invalid input at %s\n", token);
}

The important change in our implementation from the book program is, if the nexttoken is a PARENS or BRACKETS then we print them out.

   if (type == PARENS || type == BRACKETS)
     strcat(out, token);
   else if (type == '*') {
+                if ((type = nexttoken()) == PARENS || type == BRACKETS)
     sprintf(temp, "(*%s)", out);
+                else
+                    sprintf(temp, "*%s", out);
     strcpy(out, temp);
   } else if (type == NAME) {