野牛只读一行
bison only reads one line
我正在用 flex 和 bison 做一个简单的计算器,但它只读取输入文件的第一行。
这是我的野牛代码:
%{
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "symtab.h"
extern int yylex(void);
extern char *yytext;
extern int num_linea;
extern FILE *yyin;
void yyerror(char *s);
%}
%union{
struct{
char *lexema;
int lenght;
int line;
}ident;
}
%union{
struct{
int integer;
float real;
char *string;
int type;
}num;
}
%union{
int num_int;
}
%union{
float num_float;
}
%token <ident> IDENT
%token <num> LIT_INT
%token <num> LIT_FLOAT
%token <num> CADENA
%token PARENTESIS1
%token PARENTESIS2
%token OP_SUM
%token OP_REST
%token OP_MULT
%token OP_DIV
%token OP_MOD
%token OP_POW
%token ASSIGN
%token NX_LINE
%token INVALID_TOKEN
%type <num> expr
%type <num> term
%type <num> factor
%type <num> primary
%type <num> linea
%%
linea : IDENT ASSIGN expr NX_LINE {/*sym_enter(.lexema,(void *)&)*/;}
| OP_SUM expr NX_LINE {if(.type==0) {
printf("El valor es %d. \n", .integer);
} else if(.type==1) {
printf("El valor es %f. \n", .real);
}}
| OP_REST expr NX_LINE {if(.type==0) {
printf("El valor es %d. \n", -.integer);
} else if(.type==1) {
printf("El valor es %f. \n", -.real);
}}
| expr NX_LINE {if(.type==0) {
printf("El valor es entero y es %d. \n", .integer);
} else if(.type==1) {
printf("El valor es un float y es %f. \n", .real);
} else if(.type==2) {
printf("El valor es un string y es %s. \n", .string);
}}
;
expr : expr OP_SUM term {if(.type==0 && .type==0) {
$$.type=0;
$$.integer=.integer+.integer;
} else if(.type==1 && .type==1) {
$$.type=1;
$$.real=.real+.real;
} else if(.type==0 && .type==1) {
$$.type=1;
$$.real=.integer+.real;
} else if(.type==1 && .type==0) {
$$.type=1;
$$.real=.real+.integer;
}else if(.type==0 && .type==2) {
$$.type=2;
$$.string=malloc(sizeof(.string)+sizeof(.integer));
sprintf($$.string,"%d%s",.integer,.string);
} else if(.type==1 && .type==2) {
$$.type=2;
$$.string=malloc(sizeof(.string)+sizeof(.real));
sprintf($$.string,"%f%s",.real,.string);
}else if(.type==0 && .type==2) {
$$.type=2;
$$.string=malloc(sizeof(.string)+sizeof(.integer));
sprintf($$.string,"%s%d",.string,.integer);
} else if(.type==1 && .type==2) {
$$.type=2;
$$.string=malloc(sizeof(.real)+sizeof(.string));
sprintf($$.string,"%s%f",.string,.real);
}}
| expr OP_REST term {if(.type==0 && .type==0) {
$$.type=0;
$$.integer=.integer-.integer;
} else if(.type==1 && .type==1) {
$$.type=1;
$$.real=.real-.real;
} else if(.type==0 && .type==1) {
$$.type=1;
$$.real=.integer-.real;
} else if(.type==1 && .type==0) {
$$.type=0;
$$.real=.real-.integer;
}}
| term {$$=;}
;
term : term OP_MULT factor {if(.type==0 && .type==0) {
$$.type=0;
$$.integer=.integer*.integer;
} else if(.type==1 && .type==1) {
$$.type=1;
$$.real=.real*.real;
} else if(.type==0 && .type==1) {
$$.type=1;
$$.real=.integer*.real;
} else if(.type==1 && .type==0) {
$$.type=0;
$$.real=.real*.integer;
}}
| term OP_DIV factor {if(.type==0 && .type==0) {
$$.type=0;
$$.integer=.integer/.integer;
} else if(.type==1 && .type==1) {
$$.type=1;
$$.real=.real/.real;
} else if(.type==0 && .type==1) {
$$.type=1;
$$.real=.integer/.real;
} else if(.type==1 && .type==0) {
$$.type=0;
$$.real=.real/.integer;
}}
| term OP_MOD factor {if(.type==0 && .type==0) {
$$.type=0;
$$.integer=.integer%.integer;
} else if(.type==1 && .type==1) {
$$.type=1;
$$.real=fmod(.real,.real);
}}
| factor {$$=;}
;
factor : primary {$$=;}
| primary OP_POW factor {if(.type==0 && .type==0) {
$$.type=0;
$$.integer=pow(.integer,.integer);
} else if(.type==1 && .type==1) {
$$.type=1;
$$.real=pow(.real,.real);
}}
;
primary : PARENTESIS1 expr PARENTESIS2 {$$=;}
| PARENTESIS1 OP_REST expr PARENTESIS2 {if(.type==0) {
$$.type=0;
$$.integer=-.integer;
} else if(.type==1) {
$$.type=1;
$$.real=.real;
}}
| PARENTESIS1 OP_SUM expr PARENTESIS2 {$$=;}
| LIT_INT {$$=;}
| LIT_FLOAT {$$=;}
| CADENA {$$=;}
| IDENT {/*sym_lookup(,$$)*/;}
;
%%
void yyerror(char *s)
{
printf("Error %s",s);
}
int main(int argc,char **argv)
{
if (argc>1)
yyin=fopen(argv[1],"rt");
else
yyin=stdin;
yyparse();
printf("FIN del Analisis. Entrada CORRECTA\n");
printf("Numero lineas analizadas: %d\n", num_linea);
return 0;
}
这是我的弹性代码:
%{
#include "compilador1.tab.h"
#include <string.h>
#include <stdio.h>
#include <math.h>
int num_linea;
extern FILE *yyin;
%}
%option yylineno
%x comentario
%x comentario2
%x str
DIGIT [0-9]
ID [a-z][a-z0-9]*
%%
num_linea=1;
char string_buf[1000];
char *string_buf_ptr;
int string_cnt;
"\n" {printf("\n");num_linea++;return NX_LINE;}
"\t" {;}
" " {;}
"mod" {return OP_MOD;}
{DIGIT}+ {yylval.num.integer=atoi(yytext);yylval.num.type=0;printf("entero "); return LIT_INT;}
{DIGIT}+"."{DIGIT}* {yylval.num.real=atof(yytext);yylval.num.type=1;printf("real "); return LIT_FLOAT;}
{ID} {yylval.ident.lexema = (char *)malloc(sizeof(char)*yyleng);
strncpy(yylval.ident.lexema,yytext,yyleng);
yylval.ident.lenght = yyleng;
yylval.ident.line = yylineno;
printf("id ");
return IDENT;}
"/" {printf("div ");return OP_DIV;}
"**" {printf("pow ");return OP_POW;}
"*" {printf("mult ");return OP_MULT;}
"+" {printf("sum ");return OP_SUM;}
"-" {printf("rest ");return OP_REST;}
"(" {printf("( ");return PARENTESIS1;}
")" {printf(") ");return PARENTESIS2;}
":=" {printf("assign ");return ASSIGN;}
"/*" {BEGIN(comentario);}
<comentario>[^*\n]* /*ignora lo que no sea * */
<comentario>"*"+[^*/\n]* /*ignora los * no seguidos de / */
<comentario>\n {++num_linea;}
<comentario>"*"+"/" {BEGIN(INITIAL);}
"//" {BEGIN(comentario2);}
<comentario2>[^\n]
<comentario2>\n {BEGIN(INITIAL);}
\" string_buf_ptr = string_buf;string_cnt=0; BEGIN(str);
<str>\" { /* saw closing quote - all done */
BEGIN(INITIAL);
*string_buf_ptr = '[=11=]';
/* return string constant token type and
* value to parser
*/
yylval.num.type=2;
yylval.num.string=string_buf_ptr-string_cnt;
printf("string ");
return CADENA;
}
<str>\n {
/* error - unterminated string constant */
/* generate error message */
}
<str>\n *string_buf_ptr++ = '\n';
<str>\t *string_buf_ptr++ = '\t';
<str>\r *string_buf_ptr++ = '\r';
<str>\b *string_buf_ptr++ = '\b';
<str>\f *string_buf_ptr++ = '\f';
<str>\(.|\n) *string_buf_ptr++ = yytext[1];
<str>[^\\n\"]+ {
char *yptr = yytext;
while ( *yptr ) {
string_cnt++;
*string_buf_ptr++ = *yptr++;
}
}
. {printf("INVALID: %s", yytext); return INVALID_TOKEN;}
%%
并使用此输入:
4+5*6.4+"hello"
4+8
我得到这个输出:
entero sum entero mult real sum string
El valor es un string y es 36.000000hello.
entero Error syntax errorFIN del Analisis. Entrada CORRECTA
Numero lineas analizadas: 1
我的错误是什么?
您的语法的非终结符开头称为 "linea",这是有充分理由的:它恰好定义了一行 (una línea)。 Bison 解析器准确地识别开始非终端后跟文件结束符,因此如果您的输入包含多行,解析器将在第一行之后遇到 EOF 以外的内容时报告语法错误。
如果你想识别多行,你需要写一个匹配多行的语法:
programa : linea
| programa linea
我正在用 flex 和 bison 做一个简单的计算器,但它只读取输入文件的第一行。 这是我的野牛代码:
%{
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "symtab.h"
extern int yylex(void);
extern char *yytext;
extern int num_linea;
extern FILE *yyin;
void yyerror(char *s);
%}
%union{
struct{
char *lexema;
int lenght;
int line;
}ident;
}
%union{
struct{
int integer;
float real;
char *string;
int type;
}num;
}
%union{
int num_int;
}
%union{
float num_float;
}
%token <ident> IDENT
%token <num> LIT_INT
%token <num> LIT_FLOAT
%token <num> CADENA
%token PARENTESIS1
%token PARENTESIS2
%token OP_SUM
%token OP_REST
%token OP_MULT
%token OP_DIV
%token OP_MOD
%token OP_POW
%token ASSIGN
%token NX_LINE
%token INVALID_TOKEN
%type <num> expr
%type <num> term
%type <num> factor
%type <num> primary
%type <num> linea
%%
linea : IDENT ASSIGN expr NX_LINE {/*sym_enter(.lexema,(void *)&)*/;}
| OP_SUM expr NX_LINE {if(.type==0) {
printf("El valor es %d. \n", .integer);
} else if(.type==1) {
printf("El valor es %f. \n", .real);
}}
| OP_REST expr NX_LINE {if(.type==0) {
printf("El valor es %d. \n", -.integer);
} else if(.type==1) {
printf("El valor es %f. \n", -.real);
}}
| expr NX_LINE {if(.type==0) {
printf("El valor es entero y es %d. \n", .integer);
} else if(.type==1) {
printf("El valor es un float y es %f. \n", .real);
} else if(.type==2) {
printf("El valor es un string y es %s. \n", .string);
}}
;
expr : expr OP_SUM term {if(.type==0 && .type==0) {
$$.type=0;
$$.integer=.integer+.integer;
} else if(.type==1 && .type==1) {
$$.type=1;
$$.real=.real+.real;
} else if(.type==0 && .type==1) {
$$.type=1;
$$.real=.integer+.real;
} else if(.type==1 && .type==0) {
$$.type=1;
$$.real=.real+.integer;
}else if(.type==0 && .type==2) {
$$.type=2;
$$.string=malloc(sizeof(.string)+sizeof(.integer));
sprintf($$.string,"%d%s",.integer,.string);
} else if(.type==1 && .type==2) {
$$.type=2;
$$.string=malloc(sizeof(.string)+sizeof(.real));
sprintf($$.string,"%f%s",.real,.string);
}else if(.type==0 && .type==2) {
$$.type=2;
$$.string=malloc(sizeof(.string)+sizeof(.integer));
sprintf($$.string,"%s%d",.string,.integer);
} else if(.type==1 && .type==2) {
$$.type=2;
$$.string=malloc(sizeof(.real)+sizeof(.string));
sprintf($$.string,"%s%f",.string,.real);
}}
| expr OP_REST term {if(.type==0 && .type==0) {
$$.type=0;
$$.integer=.integer-.integer;
} else if(.type==1 && .type==1) {
$$.type=1;
$$.real=.real-.real;
} else if(.type==0 && .type==1) {
$$.type=1;
$$.real=.integer-.real;
} else if(.type==1 && .type==0) {
$$.type=0;
$$.real=.real-.integer;
}}
| term {$$=;}
;
term : term OP_MULT factor {if(.type==0 && .type==0) {
$$.type=0;
$$.integer=.integer*.integer;
} else if(.type==1 && .type==1) {
$$.type=1;
$$.real=.real*.real;
} else if(.type==0 && .type==1) {
$$.type=1;
$$.real=.integer*.real;
} else if(.type==1 && .type==0) {
$$.type=0;
$$.real=.real*.integer;
}}
| term OP_DIV factor {if(.type==0 && .type==0) {
$$.type=0;
$$.integer=.integer/.integer;
} else if(.type==1 && .type==1) {
$$.type=1;
$$.real=.real/.real;
} else if(.type==0 && .type==1) {
$$.type=1;
$$.real=.integer/.real;
} else if(.type==1 && .type==0) {
$$.type=0;
$$.real=.real/.integer;
}}
| term OP_MOD factor {if(.type==0 && .type==0) {
$$.type=0;
$$.integer=.integer%.integer;
} else if(.type==1 && .type==1) {
$$.type=1;
$$.real=fmod(.real,.real);
}}
| factor {$$=;}
;
factor : primary {$$=;}
| primary OP_POW factor {if(.type==0 && .type==0) {
$$.type=0;
$$.integer=pow(.integer,.integer);
} else if(.type==1 && .type==1) {
$$.type=1;
$$.real=pow(.real,.real);
}}
;
primary : PARENTESIS1 expr PARENTESIS2 {$$=;}
| PARENTESIS1 OP_REST expr PARENTESIS2 {if(.type==0) {
$$.type=0;
$$.integer=-.integer;
} else if(.type==1) {
$$.type=1;
$$.real=.real;
}}
| PARENTESIS1 OP_SUM expr PARENTESIS2 {$$=;}
| LIT_INT {$$=;}
| LIT_FLOAT {$$=;}
| CADENA {$$=;}
| IDENT {/*sym_lookup(,$$)*/;}
;
%%
void yyerror(char *s)
{
printf("Error %s",s);
}
int main(int argc,char **argv)
{
if (argc>1)
yyin=fopen(argv[1],"rt");
else
yyin=stdin;
yyparse();
printf("FIN del Analisis. Entrada CORRECTA\n");
printf("Numero lineas analizadas: %d\n", num_linea);
return 0;
}
这是我的弹性代码:
%{
#include "compilador1.tab.h"
#include <string.h>
#include <stdio.h>
#include <math.h>
int num_linea;
extern FILE *yyin;
%}
%option yylineno
%x comentario
%x comentario2
%x str
DIGIT [0-9]
ID [a-z][a-z0-9]*
%%
num_linea=1;
char string_buf[1000];
char *string_buf_ptr;
int string_cnt;
"\n" {printf("\n");num_linea++;return NX_LINE;}
"\t" {;}
" " {;}
"mod" {return OP_MOD;}
{DIGIT}+ {yylval.num.integer=atoi(yytext);yylval.num.type=0;printf("entero "); return LIT_INT;}
{DIGIT}+"."{DIGIT}* {yylval.num.real=atof(yytext);yylval.num.type=1;printf("real "); return LIT_FLOAT;}
{ID} {yylval.ident.lexema = (char *)malloc(sizeof(char)*yyleng);
strncpy(yylval.ident.lexema,yytext,yyleng);
yylval.ident.lenght = yyleng;
yylval.ident.line = yylineno;
printf("id ");
return IDENT;}
"/" {printf("div ");return OP_DIV;}
"**" {printf("pow ");return OP_POW;}
"*" {printf("mult ");return OP_MULT;}
"+" {printf("sum ");return OP_SUM;}
"-" {printf("rest ");return OP_REST;}
"(" {printf("( ");return PARENTESIS1;}
")" {printf(") ");return PARENTESIS2;}
":=" {printf("assign ");return ASSIGN;}
"/*" {BEGIN(comentario);}
<comentario>[^*\n]* /*ignora lo que no sea * */
<comentario>"*"+[^*/\n]* /*ignora los * no seguidos de / */
<comentario>\n {++num_linea;}
<comentario>"*"+"/" {BEGIN(INITIAL);}
"//" {BEGIN(comentario2);}
<comentario2>[^\n]
<comentario2>\n {BEGIN(INITIAL);}
\" string_buf_ptr = string_buf;string_cnt=0; BEGIN(str);
<str>\" { /* saw closing quote - all done */
BEGIN(INITIAL);
*string_buf_ptr = '[=11=]';
/* return string constant token type and
* value to parser
*/
yylval.num.type=2;
yylval.num.string=string_buf_ptr-string_cnt;
printf("string ");
return CADENA;
}
<str>\n {
/* error - unterminated string constant */
/* generate error message */
}
<str>\n *string_buf_ptr++ = '\n';
<str>\t *string_buf_ptr++ = '\t';
<str>\r *string_buf_ptr++ = '\r';
<str>\b *string_buf_ptr++ = '\b';
<str>\f *string_buf_ptr++ = '\f';
<str>\(.|\n) *string_buf_ptr++ = yytext[1];
<str>[^\\n\"]+ {
char *yptr = yytext;
while ( *yptr ) {
string_cnt++;
*string_buf_ptr++ = *yptr++;
}
}
. {printf("INVALID: %s", yytext); return INVALID_TOKEN;}
%%
并使用此输入:
4+5*6.4+"hello"
4+8
我得到这个输出:
entero sum entero mult real sum string
El valor es un string y es 36.000000hello.
entero Error syntax errorFIN del Analisis. Entrada CORRECTA
Numero lineas analizadas: 1
我的错误是什么?
您的语法的非终结符开头称为 "linea",这是有充分理由的:它恰好定义了一行 (una línea)。 Bison 解析器准确地识别开始非终端后跟文件结束符,因此如果您的输入包含多行,解析器将在第一行之后遇到 EOF 以外的内容时报告语法错误。
如果你想识别多行,你需要写一个匹配多行的语法:
programa : linea
| programa linea