在 Bison 中找不到 'syntax error' 消息的原因

Cannot find cause of 'syntax error' message in Bison

我正在尝试创建一个简单的 parser/compiler,主要用于家庭作业,但最终也用于学习和娱乐。我已经编写了词法分析器和解析器文件(用于命令的初始子集)并且我想输出一个 AST。但是,即使我试图解析一个简单的“1+1”,我仍然卡在 "syntax error" 消息中。这是词法分析器文件:

%{
#include "parser.tab.h"
%}

DIGIT   [0-9]
LETTER   [a-zA-Z]


%%
[ \t\n]               ;

{DIGIT}+        {yylval = atoi(yytext); return NUMBER;}

{LETTER}*       {       if (strlen(yytext) <= 8){
                                printf( "<ID, %s> ", yytext );
                        } else {
                                yytext[8] = '[=11=]';
                                printf("WARNING! Long identifier. Truncating to 8 chars\n");
                                printf( "<ID, %s> ", yytext );
                        }
                }

"+"      {printf("Found '+' symbol\n");return(PLUS);}
"-"      return(MINUS);
"*"      return(TIMES);
"/"      return(DIVIDE);
"("      return(LEFT_PARENTHESIS);
")"      return(RIGHT_PARENTHESIS);
<<EOF>>  return(END_OF_FILE);

%%
int yywrap (void) {return 1;}

这是解析器文件:

%{
#include <stdio.h>
/*#include "tree.h"
#include "treedefs.h"*/
int yylex();
#define YYSTYPE int
%}

%start program

%token  NUMBER
%token  ID
%token  PLUS    MINUS   TIMES   EQUAL
%token  LEFT_PARENTHESIS        RIGHT_PARENTHESIS

%token  LET     IN      AND
%token  END_OF_FILE

%left   PLUS    MINUS
%left   TIMES   DIVIDE
%%

program:        /* empty */
                | exp   { printf("Result: %d\n", ); }
                | END_OF_FILE {printf("Encountered EOF\n");}
                ;
exp:   NUMBER                  { $$ = ;}
     | exp PLUS exp          { $$ =  + ; }
     | exp TIMES exp          { $$ =  * ; }
     | '(' exp ')'          { $$ = ;}
     ;

%%

int yyerror (char *s) {fprintf (stderr, "%s\n", s);
}

此外,我创建了一个 main.c,以单独保留 main() 函数。您可以省略 tree*.h 文件,因为它们只包含与 AST 相关的函数。

#include <stdio.h>
#include <stdlib.h>
#include "tree.h"
#include "treedefs.h"

int main(int argc, char **argv){
        yyparse();
        TREE *RootNode = malloc(sizeof(TREE));
        return 0;
}

我已经阅读了大量的例子,但我找不到与我写的有什么(非常)不同的地方。我究竟做错了什么?任何帮助,将不胜感激。

代码有一些问题。

首先,你的词法分析器应该包括:

%{
#include "parser.tab.h"
extern int yylval;     // this line was missing
%}

其次,假设您希望代码在语句末尾进行计算,您必须在语句末尾包含一个规则。也就是说,假设它是面向行的,您将用这些替换当前的空白规则:

[ \t]           {}
[\n]            { return 0; }

第三,你的其中一句台词被篡改了。而不是这个:

printf("WARNING! Long identifier. Truncating to 8 chars\n"$

应该是这样的:

printf("WARNING! Long identifier. Truncating to 8 chars\n");

您的语法接受表达式或文件结尾。所以如果你给它一个表达式后跟一个文件结尾,你会得到一个错误。

另一个问题是您 return 输入末尾的标记 END_OF_FILE,而不是 0 -- bison 期望 EOF 为 0令牌,如果在输入末尾没有看到令牌,将给出语法错误。

最简单的解决方法是去掉 END_OF_FILE 标记并让 <<EOF>> 规则 return 0。然后你的语法变成:

program:        /* empty */ { printf("Empty input\n"); }
                | exp   { printf("Result: %d\n", ); }
                ;
       ...rest of the grammar

现在您遇到了(潜在的)问题,即您的语法只接受单个表达式。您可能希望支持由换行符或其他一些分隔符分隔的多个表达式
(也许是;?),这可以通过多种方式完成。