#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-разрядные целые числа. Если это так, то опять же единственным решением является дискриминационный тип объединения.