Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
畅游知识海洋
json
提交
c2d55109
J
json
项目概览
畅游知识海洋
/
json
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
json
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
c2d55109
编写于
2月 11, 2017
作者:
N
Niels Lohmann
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
🔨
make lexer distinguishes number types
上级
9f5dccba
变更
3
展开全部
隐藏空白更改
内联
并排
Showing
3 changed file
with
275 addition
and
215 deletion
+275
-215
src/json.hpp
src/json.hpp
+190
-128
src/json.hpp.re2c
src/json.hpp.re2c
+60
-76
test/src/unit-class_lexer.cpp
test/src/unit-class_lexer.cpp
+25
-11
未找到文件。
src/json.hpp
浏览文件 @
c2d55109
此差异已折叠。
点击以展开。
src/json.hpp.re2c
浏览文件 @
c2d55109
...
...
@@ -9444,7 +9444,9 @@ class basic_json
literal_false, ///< the `false` literal
literal_null, ///< the `null` literal
value_string, ///< a string -- use get_string() for actual value
value_number, ///< a number -- use get_number() for actual value
value_unsigned_integer, ///< an unsigned integer -- use get_number() for actual value
value_signed_integer, ///< a signed integer -- use get_number() for actual value
value_float, ///< an floating point number -- use get_number() for actual value
begin_array, ///< the character for array begin `[`
begin_object, ///< the character for object begin `{`
end_array, ///< the character for array end `]`
...
...
@@ -9596,7 +9598,9 @@ class basic_json
return "null literal";
case token_type::value_string:
return "string literal";
case token_type::value_number:
case lexer::token_type::value_unsigned_integer:
case lexer::token_type::value_signed_integer:
case lexer::token_type::value_float:
return "number literal";
case token_type::begin_array:
return "'['";
...
...
@@ -9684,18 +9688,22 @@ class basic_json
"false" { last_token_type = token_type::literal_false; break; }
// number
decimal_point = ".";
digit = [0-9];
digit_1_9 = [1-9];
e = "e" | "E";
minus = "-";
plus = "+";
zero = "0";
exp = e (minus | plus)? digit+;
frac = decimal_point digit+;
int = (zero | digit_1_9 digit*);
number = minus? int frac? exp?;
number { last_token_type = token_type::value_number; break; }
decimal_point = ".";
digit = [0-9];
digit_1_9 = [1-9];
e = "e" | "E";
minus = "-";
plus = "+";
zero = "0";
exp = e (minus | plus)? digit+;
frac = decimal_point digit+;
int = (zero | digit_1_9 digit*);
number_unsigned = int;
number_unsigned { last_token_type = token_type::value_unsigned_integer; break; }
number_signed = minus int;
number_signed { last_token_type = token_type::value_signed_integer; break; }
number_float = minus? int frac? exp?;
number_float { last_token_type = token_type::value_float; break; }
// string
quotation_mark = "\"";
...
...
@@ -10017,42 +10025,6 @@ class basic_json
return parse(val, std::is_integral<T>());
}
/*!
This is a helper to determine whether to parse the token into
floating-point or integral type.
@note We wouldn't need it if we had separate token types for
integral and floating-point cases.
@return true iff token matches `^[+-]\d+$`
*/
bool is_integral() const
{
const char* p = m_start;
if (p == nullptr)
{
return false; // LCOV_EXCL_LINE
}
if ((*p == '-') or (*p == '+'))
{
++p;
}
if (p == m_end)
{
return false; // LCOV_EXCL_LINE
}
while ((p < m_end) and (*p >= '0') and (*p <= '9'))
{
++p;
}
return (p == m_end);
}
private:
const char* const m_start = nullptr;
const char* const m_end = nullptr;
...
...
@@ -10161,7 +10133,7 @@ class basic_json
return (x == static_cast<decltype(x)>(value)) // x fits into destination T
and (x < 0) == (value < 0) // preserved sign
and ((x != 0) or is_integral()) // strto[u]ll did nto fail
//
and ((x != 0) or is_integral()) // strto[u]ll did nto fail
and (errno == 0) // strto[u]ll did not overflow
and (m_start < m_end) // token was not empty
and (endptr == m_end); // parsed entire token exactly
...
...
@@ -10185,46 +10157,56 @@ class basic_json
interpreted as a number
@param[out] result @ref basic_json object to receive the number.
@param[in] token the type of the number token
*/
void get_number(basic_json& result) const
void get_number(basic_json& result
, const token_type token
) const
{
assert(m_start != nullptr);
assert(m_start < m_cursor);
assert((token == token_type::value_unsigned_integer) or
(token == token_type::value_signed_integer) or
(token == token_type::value_float));
strtonum num(reinterpret_cast<const char*>(m_start),
reinterpret_cast<const char*>(m_cursor));
const bool is_negative = (*m_start == '-');
result.m_type = value_t::discarded;
if (not num.is_integral())
switch (token)
{
// will parse as float below
}
else if (is_negative)
{
number_integer_t val{0};
if (num.to(val))
case lexer::token_type::value_unsigned_integer:
{
result.m_type = value_t::number_integer;
result.m_value = val;
number_unsigned_t val{0};
if (num.to(val))
{
result.m_type = value_t::number_unsigned;
result.m_value = val;
return;
}
break;
}
}
else
{
number_unsigned_t val{0};
if (num.to(val))
case lexer::token_type::value_signed_integer:
{
result.m_type = value_t::number_unsigned;
result.m_value = val;
number_integer_t val{0};
if (num.to(val))
{
result.m_type = value_t::number_integer;
result.m_value = val;
return;
}
break;
}
default:
{
break;
}
}
number_float_t val{0};
if (
result.m_type != value_t::discarded or (not num.to(val)
))
if (
not num.to(val
))
{
// already have a value from above or couldn't parse as float_t
// couldn't parse as float_t
result.m_type = value_t::discarded;
return;
}
...
...
@@ -10480,9 +10462,11 @@ class basic_json
break;
}
case lexer::token_type::value_number:
case lexer::token_type::value_unsigned_integer:
case lexer::token_type::value_signed_integer:
case lexer::token_type::value_float:
{
m_lexer.get_number(result);
m_lexer.get_number(result
, last_token
);
get_token();
break;
}
...
...
test/src/unit-class_lexer.cpp
浏览文件 @
c2d55109
...
...
@@ -65,25 +65,37 @@ TEST_CASE("lexer class")
SECTION
(
"numbers"
)
{
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"0"
),
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
numb
er
));
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
unsigned_integ
er
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"1"
),
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
numb
er
));
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
unsigned_integ
er
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"2"
),
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
numb
er
));
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
unsigned_integ
er
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"3"
),
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
numb
er
));
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
unsigned_integ
er
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"4"
),
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
numb
er
));
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
unsigned_integ
er
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"5"
),
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
numb
er
));
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
unsigned_integ
er
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"6"
),
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
numb
er
));
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
unsigned_integ
er
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"7"
),
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
numb
er
));
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
unsigned_integ
er
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"8"
),
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
numb
er
));
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_
unsigned_integ
er
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"9"
),
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_number
));
1
).
scan
()
==
json
::
lexer
::
token_type
::
value_unsigned_integer
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"-0"
),
2
).
scan
()
==
json
::
lexer
::
token_type
::
value_signed_integer
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"-1"
),
2
).
scan
()
==
json
::
lexer
::
token_type
::
value_signed_integer
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"1.1"
),
3
).
scan
()
==
json
::
lexer
::
token_type
::
value_float
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"-1.1"
),
4
).
scan
()
==
json
::
lexer
::
token_type
::
value_float
));
CHECK
((
json
::
lexer
(
reinterpret_cast
<
const
json
::
lexer
::
lexer_char_t
*>
(
"1E10"
),
4
).
scan
()
==
json
::
lexer
::
token_type
::
value_float
));
}
SECTION
(
"whitespace"
)
...
...
@@ -109,7 +121,9 @@ TEST_CASE("lexer class")
CHECK
((
json
::
lexer
::
token_type_name
(
json
::
lexer
::
token_type
::
literal_false
)
==
"false literal"
));
CHECK
((
json
::
lexer
::
token_type_name
(
json
::
lexer
::
token_type
::
literal_null
)
==
"null literal"
));
CHECK
((
json
::
lexer
::
token_type_name
(
json
::
lexer
::
token_type
::
value_string
)
==
"string literal"
));
CHECK
((
json
::
lexer
::
token_type_name
(
json
::
lexer
::
token_type
::
value_number
)
==
"number literal"
));
CHECK
((
json
::
lexer
::
token_type_name
(
json
::
lexer
::
token_type
::
value_unsigned_integer
)
==
"number literal"
));
CHECK
((
json
::
lexer
::
token_type_name
(
json
::
lexer
::
token_type
::
value_signed_integer
)
==
"number literal"
));
CHECK
((
json
::
lexer
::
token_type_name
(
json
::
lexer
::
token_type
::
value_float
)
==
"number literal"
));
CHECK
((
json
::
lexer
::
token_type_name
(
json
::
lexer
::
token_type
::
begin_array
)
==
"'['"
));
CHECK
((
json
::
lexer
::
token_type_name
(
json
::
lexer
::
token_type
::
begin_object
)
==
"'{'"
));
CHECK
((
json
::
lexer
::
token_type_name
(
json
::
lexer
::
token_type
::
end_array
)
==
"']'"
));
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录