2015-10-11 4 views
-2

Я делаю простой калькулятор с flex и bison, но он только считывает первую строку входного файла. это мой бизон код: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($1.lexema,(void *)&$3)*/;} 

     | OP_SUM expr NX_LINE {if($2.type==0) { 

          printf("El valor es %d. \n", $2.integer); 

         } else if($2.type==1) { 

          printf("El valor es %f. \n", $2.real); 

         }} 

     | OP_REST expr NX_LINE {if($2.type==0) { 

          printf("El valor es %d. \n", -$2.integer); 

         } else if($2.type==1) { 

          printf("El valor es %f. \n", -$2.real); 

         }} 

     | expr NX_LINE {if($1.type==0) { 

          printf("El valor es entero y es %d. \n", $1.integer); 

         } else if($1.type==1) { 

          printf("El valor es un float y es %f. \n", $1.real); 

         } else if($1.type==2) { 

          printf("El valor es un string y es %s. \n", $1.string); 

         }} 

     ; 

expr : expr OP_SUM term {if($1.type==0 && $3.type==0) { 

              $$.type=0; 

              $$.integer=$1.integer+$3.integer; 

            } else if($1.type==1 && $3.type==1) { 

             $$.type=1; 

             $$.real=$1.real+$3.real; 

            } else if($1.type==0 && $3.type==1) { 

             $$.type=1; 

             $$.real=$1.integer+$3.real; 

            } else if($1.type==1 && $3.type==0) { 

             $$.type=1; 

             $$.real=$1.real+$3.integer; 

            }else if($1.type==0 && $3.type==2) { 

             $$.type=2; 

             $$.string=malloc(sizeof($3.string)+sizeof($1.integer)); 

             sprintf($$.string,"%d%s",$1.integer,$3.string); 

            } else if($1.type==1 && $3.type==2) { 

             $$.type=2; 

             $$.string=malloc(sizeof($3.string)+sizeof($1.real)); 

             sprintf($$.string,"%f%s",$1.real,$3.string); 

            }else if($3.type==0 && $1.type==2) { 

             $$.type=2; 

             $$.string=malloc(sizeof($1.string)+sizeof($3.integer)); 

             sprintf($$.string,"%s%d",$1.string,$3.integer); 

            } else if($3.type==1 && $1.type==2) { 

             $$.type=2; 

             $$.string=malloc(sizeof($3.real)+sizeof($1.string)); 

             sprintf($$.string,"%s%f",$1.string,$3.real); 

            }} 

     | expr OP_REST term {if($1.type==0 && $3.type==0) { 

              $$.type=0; 

              $$.integer=$1.integer-$3.integer; 

            } else if($1.type==1 && $3.type==1) { 

             $$.type=1; 

             $$.real=$1.real-$3.real; 

            } else if($1.type==0 && $3.type==1) { 

             $$.type=1; 

             $$.real=$1.integer-$3.real; 

            } else if($1.type==1 && $3.type==0) { 

             $$.type=0; 

             $$.real=$1.real-$3.integer; 

            }} 

     | term    {$$=$1;} 

     ; 

term : term OP_MULT factor {if($1.type==0 && $3.type==0) { 

              $$.type=0; 

              $$.integer=$1.integer*$3.integer; 

            } else if($1.type==1 && $3.type==1) { 

             $$.type=1; 

             $$.real=$1.real*$3.real; 

            } else if($1.type==0 && $3.type==1) { 

             $$.type=1; 

             $$.real=$1.integer*$3.real; 

            } else if($1.type==1 && $3.type==0) { 

             $$.type=0; 

             $$.real=$1.real*$3.integer; 

            }} 

     | term OP_DIV factor {if($1.type==0 && $3.type==0) { 

              $$.type=0; 

              $$.integer=$1.integer/$3.integer; 

            } else if($1.type==1 && $3.type==1) { 

             $$.type=1; 

             $$.real=$1.real/$3.real; 

            } else if($1.type==0 && $3.type==1) { 

             $$.type=1; 

             $$.real=$1.integer/$3.real; 

            } else if($1.type==1 && $3.type==0) { 

             $$.type=0; 

             $$.real=$1.real/$3.integer; 

            }} 

     | term OP_MOD factor {if($1.type==0 && $3.type==0) { 

              $$.type=0; 

              $$.integer=$1.integer%$3.integer; 

            } else if($1.type==1 && $3.type==1) { 

             $$.type=1; 

             $$.real=fmod($1.real,$3.real); 

            }} 

     | factor    {$$=$1;} 

     ; 

factor : primary    {$$=$1;} 

     | primary OP_POW factor {if($1.type==0 && $3.type==0) { 

              $$.type=0; 

              $$.integer=pow($1.integer,$3.integer); 

            } else if($1.type==1 && $3.type==1) { 

             $$.type=1; 

             $$.real=pow($1.real,$3.real); 

            }} 

     ; 

primary : PARENTESIS1 expr PARENTESIS2 {$$=$2;} 

     | PARENTESIS1 OP_REST expr PARENTESIS2 {if($3.type==0) { 

                 $$.type=0; 

                 $$.integer=-$3.integer; 

                } else if($3.type==1) { 

                 $$.type=1; 

                 $$.real=$3.real; 

                }} 

     | PARENTESIS1 OP_SUM expr PARENTESIS2 {$$=$3;} 

     | LIT_INT {$$=$1;} 

     | LIT_FLOAT {$$=$1;} 

     | CADENA {$$=$1;} 

     | IDENT {/*sym_lookup($1,$$)*/;} 

     ; 



%% 





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 = '\0'; 

/* 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 

Какая у меня ошибка?

+2

Too. Многое. Код. Пожалуйста, ознакомьтесь с * минимальным примером * – m02ph3u5

+1

Пожалуйста, уменьшите количество кода в своем Вопросе, сосредоточив внимание на части кода, которая создает трудности. –

ответ

1

Начальная не-терминальная грамматика называется «linea», и по уважительной причине она определяет ровно одну строку (una línea). Анализаторы Bison точно распознают начало без терминалов, за которым следует конец файла, поэтому, если ваш ввод содержит более одной строки, синтаксический анализатор будет сообщать синтаксическую ошибку, когда он встречает что-то, отличное от EOF, после первой строки.

Если вы хотите, чтобы распознать несколько строк, вы должны написать грамматику, которая соответствует несколько строк:

programa : linea 
     | programa linea