Программа K

#c #recursive-descent

Вопрос:

Я застрял с программой dcl из главы 5.12 в Kamp;R C. Это в основном программа, которая принимает объявление переменной/функции/таблицы C и печатает ее описание на английском языке. Он работает для простых объявлений, таких как int a , но не работает с более сложными. Например, когда я ввожу int (*pf)() , я получаю вывод

 error: expected name or (dcl)
Syntax error
:  int
error: expected name or (dcl)
:  function that returns pf
 

Ниже приведена часть кода, относящаяся к программе. Функции getch() и ungetch() находятся в отдельном файле.

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

#define MAXTOKEN 100

enum { NAME, PARENS, BRACKETS };

void dcl(void);
void dirdcl(void);
int gettoken(void);

int tokentype;
char token[MAXTOKEN];
char name[MAXTOKEN];
char datatype[MAXTOKEN];
char out[1000];

int main(void)
{
    while (gettoken() != EOF) {
        strcpy(datatype, token);
        out[0] = '';
        dcl();
        if (tokentype != 'n')
            printf("Syntax errorn");
        printf("%s: %s %sn", name, out, datatype);
    }

    return 0;
}

void dcl(void)
{
    int ns;
    
    for (ns = 0; gettoken() == '*'; )
        ns  ;
    dirdcl();
    while (ns-- > 0)
        strcat(out, " pointer to");
}

void dirdcl(void)
{
    int type;

    if (tokentype == '(') {
        dcl();
        if (tokentype != ')')
            printf("error: missing )n");
    } else if (tokentype == NAME)
        strcpy(name, token);
    else
        printf("error: expected name or (dcl)n");
    while ((type=gettoken()) == PARENS || type == BRACKETS) {
        if (type == PARENS)
            strcat(out, " function that returns");
        else {
            strcat(out, " array");
            strcat(out, token);
            strcat(out, " of");
        }
    }
}

int gettoken(void)
{
    int c;
    char *p = token;

    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 = '';
        return tokentype = BRACKETS;
    } else if (isalpha(c)) {
        for (*p   = c; isalnum(c = getch()); )
            *p   = c;
        *p = '';
        ungetch(c);
        return tokentype = NAME;
    } else
        return tokentype = c;
}
 

Не могли бы вы, пожалуйста, помочь мне точно определить ошибку?

Комментарии:

1. Вы забыли задать вопрос, но если вам интересно, что не так с программой, то строка return tokentype = ')'; gettoken() выглядит неправильно. Скорее всего , так и должно быть return tokentype = '('; . Могут быть и другие проблемы.

2. По запросу была выявлена ошибка: return tokentype = ')📍'; .

3. @Джон Боллинджер, спасибо тебе. Я добавил вопрос и с самого начала нашел эту часть подозрительной. В греческой версии книги множество ошибок.

Ответ №1:

На p124 Брайан и Деннис говорят: «Поскольку программы предназначены для иллюстрации, а не для защиты от пуль, существуют значительные ограничения» dcl .

Последнее предложение в этом абзаце содержит эту версию окончательного решения автора: «Эти улучшения оставлены в качестве упражнений».

Это может быть хорошее время, чтобы стряхнуть пыль с yacc.