正如我在标题中所述,我正在尝试使用flex和bison编写解析器。但是,无论我如何修改文件,都会出现错误“第1行中的语法错误”。
所以我决定写一个非常简单的例子,看看我的方法是否正确。
这是简单的文件“c1.isc”,将被读取:
1 nand
2 nor
3 nand
4 nor
5 xor
这是token.l文件:
%{
# include <stdio.h>
# include <string.h>
# include "parse.tab.h"
struct{
char *symbol;
int val;
} symtab[]={
"nand", 1,
"nor", 2,
"xor", 3,
"0",0
};
extern int yylval;
%}
DIGITS [0-9]+
BLANK [ \t\n]+
ALPHA [a-z]+
%%
{DIGITS} {yylval=atoi(yytext);return(NUM);}
{ALPHA} {yylval=lookup(yytext);return(TYPE);}
{BLANK} ;
%%
lookup(s)
char* s;
{int i;
for (i=0;symtab[i].val!=0;i++)
{
if(strcmp(symtab[i].symbol,s)==0)
break;
}
return(symtab[i].val);
}
这是parse.y文件
%{
# include <stdio.h>
extern FILE *yyin;
int gi;
%}
%token NUM TYPE
%%
parto: NUM
{gi=$1;printf("num=%d\t",gi);}
TYPE
{gi=$3;printf("type=%d\n",gi);}
;
%%
yyerror(s)
char *s;
{
extern int yylineno;
extern char yytext[];
fprintf(stderr, "%s in line %d near <%s>\n", s, yylineno, yytext);
exit(-1);
}
main()
{FILE *x=fopen("c1.isc","r");
yyin=x;
yyparse();
}
我认为这几乎是最简单的例子,但是,解析器只输出第一行为“num = 1 gat = 1”,然后是“第1行附近的语法错误”。
我真的不知道为什么。我确定令牌文件是正确的,因为我已经使用以下方式测试它:
%{
# include <stdio.h>
# include <string.h>
struct{
char *symbol;
int val;
} symtab[]={
"nand", 1,
"nor", 2,
"xor", 3,
"0",0
};
int val;
%}
DIGITS [0-9]+
BLANK [ \t\n]+
ALPHA [a-z]+
%%
{DIGITS} {val=atoi(yytext);printf("num=%d\t",val);}
{ALPHA} {val=lookup(yytext);printf("type=%d\n",val);}
{BLANK} ;
%%
lookup(s)
char* s;
{int i;
for (i=0;symtab[i].val!=0;i++)
{
if(strcmp(symtab[i].symbol,s)==0)
break;
}
return(symtab[i].val);
}
main()
{
FILE *x=fopen("c1.isc","r");
yyin=x;
yylex();
}
yylex()可以工作。
我的编译方式是 1. flex token.l 2. bison -d parse.y 3. cc lex.yy.c parse.tab.c -lfl
然后我会得到a.out
,当我运行a.out
时,会出现错误。
我想那是因为我在parse.y文件中的规则不对,但错误总是出现在第一行?
我使用了以下规则来使其发挥作用。
parti:
| parti parto
;
parto: NUM
{gi=$1;printf("num=%d\t",gi);}
TYPE
{gi=$3;printf("type=%d\n",gi);}
;
答案 0 :(得分:1)
也许我在这里遗漏了一些东西,但你的语法只说输入应该是一个NUM和一个TYPE。就这样。因此,当解析器找到更多内容时,输入的第二行会出现错误。
您必须添加处理多行的规则。像这样:
lots_of_partos: parto lots_of_partos | /* empty */ ;