Exercise 5.18 - recover from input errors

Question

Make dcl recover from input errors.

/* Make dcl recover from input errors */

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

enum { NAME,PARENS,BRACKETS };
enum { NO, YES };

void dcl(void);
void dirdcl(void);
void errmsg(char *);

int gettoken(void);
extern int tokentype;   /* type of last token */
extern char token[];    /* last token string */
extern char name[]; /* identifier name */
extern char out[];
extern int prevtoken;


/* dcl: parse a declarator  */
void dcl(void)
{
    int ns;
    
    for(ns = 0; gettoken() == '*';)     /* count *'s    */
        ns++;
    
    dirdcl();

    while(ns-- > 0)
            strcat(out,"pointer to");
}


/* dirdcl: parse a direct declaration */
void dirdcl(void)
{
    int type;
    
    if(tokentype == '(' )
    {
        dcl();

        if(tokentype != ')')
            errmsg("error: missing ) \n");
    }
    else if ( tokentype == NAME)
        strcpy(name,token);
    else
        errmsg("error: expected name or (dcl) \n");

    while((type = gettoken()) == PARENS || type == BRACKETS)
        if(type == PARENS)
            strcat(out,"function returning");
        else
        {
            strcat(out,"array");
            strcat(out,token);
            strcat(out,"of");
        }
}

/* errmsg:  print error message and indicate avail. token */

void errmsg(char *msg)
{
    printf("%s",msg);
    prevtoken = YES;
}

/* The Source file gettoken.c */

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

/*  enum { NAME,PARENS,BRACKETS}; */
/*  enum { NO,YES };        */

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

/* gettoken : return next token */

int gettoken(void)
{
    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;           /* next free position in buf    */

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