цифры после десятичной точки заменяются на 0 в bison и flex

#bison #flex-lexer #yacc

Вопрос:

Я новичок в bison и flex.Я присваиваю плавающее значение, предположим, a=12,34 .Но когда я печатаю значение, я нахожу 12,000000.Пожалуйста, помогите мне .Заранее спасибо.Значение lex — файла ruturn с плавающей точкой очень хорошо.Я печатаю значение в другом месте кода, и это нормально.Но когда значение присваивается переменной, возникает проблема, а затем замените значения после десятичной точки на ).

Вот мое досье на бизона

     /*C declarations (types, variables, functions, preprocessor commands)*/

    %{
        #include<stdio.h>
        # include <stdlib.h>
        # include <stdarg.h>
        # include <string.h>
        # include <math.h>
        
        int yylex(void);
        int check[100],int_val[1000],var_type[1000];
        float float_val[1000];
        char char_val[1000];
        int caseD,caseV;
        
        
        
        
    %}
    /* Bison declarations (grammar symbols, operator precedence decl., attribute data type) */
    %error-verbose

       %union{
      int intVal;
      char* variable;
      char* strVal;
      float floatVal;
      char charVal;
    }
     
     
     %token Begin INTEGER FLOAT CHAR END COLON SEMICOLON ASSIGN COMMA  FORWARD_ARROW SHOW 
     %token BACKWARD_ARROW TAKE PLUS SUB MULT DIV MOD OTB CTB POW SIN COS TAN LOG LOG10 OP CP 
     %token LESS_THAN GREATER_THAN LESS_EQUAL GREATER_EQUAL IF ELSE_IF ELSE EQUAL NOT_EQUAL INC
     %token DEC FOR IN FOR_INC FOR_DEC EVEN_ODD FACTORIAL SUM GCD LCM SWITCH
     %token DEFAULT WHILE OSB CSB
     
     %token<intVal>INT_VAL
     %token<floatVal>FLOAT_VAL
     %token<charVal>CHAR_VAL
     %token<intVal>VARIABLE
     %token<strVal>STRING_VAL

     
     %type<intVal>expression statements cdeclare condition cstatements number
   

    %%

    program:Begin COLON cstatements END   {printf("ntttttCompilation Done Succesfully!!!n");
                                                
                                          
                                          }
           ;
    cstatements:/* Empty */           {}
               |SEMICOLON                       {printf("nttttEmpty statementn");}
               |cstatements cdeclare SEMICOLON  
               |cstatements statements
               
               
              
               ;
    cdeclare:FLOAT float_id {}
            
                
            ;
   
    float_id:float_id1 COMMA float_id 
      |float_id1
      ;
    float_id1:VARIABLE      {
                                if(check[$1]==1)
                                 {
                                   printf("nttttCompilation error-> %c is redeclared n",$1 97);
                                 }
                                else{
                                var_type[$1]=1;
                                check[$1]=1;
                                printf("ntttt%c is declared successfullyn",$1 97);
                               }
                            }
        |VARIABLE ASSIGN expression {   
                                        if(check[$1]==1)
                                         {
                                           printf("nttttCompilation error-> %c is redeclared n",$1 97);
                                         }
                                        else{
                                        var_type[$1]=1;
                                        check[$1]=1;
                                        float_val[$1]=$3;
                                        printf("ntttt%c is declared and assigned by %f successfullyn",$1 97,(float)($3));
                                       }
                                
                               }
        
        ;
        
   
                               
        
        

    statements:SHOW FORWARD_ARROW VARIABLE SEMICOLON       { 
                                                                if(check[$3] == 1) 
                                                                    {
                                                                     if(var_type[$3]==0)
                                                                        printf("nttttValue of %c is: %dn",$3 97,int_val[$3]);
                                                                     else if(var_type[$3]==1)
                                                                        printf("nttttValue of %c is: %fn",$3 97,float_val[$3]);   
                                                                     else if(var_type[$3]==2)
                                                                        printf("nttttValue of %c is: %cn",$3 97,char_val[$3]);                                                                        
                                                                    }
                                                                else
                                                                {
                                                                
                                                                    printf("nttttCompilation error-> %c was not declaredn",$3 97);
                                                                }

                                                            }
            
                                                        
              |VARIABLE ASSIGN expression SEMICOLON         {                                                           
                                                                if(check[$1] == 1)
                                                                {
                                                                    if(var_type[$1]==0)
                                                                        {
                                                                          int_val[$1]=$3;
                                                                          printf("ntttt%c is assigned by %d successfullyn",$1 97,$3); 
                                                                        }
                                                                     else if(var_type[$1]==1)
                                                                       {
                                                                         float_val[$1]=$3;
                                                                         printf("ntttt%c is assigned by %f successfullyn",$1 97,(float)($3));
                                                                       }
                                                                      else if(var_type[$1]==2)
                                                                       {
                                                                         float_val[$1]=$3;
                                                                         printf("ntttt%c is assigned by %c successfullyn",$1 97,$3);
                                                                       }
                                                                }
                                                                else
                                                                {
                                                                  printf("nttCompilation error-> %c was not declaredn",$1 97);
                                                                }
                                                        }
             
              ;


    expression: number{ $ = $1;  
                       //printf("%fn",$1);
                      }
             

    number:INT_VAL {$=$1;}
          |FLOAT_VAL {$=$1;
                      //printf("%fn",$1);
                     }
          |CHAR_VAL  {$=$1;}
        
          ;
              
    %%


    int yywrap(){
    return 1;
    }
    int yyerror(char *s)
    {
    fprintf(stderr,"%sn",s);
    }
    int main()
    {
    freopen("input.txt","r",stdin);
    yyparse();
    }
 

Если я назначу m_float a:=12.45.Тогда результат должен быть 12.45.Но программа выдает мне 12.000000.

Ответ №1:

Вы заявили, что

 %type<intVal>expression … number
 

поэтому , когда вы создаете a number из a FLOAT_VAL , вы преобразуете его в целое число. Но все ваши переменные имеют плавающую точку, поэтому позже вы сохраните это целое число в виде значения с плавающей запятой. Эффект на самом деле ничем не отличается от следующего:

 float value = 12.45;
int number = value;
int expr = number;
float a = expr:
printf("a = %fn", a);
 

Я надеюсь, что очевидно, почему
этот фрагмент C будет распечатан a = 12.000000 .

Создать калькулятор с несколькими типами данных не так просто. Вы не можете использовать простой примитивный тип C для хранения чего-либо, что может быть одним из различных типов. Вам понадобится какой-то дискриминационный союз, а это намного больше работы

Распространенным решением (например, используемым JavaScript) является использование double в качестве единственного числового типа. (В общем, вы должны использовать double вместо float в любом случае; float недостаточно точен для многих вычислений.) A double может точно представлять любое 32-разрядное целое значение, поэтому вы не теряете точности при использовании double для хранения целых чисел.

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

На типичных платформах double имеет точность 53 бита, поэтому вы можете использовать целые числа, несколько большие, чем могли бы поместиться в an int , но не такие большие, как могли бы поместиться в a long long . Иногда вам действительно нужны 64-разрядные целые числа. Если это так, то опять же единственным решением является дискриминационный тип объединения.