【问题标题】:Cannot find cause of 'syntax error' message in Bison在 Bison 中找不到“语法错误”消息的原因
【发布时间】:2015-07-24 13:55:33
【问题描述】:

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

%{
#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] = '\0';
                                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", $1); }
                | END_OF_FILE {printf("Encountered EOF\n");}
                ;
exp:   NUMBER                  { $$ = $1;}
     | exp PLUS exp          { $$ = $1 + $3; }
     | exp TIMES exp          { $$ = $1 * $3; }
     | '(' exp ')'          { $$ = $2;}
     ;

%%

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;
}

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

【问题讨论】:

  • 在解析器中,'(' exp ')':用LEFT_PARENTHESISRIGHT_PARENTHESIS 替换(和)。添加令牌DIVIDE 并为它和MINUS 添加规则。我没有看到其他错误。 - 使用调试器单步执行它以查看引发错误的位置。
  • 谢谢,我已经更正了,但没有成功。尝试其他方式。

标签: c compiler-construction bison yacc lex


【解决方案1】:

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

另一个问题是您在输入末尾返回标记 END_OF_FILE,而不是 0——bison 期望 EOF 标记为 0,如果没有,则会给出语法错误在输入的末尾看到一个。

解决这两个问题的最简单方法是去掉 END_OF_FILE 标记并让 &lt;&lt;EOF&gt;&gt; 规则返回 0。然后你的语法变成:

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

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

【讨论】:

    【解决方案2】:

    代码存在一些问题。

    首先,您的词法分析器应该包含以下内容:

    %{
    #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");
    

    【讨论】:

    • 我已经更正了所有这些但没有成功(除了 munged 行,这是因为复制粘贴错误)。现在我已经成功地制作了一个非常简单的示例,我将尝试以此为基础逐步重新构建我的文件。如果我最终得到一个解决方案,我会告诉你解决方案。
    • extern int yylval; 是多余的——它将出现在 bison 生成的 parser.tab.h 文件中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    • 2021-08-14
    • 2016-02-11
    • 2020-09-24
    • 1970-01-01
    • 1970-01-01
    • 2014-09-10
    相关资源
    最近更新 更多