Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
3acbc0a0
Commit
3acbc0a0
authored
Aug 06, 2019
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Re-use floating point parser in number parser
parent
ace0227f
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
39 additions
and
118 deletions
+39
-118
libcaf_core/caf/detail/parser/read_floating_point.hpp
libcaf_core/caf/detail/parser/read_floating_point.hpp
+5
-1
libcaf_core/caf/detail/parser/read_number.hpp
libcaf_core/caf/detail/parser/read_number.hpp
+34
-117
No files found.
libcaf_core/caf/detail/parser/read_floating_point.hpp
View file @
3acbc0a0
...
@@ -45,7 +45,8 @@ namespace parser {
...
@@ -45,7 +45,8 @@ namespace parser {
/// the pre-decimal value.
/// the pre-decimal value.
template
<
class
Iterator
,
class
Sentinel
,
class
Consumer
,
class
ValueType
>
template
<
class
Iterator
,
class
Sentinel
,
class
Consumer
,
class
ValueType
>
void
read_floating_point
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
consumer
,
void
read_floating_point
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
consumer
,
optional
<
ValueType
>
start_value
)
{
optional
<
ValueType
>
start_value
,
bool
negative
=
false
)
{
// Any exponent larger than 511 always overflows.
// Any exponent larger than 511 always overflows.
static
constexpr
int
max_double_exponent
=
511
;
static
constexpr
int
max_double_exponent
=
511
;
// We assume a simple integer until proven wrong.
// We assume a simple integer until proven wrong.
...
@@ -58,6 +59,9 @@ void read_floating_point(state<Iterator, Sentinel>& ps, Consumer& consumer,
...
@@ -58,6 +59,9 @@ void read_floating_point(state<Iterator, Sentinel>& ps, Consumer& consumer,
}
else
if
(
*
start_value
<
0
)
{
}
else
if
(
*
start_value
<
0
)
{
sign
=
minus
;
sign
=
minus
;
result
=
-*
start_value
;
result
=
-*
start_value
;
}
else
if
(
negative
)
{
sign
=
minus
;
result
=
*
start_value
;
}
else
{
}
else
{
sign
=
plus
;
sign
=
plus
;
result
=
*
start_value
;
result
=
*
start_value
;
...
...
libcaf_core/caf/detail/parser/read_number.hpp
View file @
3acbc0a0
...
@@ -21,10 +21,11 @@
...
@@ -21,10 +21,11 @@
#include <cstdint>
#include <cstdint>
#include "caf/config.hpp"
#include "caf/config.hpp"
#include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/add_ascii.hpp"
#include "caf/detail/parser/add_ascii.hpp"
#include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/is_digit.hpp"
#include "caf/detail/parser/is_digit.hpp"
#include "caf/detail/parser/read_floating_point.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/parser/sub_ascii.hpp"
#include "caf/detail/parser/sub_ascii.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/detail/scope_guard.hpp"
...
@@ -42,87 +43,32 @@ namespace parser {
...
@@ -42,87 +43,32 @@ namespace parser {
/// `double`.
/// `double`.
template
<
class
Iterator
,
class
Sentinel
,
class
Consumer
>
template
<
class
Iterator
,
class
Sentinel
,
class
Consumer
>
void
read_number
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
consumer
)
{
void
read_number
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
consumer
)
{
// Any exponent larger than 511 always overflows.
static
constexpr
int
max_double_exponent
=
511
;
// We assume a simple integer until proven wrong.
enum
result_type_t
{
integer
,
positive_double
,
negative_double
};
auto
result_type
=
integer
;
// Adjusts our mantissa, e.g., 1.23 becomes 123 with a dec_exp of -2.
auto
dec_exp
=
0
;
// Exponent part of a floating point literal.
auto
exp
=
0
;
// Our result when reading a floating point number.
auto
dbl_res
=
0.
;
// Our result when reading an integer number.
// Our result when reading an integer number.
int64_t
int_res
=
0
;
int64_t
result
=
0
;
// Computes the result on success.
// Computes the result on success.
auto
g
=
caf
::
detail
::
make_scope_guard
([
&
]
{
auto
g
=
caf
::
detail
::
make_scope_guard
([
&
]
{
if
(
ps
.
code
<=
pec
::
trailing_character
)
{
if
(
ps
.
code
<=
pec
::
trailing_character
)
if
(
result_type
==
integer
)
{
consumer
.
value
(
result
);
consumer
.
value
(
int_res
);
return
;
}
// Compute final floating point number.
// 1) Fix the exponent.
exp
+=
dec_exp
;
// 2) Check whether exponent is in valid range.
if
(
exp
<
-
max_double_exponent
)
{
ps
.
code
=
pec
::
exponent_underflow
;
return
;
}
if
(
exp
>
max_double_exponent
)
{
ps
.
code
=
pec
::
exponent_overflow
;
return
;
}
// 3) Scale result.
// Pre-computed powers of 10 for the scaling loop.
static
double
powerTable
[]
=
{
1e1
,
1e2
,
1e4
,
1e8
,
1e16
,
1e32
,
1e64
,
1e128
,
1e256
};
auto
i
=
0
;
if
(
exp
<
0
)
{
for
(
auto
n
=
-
exp
;
n
!=
0
;
n
>>=
1
,
++
i
)
if
(
n
&
0x01
)
dbl_res
/=
powerTable
[
i
];
}
else
{
for
(
auto
n
=
exp
;
n
!=
0
;
n
>>=
1
,
++
i
)
if
(
n
&
0x01
)
dbl_res
*=
powerTable
[
i
];
}
// 4) Fix sign and call consumer.
consumer
.
value
(
result_type
==
positive_double
?
dbl_res
:
-
dbl_res
);
}
});
});
// Switches from parsing an integer to parsing a double.
// clang-format off
auto
ch_res
=
[
&
](
result_type_t
x
)
{
CAF_ASSERT
(
result_type
==
integer
);
result_type
=
x
;
// We parse doubles as positive number and restore the sign in `g`.
dbl_res
=
result_type
==
negative_double
?
-
static_cast
<
double
>
(
int_res
)
:
static_cast
<
double
>
(
int_res
);
};
// Reads the a decimal place.
auto
rd_decimal
=
[
&
](
char
c
)
{
--
dec_exp
;
return
add_ascii
<
10
>
(
dbl_res
,
c
);
};
// Definition of our parser FSM.
// Definition of our parser FSM.
start
();
start
();
state
(
init
)
{
state
(
init
)
{
transition
(
init
,
"
\t
"
)
transition
(
init
,
"
\t
"
)
transition
(
has_plus
,
'+'
)
transition
(
has_plus
,
'+'
)
transition
(
has_minus
,
'-'
)
transition
(
has_minus
,
'-'
)
transition
(
pos_zero
,
'0'
)
epsilon
(
has_plus
)
epsilon
(
has_plus
)
}
}
// "+" or "-" alone aren't numbers.
// "+" or "-" alone aren't numbers.
state
(
has_plus
)
{
state
(
has_plus
)
{
transition
(
leading_dot
,
'.'
,
ch_res
(
positive_double
))
fsm_epsilon
(
read_floating_point
(
ps
,
consumer
,
optional
<
double
>
{
0.
}),
done
,
'.'
,
g
.
disable
())
transition
(
pos_zero
,
'0'
)
transition
(
pos_zero
,
'0'
)
epsilon
(
pos_dec
)
epsilon
(
pos_dec
)
}
}
state
(
has_minus
)
{
state
(
has_minus
)
{
transition
(
leading_dot
,
'.'
,
ch_res
(
negative_double
))
fsm_epsilon
(
read_floating_point
(
ps
,
consumer
,
optional
<
double
>
{
0.
},
true
),
done
,
'.'
,
g
.
disable
())
transition
(
neg_zero
,
'0'
)
transition
(
neg_zero
,
'0'
)
epsilon
(
neg_dec
)
epsilon
(
neg_dec
)
}
}
...
@@ -130,13 +76,15 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
...
@@ -130,13 +76,15 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
term_state
(
pos_zero
)
{
term_state
(
pos_zero
)
{
transition
(
start_pos_bin
,
"bB"
)
transition
(
start_pos_bin
,
"bB"
)
transition
(
start_pos_hex
,
"xX"
)
transition
(
start_pos_hex
,
"xX"
)
transition
(
trailing_dot
,
'.'
,
ch_res
(
positive_double
))
fsm_epsilon
(
read_floating_point
(
ps
,
consumer
,
optional
<
double
>
{
0.
}),
done
,
'.'
,
g
.
disable
())
epsilon
(
pos_oct
)
epsilon
(
pos_oct
)
}
}
term_state
(
neg_zero
)
{
term_state
(
neg_zero
)
{
transition
(
start_neg_bin
,
"bB"
)
transition
(
start_neg_bin
,
"bB"
)
transition
(
start_neg_hex
,
"xX"
)
transition
(
start_neg_hex
,
"xX"
)
transition
(
trailing_dot
,
'.'
,
ch_res
(
negative_double
))
fsm_epsilon
(
read_floating_point
(
ps
,
consumer
,
optional
<
double
>
{
0.
},
true
),
done
,
'.'
,
g
.
disable
())
epsilon
(
neg_oct
)
epsilon
(
neg_oct
)
}
}
// Binary integers.
// Binary integers.
...
@@ -144,27 +92,27 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
...
@@ -144,27 +92,27 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
epsilon
(
pos_bin
)
epsilon
(
pos_bin
)
}
}
term_state
(
pos_bin
)
{
term_state
(
pos_bin
)
{
transition
(
pos_bin
,
"01"
,
add_ascii
<
2
>
(
int_res
,
ch
),
pec
::
integer_overflow
)
transition
(
pos_bin
,
"01"
,
add_ascii
<
2
>
(
result
,
ch
),
pec
::
integer_overflow
)
}
}
state
(
start_neg_bin
)
{
state
(
start_neg_bin
)
{
epsilon
(
neg_bin
)
epsilon
(
neg_bin
)
}
}
term_state
(
neg_bin
)
{
term_state
(
neg_bin
)
{
transition
(
neg_bin
,
"01"
,
sub_ascii
<
2
>
(
int_res
,
ch
),
pec
::
integer_underflow
)
transition
(
neg_bin
,
"01"
,
sub_ascii
<
2
>
(
result
,
ch
),
pec
::
integer_underflow
)
}
}
// Octal integers.
// Octal integers.
state
(
start_pos_oct
)
{
state
(
start_pos_oct
)
{
epsilon
(
pos_oct
)
epsilon
(
pos_oct
)
}
}
term_state
(
pos_oct
)
{
term_state
(
pos_oct
)
{
transition
(
pos_oct
,
octal_chars
,
add_ascii
<
8
>
(
int_res
,
ch
),
transition
(
pos_oct
,
octal_chars
,
add_ascii
<
8
>
(
result
,
ch
),
pec
::
integer_overflow
)
pec
::
integer_overflow
)
}
}
state
(
start_neg_oct
)
{
state
(
start_neg_oct
)
{
epsilon
(
neg_oct
)
epsilon
(
neg_oct
)
}
}
term_state
(
neg_oct
)
{
term_state
(
neg_oct
)
{
transition
(
neg_oct
,
octal_chars
,
sub_ascii
<
8
>
(
int_res
,
ch
),
transition
(
neg_oct
,
octal_chars
,
sub_ascii
<
8
>
(
result
,
ch
),
pec
::
integer_underflow
)
pec
::
integer_underflow
)
}
}
// Hexal integers.
// Hexal integers.
...
@@ -172,70 +120,39 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
...
@@ -172,70 +120,39 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
epsilon
(
pos_hex
)
epsilon
(
pos_hex
)
}
}
term_state
(
pos_hex
)
{
term_state
(
pos_hex
)
{
transition
(
pos_hex
,
hexadecimal_chars
,
add_ascii
<
16
>
(
int_res
,
ch
),
transition
(
pos_hex
,
hexadecimal_chars
,
add_ascii
<
16
>
(
result
,
ch
),
pec
::
integer_overflow
)
pec
::
integer_overflow
)
}
}
state
(
start_neg_hex
)
{
state
(
start_neg_hex
)
{
epsilon
(
neg_hex
)
epsilon
(
neg_hex
)
}
}
term_state
(
neg_hex
)
{
term_state
(
neg_hex
)
{
transition
(
neg_hex
,
hexadecimal_chars
,
sub_ascii
<
16
>
(
int_res
,
ch
),
transition
(
neg_hex
,
hexadecimal_chars
,
sub_ascii
<
16
>
(
result
,
ch
),
pec
::
integer_underflow
)
pec
::
integer_underflow
)
}
}
// Reads the integer part of the mantissa or a positive decimal integer.
// Reads the integer part of the mantissa or a positive decimal integer.
term_state
(
pos_dec
)
{
term_state
(
pos_dec
)
{
transition
(
pos_dec
,
decimal_chars
,
add_ascii
<
10
>
(
int_res
,
ch
),
transition
(
pos_dec
,
decimal_chars
,
add_ascii
<
10
>
(
result
,
ch
),
pec
::
integer_overflow
)
pec
::
integer_overflow
)
transition
(
has_e
,
"eE"
,
ch_res
(
positive_double
))
fsm_epsilon
(
read_floating_point
(
ps
,
consumer
,
optional
<
double
>
{
result
}),
transition
(
trailing_dot
,
'.'
,
ch_res
(
positive_double
))
done
,
"eE"
,
g
.
disable
())
fsm_epsilon
(
read_floating_point
(
ps
,
consumer
,
optional
<
double
>
{
result
}),
done
,
'.'
,
g
.
disable
())
}
}
// Reads the integer part of the mantissa or a negative decimal integer.
// Reads the integer part of the mantissa or a negative decimal integer.
term_state
(
neg_dec
)
{
term_state
(
neg_dec
)
{
transition
(
neg_dec
,
decimal_chars
,
sub_ascii
<
10
>
(
int_res
,
ch
),
transition
(
neg_dec
,
decimal_chars
,
sub_ascii
<
10
>
(
result
,
ch
),
pec
::
integer_underflow
)
pec
::
integer_underflow
)
transition
(
has_e
,
"eE"
,
ch_res
(
negative_double
))
fsm_epsilon
(
read_floating_point
(
ps
,
consumer
,
optional
<
double
>
{
result
},
true
),
transition
(
trailing_dot
,
'.'
,
ch_res
(
negative_double
))
done
,
"eE"
,
g
.
disable
())
}
fsm_epsilon
(
read_floating_point
(
ps
,
consumer
,
optional
<
double
>
{
result
},
true
),
// ".", "+.", etc. aren't valid numbers, so this state isn't terminal.
done
,
'.'
,
g
.
disable
())
state
(
leading_dot
)
{
}
transition
(
after_dot
,
decimal_chars
,
rd_decimal
(
ch
),
pec
::
exponent_underflow
)
term_state
(
done
)
{
}
// nop
// "1." is a valid number, so a trailing dot is a terminal state.
term_state
(
trailing_dot
)
{
epsilon
(
after_dot
)
}
// Read the decimal part of a mantissa.
term_state
(
after_dot
)
{
transition
(
after_dot
,
decimal_chars
,
rd_decimal
(
ch
),
pec
::
exponent_underflow
)
transition
(
has_e
,
"eE"
)
}
// "...e", "...e+", and "...e-" aren't valid numbers, so these states are not
// terminal.
state
(
has_e
)
{
transition
(
has_plus_after_e
,
'+'
)
transition
(
has_minus_after_e
,
'-'
)
transition
(
pos_exp
,
decimal_chars
,
add_ascii
<
10
>
(
exp
,
ch
),
pec
::
exponent_overflow
)
}
state
(
has_plus_after_e
)
{
transition
(
pos_exp
,
decimal_chars
,
add_ascii
<
10
>
(
exp
,
ch
),
pec
::
exponent_overflow
)
}
state
(
has_minus_after_e
)
{
transition
(
neg_exp
,
decimal_chars
,
sub_ascii
<
10
>
(
exp
,
ch
),
pec
::
exponent_underflow
)
}
// Read a positive exponent.
term_state
(
pos_exp
)
{
transition
(
pos_exp
,
decimal_chars
,
add_ascii
<
10
>
(
exp
,
ch
),
pec
::
exponent_overflow
)
}
// Read a negative exponent.
term_state
(
neg_exp
)
{
transition
(
neg_exp
,
decimal_chars
,
sub_ascii
<
10
>
(
exp
,
ch
),
pec
::
exponent_underflow
)
}
}
fin
();
fin
();
// clang-format on
}
}
}
// namespace parser
}
// namespace parser
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment