野牛只读一行

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