cprover
parse_float.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Conversion of Expressions
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "parse_float.h"
13 
14 #include <cctype>
15 
17  const std::string &src,
18  mp_integer &significand,
19  mp_integer &exponent,
20  unsigned &exponent_base,
21  bool &is_float, bool &is_long, bool &is_imaginary,
22  bool &is_decimal, bool &is_float80, bool &is_float128)
23 {
24  // {digits}{dot}{digits}{exponent}?{floatsuffix}?
25  // {digits}{dot}{exponent}?{floatsuffix}?
26  // {dot}{digits}{exponent}?{floatsuffix}?
27  // {digits}{exponent}{floatsuffix}?
28 
29  // Hex format (C99):
30  // 0x{hexdigits}{dot}{hexdigits}[pP]{exponent}{floatsuffix}?
31  // 0x{hexdigits}{dot}[pP]{exponent}{floatsuffix}?
32 
33  const char *p=src.c_str();
34 
35  std::string str_whole_number,
36  str_fraction_part,
37  str_exponent;
38 
39  exponent_base=10;
40 
41  // is this hex?
42 
43  if(src.size()>=2 && src[0]=='0' && tolower(src[1])=='x')
44  {
45  // skip the 0x
46  p+=2;
47 
48  exponent_base=2;
49 
50  // get whole number part
51  while(*p!='.' && *p!=0 && *p!='p' && *p!='P')
52  {
53  str_whole_number+=*p;
54  p++;
55  }
56 
57  // skip dot
58  if(*p=='.')
59  p++;
60 
61  // get fraction part
62  while(*p!=0 && *p!='p' && *p!='P')
63  {
64  str_fraction_part+=*p;
65  p++;
66  }
67 
68  // skip P
69  if(*p=='p' || *p=='P')
70  p++;
71 
72  // skip +
73  if(*p=='+')
74  p++;
75 
76  // get exponent
77  while(*p!=0 && *p!='f' && *p!='F' && *p!='l' && *p!='L' &&
78  *p!='w' && *p!='W' && *p!='q' && *p!='Q' && *p!='d' && *p!='D')
79  {
80  str_exponent+=*p;
81  p++;
82  }
83 
84  std::string str_number=str_whole_number+
85  str_fraction_part;
86 
87  // The significand part is interpreted as a (decimal or hexadecimal)
88  // rational number; the digit sequence in the exponent part is
89  // interpreted as a decimal integer.
90 
91  if(str_number.empty())
92  significand=0;
93  else
94  significand=string2integer(str_number, 16); // hex
95 
96  if(str_exponent.empty())
97  exponent=0;
98  else
99  exponent=string2integer(str_exponent, 10); // decimal
100 
101  // adjust exponent
102  exponent-=str_fraction_part.size()*4; // each digit has 4 bits
103  }
104  else
105  {
106  // get whole number part
107  while(*p!='.' && *p!=0 && *p!='e' && *p!='E' &&
108  *p!='f' && *p!='F' && *p!='l' && *p!='L' &&
109  *p!='w' && *p!='W' && *p!='q' && *p!='Q' && *p!='d' && *p!='D' &&
110  *p!='i' && *p!='I' && *p!='j' && *p!='J')
111  {
112  str_whole_number+=*p;
113  p++;
114  }
115 
116  // skip dot
117  if(*p=='.')
118  p++;
119 
120  // get fraction part
121  while(*p!=0 && *p!='e' && *p!='E' &&
122  *p!='f' && *p!='F' && *p!='l' && *p!='L' &&
123  *p!='w' && *p!='W' && *p!='q' && *p!='Q' && *p!='d' && *p!='D' &&
124  *p!='i' && *p!='I' && *p!='j' && *p!='J')
125  {
126  str_fraction_part+=*p;
127  p++;
128  }
129 
130  // skip E
131  if(*p=='e' || *p=='E')
132  p++;
133 
134  // skip +
135  if(*p=='+')
136  p++;
137 
138  // get exponent
139  while(*p!=0 && *p!='f' && *p!='F' && *p!='l' && *p!='L' &&
140  *p!='w' && *p!='W' && *p!='q' && *p!='Q' && *p!='d' && *p!='D' &&
141  *p!='i' && *p!='I' && *p!='j' && *p!='J')
142  {
143  str_exponent+=*p;
144  p++;
145  }
146 
147  std::string str_number=str_whole_number+
148  str_fraction_part;
149 
150  if(str_number.empty())
151  significand=0;
152  else
153  significand=string2integer(str_number, 10);
154 
155  if(str_exponent.empty())
156  exponent=0;
157  else
158  exponent=string2integer(str_exponent, 10);
159 
160  // adjust exponent
161  exponent-=str_fraction_part.size();
162  }
163 
164  // get flags
165  is_float=is_long=is_imaginary=is_decimal=is_float80=is_float128=false;
166 
167  while(*p!=0)
168  {
169  if(*p=='f' || *p=='F')
170  is_float=true;
171  else if(*p=='l' || *p=='L')
172  is_long=true;
173  else if(*p=='i' || *p=='I' || *p=='j' || *p=='J')
174  is_imaginary=true;
175  // http://gcc.gnu.org/onlinedocs/gcc/Decimal-Float.html
176  else if(*p=='d' || *p=='D')
177  // a suffix with just d or D but nothing else is a GCC extension with no
178  // particular effect -- and forbidden by Clang
179  is_decimal=is_decimal || *(p+1)!=0;
180  // http://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
181  else if(*p=='w' || *p=='W')
182  is_float80=true;
183  else if(*p=='q' || *p=='Q')
184  is_float128=true;
185 
186  p++;
187  }
188 }
void parse_float(const std::string &src, mp_integer &significand, mp_integer &exponent, unsigned &exponent_base, bool &is_float, bool &is_long, bool &is_imaginary, bool &is_decimal, bool &is_float80, bool &is_float128)
Definition: parse_float.cpp:16
BigInt mp_integer
Definition: mp_arith.h:19
const mp_integer string2integer(const std::string &n, unsigned base)
Definition: mp_arith.cpp:53
ANSI-C Conversion / Type Checking.