🔨 simplifying scanner
This commit is contained in:
parent
3dc5d95422
commit
e99b783def
2 changed files with 34 additions and 60 deletions
72
src/json.hpp
72
src/json.hpp
|
@ -11461,17 +11461,6 @@ class basic_json
|
||||||
return codepoint;
|
return codepoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief create diagnostic representation of a codepoint
|
|
||||||
@return string "U+XXXX" for codepoint XXXX
|
|
||||||
*/
|
|
||||||
static std::string codepoint_to_string(int codepoint)
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << "U+" << std::setw(4) << std::uppercase << std::setfill('0') << std::hex << codepoint;
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief scan a string literal
|
@brief scan a string literal
|
||||||
|
|
||||||
|
@ -11497,9 +11486,7 @@ class basic_json
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// get next character
|
// get next character
|
||||||
get();
|
switch (get())
|
||||||
|
|
||||||
switch (current)
|
|
||||||
{
|
{
|
||||||
// end of file while parsing string
|
// end of file while parsing string
|
||||||
case std::char_traits<char>::eof():
|
case std::char_traits<char>::eof():
|
||||||
|
@ -12396,40 +12383,24 @@ scan_number_done:
|
||||||
return token_type::value_float;
|
return token_type::value_float;
|
||||||
}
|
}
|
||||||
|
|
||||||
token_type scan_true()
|
/*!
|
||||||
|
@param[in] literal_text the literal text to expect
|
||||||
|
@param[in] length the length of the passed literal text
|
||||||
|
@param[in] return_type the token type to return on success
|
||||||
|
*/
|
||||||
|
token_type scan_literal(const char* literal_text, const size_t length,
|
||||||
|
token_type return_type)
|
||||||
{
|
{
|
||||||
assert(current == 't');
|
assert(current == literal_text[0]);
|
||||||
if (JSON_LIKELY((get() == 'r' and get() == 'u' and get() == 'e')))
|
for (size_t i = 1; i < length; ++i)
|
||||||
{
|
{
|
||||||
return token_type::literal_true;
|
if (JSON_UNLIKELY(get() != literal_text[i]))
|
||||||
|
{
|
||||||
|
error_message = "invalid literal";
|
||||||
|
return token_type::parse_error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return return_type;
|
||||||
error_message = "invalid literal; expected 'true'";
|
|
||||||
return token_type::parse_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
token_type scan_false()
|
|
||||||
{
|
|
||||||
assert(current == 'f');
|
|
||||||
if (JSON_LIKELY((get() == 'a' and get() == 'l' and get() == 's' and get() == 'e')))
|
|
||||||
{
|
|
||||||
return token_type::literal_false;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_message = "invalid literal; expected 'false'";
|
|
||||||
return token_type::parse_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
token_type scan_null()
|
|
||||||
{
|
|
||||||
assert(current == 'n');
|
|
||||||
if (JSON_LIKELY((get() == 'u' and get() == 'l' and get() == 'l')))
|
|
||||||
{
|
|
||||||
return token_type::literal_null;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_message = "invalid literal; expected 'null'";
|
|
||||||
return token_type::parse_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
|
@ -12461,6 +12432,7 @@ scan_number_done:
|
||||||
{
|
{
|
||||||
yytext.resize(2 * yytext.capacity(), '\0');
|
yytext.resize(2 * yytext.capacity(), '\0');
|
||||||
}
|
}
|
||||||
|
assert(yylen < yytext.size());
|
||||||
yytext[yylen++] = static_cast<char>(c);
|
yytext[yylen++] = static_cast<char>(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12523,7 +12495,9 @@ scan_number_done:
|
||||||
else if ('\x00' <= c and c <= '\x1f')
|
else if ('\x00' <= c and c <= '\x1f')
|
||||||
{
|
{
|
||||||
// escape control characters
|
// escape control characters
|
||||||
result += "<" + codepoint_to_string(c) + ">";
|
std::stringstream ss;
|
||||||
|
ss << "<U+" << std::setw(4) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(c) << ">";
|
||||||
|
result += ss.str();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -12572,11 +12546,11 @@ scan_number_done:
|
||||||
|
|
||||||
// literals
|
// literals
|
||||||
case 't':
|
case 't':
|
||||||
return scan_true();
|
return scan_literal("true", 4, token_type::literal_true);
|
||||||
case 'f':
|
case 'f':
|
||||||
return scan_false();
|
return scan_literal("false", 5, token_type::literal_false);
|
||||||
case 'n':
|
case 'n':
|
||||||
return scan_null();
|
return scan_literal("null", 4, token_type::literal_null);
|
||||||
|
|
||||||
// string
|
// string
|
||||||
case '\"':
|
case '\"':
|
||||||
|
|
|
@ -338,7 +338,7 @@ TEST_CASE("parser class")
|
||||||
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("-0e-:"))).parse(),
|
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("-0e-:"))).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 5: syntax error - invalid number; expected digit after exponent sign; last read: '-0e-:'");
|
"[json.exception.parse_error.101] parse error at 5: syntax error - invalid number; expected digit after exponent sign; last read: '-0e-:'");
|
||||||
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("-0f"))).parse(),
|
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("-0f"))).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; expected 'false'; last read: '-0f'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: '-0f'; expected end of input");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -656,22 +656,22 @@ TEST_CASE("parser class")
|
||||||
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("nu"))).parse(), json::parse_error);
|
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("nu"))).parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("nul"))).parse(), json::parse_error);
|
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("nul"))).parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("n"))).parse(),
|
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("n"))).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; expected 'null'; last read: 'n'");
|
"[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 'n'");
|
||||||
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("nu"))).parse(),
|
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("nu"))).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; expected 'null'; last read: 'nu'");
|
"[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; last read: 'nu'");
|
||||||
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("nul"))).parse(),
|
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("nul"))).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; expected 'null'; last read: 'nul'");
|
"[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'nul'");
|
||||||
|
|
||||||
// unexpected end of true
|
// unexpected end of true
|
||||||
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("t"))).parse(), json::parse_error);
|
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("t"))).parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("tr"))).parse(), json::parse_error);
|
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("tr"))).parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("tru"))).parse(), json::parse_error);
|
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("tru"))).parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("t"))).parse(),
|
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("t"))).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; expected 'true'; last read: 't'");
|
"[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 't'");
|
||||||
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("tr"))).parse(),
|
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("tr"))).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; expected 'true'; last read: 'tr'");
|
"[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; last read: 'tr'");
|
||||||
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("tru"))).parse(),
|
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("tru"))).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; expected 'true'; last read: 'tru'");
|
"[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'tru'");
|
||||||
|
|
||||||
// unexpected end of false
|
// unexpected end of false
|
||||||
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("f"))).parse(), json::parse_error);
|
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("f"))).parse(), json::parse_error);
|
||||||
|
@ -679,13 +679,13 @@ TEST_CASE("parser class")
|
||||||
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("fal"))).parse(), json::parse_error);
|
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("fal"))).parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("fals"))).parse(), json::parse_error);
|
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("fals"))).parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("f"))).parse(),
|
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("f"))).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; expected 'false'; last read: 'f'");
|
"[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 'f'");
|
||||||
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("fa"))).parse(),
|
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("fa"))).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; expected 'false'; last read: 'fa'");
|
"[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; last read: 'fa'");
|
||||||
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("fal"))).parse(),
|
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("fal"))).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; expected 'false'; last read: 'fal'");
|
"[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'fal'");
|
||||||
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("fals"))).parse(),
|
CHECK_THROWS_WITH(json::parser(json::input_adapter::create(std::string("fals"))).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; expected 'false'; last read: 'fals'");
|
"[json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; last read: 'fals'");
|
||||||
|
|
||||||
// missing/unexpected end of array
|
// missing/unexpected end of array
|
||||||
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("["))).parse(), json::parse_error);
|
CHECK_THROWS_AS(json::parser(json::input_adapter::create(std::string("["))).parse(), json::parse_error);
|
||||||
|
|
Loading…
Reference in a new issue