如何修复“line:1:error:syntax error!”

时间:2013-03-25 08:37:59

标签: bison yacc lex flex-lexer

我正在尝试使用flex和bison编写解析器。但是,无论我如何修改文件,总是会出现错误“第1行中的语法错误”。 这是yyinput的test.vm文件:

$asfdfsdf
sdfsdfs
sdfsdfsd
sdfsdfsd
sfsdfd

这是vtl4.l文件:

%{
#include<stdio.h>
#include<string.h>
#include "context.h"
#include "bool.h"
#include "vtl4.tab.h"
%}
%%
(.|\n)* {yylval.string = yytext;return CONTENT;}
<<EOF>> {return FINAL;}
%%

这是vtl4.y文件:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bool.h"
#include "parser.h"
#include "context.h"
#include "vtl4.tab.h"

extern FILE * yyin;
extern FILE * yyout;
extern int yylex();
extern int yywrap();
%}

%union {
struct simpleNode *ast;
double d;
int i;
bool b;
char* string;
struct symbol *sym;
}

%type <ast> root stmts stmt

%token <string> CONTENT

%token FINAL

%%

root:stmts FINAL {printf("root\n");$$ = process($1);traverse($$);}
;

stmts: {printf("stmts:stmt\n");$$ = 0;}
|stmts stmt {printf("stmts:stmts stmt\n");$$ = add_ybrother($1,$2);}
;

stmt:CONTENT {printf("stmt\n");$$ = text($1);}
;

%%
int main(){
FILE *src;
src = fopen("test.vm","r");
yyin = src;
yyparse();
fclose(src);
return 1;
}

int yywrap(){
return 1;
}

生成文件:

CC=cc

FLEX=vtl4.l

BISON=vtl4.y

parse:vtl4.tab.c lex.yy.c
       $(CC) -o out *.c -ll


vtl4.tab.c:$(BISON)
      bison -d $(BISON) --report=all

lex.yy.c:$(FLEX)
        flex $(FLEX)

当我运行./out时,它会打印出正确的结果,但最后总是说“line:1:error:syntax error”!我不知道为什么?

编辑lex规则

时效果很好
<<EOF>> {return FINAL;}

<<EOF>> {yyterminate();}

并修改yacc规则

root:stmts FINAL {printf("root\n");$$ = process($1);traverse($$);}

root:stmts {printf("root\n");$$ = process($1);traverse($$);}

但我不知道为什么?

1 个答案:

答案 0 :(得分:2)

通过使用return FINAL规则中的<<EOF>>,标记生成器将继续在文件结尾返回FINAL。当flexbison结合使用时,您不必(也不应该)使用显式的文件结束标记。只需依靠yylex在文件结尾处返回的0,前提是yywrap返回1.这正是yyterminate为你所做的,这就是为什么这样做的原因细

在这种情况下,语法面临着无法处理的FINAL令牌的源源不断。当然,你不应该在你的语法中容纳这种无休止的流,因为语法将是“正确的”但永远不会终止。

我假设您知道您的tokenizer将匹配单个CONTENT令牌中的完整文件,因此即使您的语法支持CONTENT令牌列表,它也始终只能看到一个。

PS:我通过使用-t bison选项找到了问题,它将调试跟踪添加到解析器中,并显示它在第二次出现FINAL时被阻塞。 / p>

P.S2:Makefile*.c的编译器调用中使用parse。这非常危险,因为一些随机.c文件可能会在您的目录中挂起。最好使用$^来引用规则所依赖的所有文件。

P.S3:由于您已经定义了自己的yywrapmain,因此可能会失去-ll

相关问题