繁体   English   中英

K&R递归下降解析器错误

[英]K&R recursive descent parser error

我正在研究K&R第5章。

该书刚刚介绍了递归下降解析器,以说明在C中发现的一些“复杂声明”。但是,该程序始终报告语法错误。

例如,如果我按如下所示运行程序,然后输入int a; 然后按回车键,我收到以下输出:

$ ./dcl
int a;
syntax error
a:  int

我也尝试过使用一个int和空的main函数重定向文件,但是收到相同的错误,因此不要认为这是一个'\\ n'问题。

下一个练习5-18要求读者“使dc1从输入错误中恢复”,但是我不认为我可以正常工作。 随后,我从本书的PDF复制并粘贴了代码,因此认为它反映了所印刷的内容。

有关诊断和解决方案的建议深表感谢。

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

#define MAXTOKEN 100
#define BUFSIZE 100

enum { NAME, PARENS, BRACKETS };

void dcl(void);
void dirdcl(void);

int bufp = 0; /* next free position in buf */
int gettoken(void);
int tokentype;           /* type of last token */
char token[MAXTOKEN];    /* last token string */
char name[MAXTOKEN];     /* identifier name */
char datatype[MAXTOKEN]; /* data type = char, int, etc. */
char out[1000];
char buf[BUFSIZE]; /* buffer for ungetch */


int main() /* convert declaration to words */
{
     while (gettoken() != EOF) { /* 1st token on line */
      strcpy(datatype, token); /* is the datatype */
      out[0] = '\0';
      dcl(); /* parse rest of line */
      if (tokentype != '\n')
           printf("syntax error\n");
      printf("%s: %s %s\n", name, out, datatype);
     }
     return 0;
}

/* 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 declarator */
void dirdcl(void)
{
     int type;
     if (tokentype == '(') {
      dcl(); /* ( dcl ) */
      if (tokentype != ')')
           printf("error: missing )\n");
     } else if (tokentype == NAME) /* variable name */
      strcpy(name, token);
     else
      printf("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");
      }
}

/* return next token */
int gettoken(void)
{
     int c, getch(void);
     void ungetch(int);
     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 = '\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;
}


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

/* push character back on input */
void ungetch(int c) 
{
     if (bufp >= BUFSIZE)
      printf("ungetch: too many characters\n");
     else
      buf[bufp++] = c;
}

乔纳森·莱弗勒(Jonathan Leffler)是正确的,该代码只是按照书中代码之前所概述的那样解析声明语法,而不是像在代码中那样在语法上正确的声明。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM