无法找到'语法错误的原因'在野牛的消息

时间:2015-07-24 13:55:34

标签: c compiler-construction bison yacc lex

我试图创建一个简单的解析器/编译器,主要用于家庭作业,但最终用于学习目的和乐趣。我已经写了词法分析器和解析器文件(对于命令的初始子集),我想输出一个AST。但是,我遇到了#34;语法错误"消息,即使我试图解析一个简单的&1; 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()函数。您可以省略树* .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;
}

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

2 个答案:

答案 0 :(得分: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");

答案 1 :(得分:0)

您的语法接受表达式或文件结尾。因此,如果您给它一个表达式后跟一个文件结尾,则会出现错误。

另一个问题是你在输入的末尾返回了令牌END_OF_FILE,而不是0 - 野牛期待EOF令牌的0并且会给出一个语法错误,如果它没有在输入的末尾看到一个。

对这两者最简单的解决方法是删除END_OF_FILE令牌并让<<EOF>>规则返回0.然后你的语法变为:

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

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