0

我正在尝试使用 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($$);}

但我不知道为什么?

4

1 回答 1

2

通过return FINAL<<EOF>>规则中使用,标记器将继续FINAL在文件结束时返回。当与您flex结合使用时,bison您不必(也不应该)使用显式的文件结束标记。只需依赖将在yylex文件结束时返回的 0,只要yywrap返回 1。这yyterminate也对您有用,这就是为什么它可以正常工作的原因。

在这种情况下,语法面临着FINAL它无法处理的无穷无尽的标记流。当然,您不应该在语法中容纳这种无穷无尽的流,因为语法将是“正确的”,但永远不会终止。

我假设您知道您的标记器将匹配单个CONTENT标记中的完整文件,因此即使您的语法支持CONTENT标记列表,它也总是只能看到一个。

PS:我通过使用向解析器添加调试跟踪的-t选项发现了问题bison,它表明它在第二次出现FINAL.

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

P.S3:正如您已经定义了自己的那样yywrapmain您可能会丢失-ll.

于 2013-03-25T22:06:25.427 回答