Commit c816fd12 by Niels

cleanup

parent d609790f
...@@ -2415,6 +2415,41 @@ class basic_json ...@@ -2415,6 +2415,41 @@ class basic_json
inline lexer() = default; inline lexer() = default;
inline static std::string token_type_name(token_type t)
{
switch (t)
{
case (token_type::uninitialized):
return "<uninitialized>";
case (token_type::literal_true):
return "true literal";
case (token_type::literal_false):
return "false literal";
case (token_type::literal_null):
return "null literal";
case (token_type::value_string):
return "string literal";
case (token_type::value_number):
return "number literal";
case (token_type::begin_array):
return "[";
case (token_type::begin_object):
return "{";
case (token_type::end_array):
return "]";
case (token_type::end_object):
return "}";
case (token_type::name_separator):
return ":";
case (token_type::value_separator):
return ",";
case (token_type::parse_error):
return "<parse error>";
case (token_type::end_of_input):
return "<end of input>";
}
}
/*! /*!
This function implements a scanner for JSON. It is specified using This function implements a scanner for JSON. It is specified using
regular expressions that try to follow RFC 7159 and ECMA-404 as close regular expressions that try to follow RFC 7159 and ECMA-404 as close
...@@ -2429,6 +2464,10 @@ class basic_json ...@@ -2429,6 +2464,10 @@ class basic_json
*/ */
inline token_type scan() inline token_type scan()
{ {
// pointer for backtracking information
const char* m_marker = nullptr;
// remember the begin of the token
m_start = m_cursor; m_start = m_cursor;
...@@ -2437,142 +2476,156 @@ class basic_json ...@@ -2437,142 +2476,156 @@ class basic_json
unsigned int yyaccept = 0; unsigned int yyaccept = 0;
static const unsigned char yybm[] = static const unsigned char yybm[] =
{ {
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 160, 160, 128, 128, 160, 128, 128, 64, 192, 192, 64, 64, 192, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
160, 128, 0, 128, 128, 128, 128, 128, 192, 64, 0, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
192, 192, 192, 192, 192, 192, 192, 192, 96, 96, 96, 96, 96, 96, 96, 96,
192, 192, 128, 128, 128, 128, 128, 128, 96, 96, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 0, 128, 128, 128, 64, 64, 64, 64, 0, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 64,
}; };
yych = *(m_marker = m_cursor); yych = *m_cursor;
if (yybm[0 + yych] & 32) if (yych <= '9')
{
goto json_parser_3;
}
if (yych <= '[')
{ {
if (yych <= '-') if (yych <= ' ')
{ {
if (yych <= '"') if (yych <= '\n')
{ {
if (yych <= 0x00) if (yych <= 0x00)
{ {
goto json_parser_28; goto json_parser_3;
} }
if (yych >= '"') if (yych <= 0x08)
{ {
goto json_parser_26; goto json_parser_5;
} }
goto json_parser_7;
} }
else else
{ {
if (yych <= '+') if (yych == '\r')
{ {
goto json_parser_2; goto json_parser_7;
} }
if (yych <= ',') if (yych <= 0x1F)
{ {
goto json_parser_13; goto json_parser_5;
} }
goto json_parser_21; goto json_parser_7;
} }
} }
else else
{ {
if (yych <= '9') if (yych <= ',')
{ {
if (yych <= '/') if (yych == '"')
{ {
goto json_parser_2; goto json_parser_8;
} }
if (yych <= '0') if (yych <= '+')
{ {
goto json_parser_22; goto json_parser_5;
} }
goto json_parser_24; goto json_parser_9;
} }
else else
{ {
if (yych <= ':') if (yych <= '-')
{ {
goto json_parser_15; goto json_parser_11;
} }
if (yych >= '[') if (yych <= '/')
{ {
goto json_parser_5; goto json_parser_5;
} }
if (yych <= '0')
{
goto json_parser_12;
}
goto json_parser_14;
} }
} }
} }
else else
{ {
if (yych <= 'n') if (yych <= 'm')
{ {
if (yych <= 'e') if (yych <= '\\')
{ {
if (yych == ']') if (yych <= ':')
{ {
goto json_parser_7; goto json_parser_15;
} }
if (yych == '[')
{
goto json_parser_17;
}
goto json_parser_5;
} }
else else
{ {
if (yych <= 'f') if (yych <= ']')
{ {
goto json_parser_20; goto json_parser_19;
} }
if (yych >= 'n') if (yych == 'f')
{ {
goto json_parser_17; goto json_parser_21;
} }
goto json_parser_5;
} }
} }
else else
{ {
if (yych <= 'z') if (yych <= 'z')
{ {
if (yych <= 'n')
{
goto json_parser_22;
}
if (yych == 't') if (yych == 't')
{ {
goto json_parser_19; goto json_parser_23;
} }
goto json_parser_5;
} }
else else
{ {
if (yych <= '{') if (yych <= '{')
{ {
goto json_parser_9; goto json_parser_24;
} }
if (yych == '}') if (yych == '}')
{ {
goto json_parser_11; goto json_parser_26;
} }
goto json_parser_5;
} }
} }
} }
...@@ -2582,158 +2635,330 @@ json_parser_2: ...@@ -2582,158 +2635,330 @@ json_parser_2:
} }
json_parser_3: json_parser_3:
++m_cursor; ++m_cursor;
yych = *m_cursor;
if (yybm[0 + yych] & 32)
{ {
goto json_parser_3; return token_type::end_of_input;
} }
goto json_parser_2;
json_parser_5: json_parser_5:
++m_cursor; ++m_cursor;
json_parser_6:
{ {
return token_type::begin_array; return token_type::parse_error;
} }
json_parser_7: json_parser_7:
++m_cursor; yych = *++m_cursor;
{ goto json_parser_62;
return token_type::end_array; json_parser_8:
} yyaccept = 0;
yych = *(m_marker = ++m_cursor);
goto json_parser_53;
json_parser_9: json_parser_9:
++m_cursor; ++m_cursor;
{ {
return token_type::begin_object; return token_type::value_separator;
} }
json_parser_11: json_parser_11:
++m_cursor; yych = *++m_cursor;
if (yych <= '/')
{ {
return token_type::end_object; goto json_parser_6;
}
if (yych <= '0')
{
goto json_parser_51;
}
if (yych <= '9')
{
goto json_parser_42;
}
goto json_parser_6;
json_parser_12:
yyaccept = 1;
yych = *(m_marker = ++m_cursor);
if (yych <= 'D')
{
if (yych == '.')
{
goto json_parser_44;
}
}
else
{
if (yych <= 'E')
{
goto json_parser_45;
}
if (yych == 'e')
{
goto json_parser_45;
}
} }
json_parser_13: json_parser_13:
++m_cursor;
{ {
return token_type::value_separator; return token_type::value_number;
} }
json_parser_14:
yyaccept = 1;
yych = *(m_marker = ++m_cursor);
goto json_parser_43;
json_parser_15: json_parser_15:
++m_cursor; ++m_cursor;
{ {
return token_type::name_separator; return token_type::name_separator;
} }
json_parser_17: json_parser_17:
++m_cursor;
{
return token_type::begin_array;
}
json_parser_19:
++m_cursor;
{
return token_type::end_array;
}
json_parser_21:
yyaccept = 0;
yych = *(m_marker = ++m_cursor);
if (yych == 'a')
{
goto json_parser_37;
}
goto json_parser_6;
json_parser_22:
yyaccept = 0;
yych = *(m_marker = ++m_cursor);
if (yych == 'u')
{
goto json_parser_33;
}
goto json_parser_6;
json_parser_23:
yyaccept = 0;
yych = *(m_marker = ++m_cursor);
if (yych == 'r')
{
goto json_parser_28;
}
goto json_parser_6;
json_parser_24:
++m_cursor;
{
return token_type::begin_object;
}
json_parser_26:
++m_cursor;
{
return token_type::end_object;
}
json_parser_28:
yych = *++m_cursor; yych = *++m_cursor;
if (yych == 'u') if (yych == 'u')
{ {
goto json_parser_53; goto json_parser_30;
} }
json_parser_18: json_parser_29:
m_cursor = m_marker; m_cursor = m_marker;
if (yyaccept == 0) if (yyaccept == 0)
{ {
goto json_parser_2; goto json_parser_6;
} }
else else
{ {
goto json_parser_23; goto json_parser_13;
} }
json_parser_19: json_parser_30:
yych = *++m_cursor; yych = *++m_cursor;
if (yych == 'r') if (yych != 'e')
{ {
goto json_parser_49; goto json_parser_29;
} }
goto json_parser_18; ++m_cursor;
json_parser_20: {
return token_type::literal_true;
}
json_parser_33:
yych = *++m_cursor; yych = *++m_cursor;
if (yych == 'a') if (yych != 'l')
{ {
goto json_parser_44; goto json_parser_29;
} }
goto json_parser_18;
json_parser_21:
yych = *++m_cursor; yych = *++m_cursor;
if (yych <= '/') if (yych != 'l')
{ {
goto json_parser_18; goto json_parser_29;
} }
if (yych <= '0') ++m_cursor;
{ {
goto json_parser_22; return token_type::literal_null;
} }
if (yych <= '9') json_parser_37:
yych = *++m_cursor;
if (yych != 'l')
{ {
goto json_parser_24; goto json_parser_29;
} }
goto json_parser_18; yych = *++m_cursor;
json_parser_22: if (yych != 's')
{
goto json_parser_29;
}
yych = *++m_cursor;
if (yych != 'e')
{
goto json_parser_29;
}
++m_cursor;
{
return token_type::literal_false;
}
json_parser_42:
yyaccept = 1; yyaccept = 1;
yych = *(m_marker = ++m_cursor); m_marker = ++m_cursor;
yych = *m_cursor;
json_parser_43:
if (yybm[0 + yych] & 32)
{
goto json_parser_42;
}
if (yych <= 'D') if (yych <= 'D')
{ {
if (yych == '.') if (yych != '.')
{ {
goto json_parser_37; goto json_parser_13;
} }
} }
else else
{ {
if (yych <= 'E') if (yych <= 'E')
{ {
goto json_parser_38; goto json_parser_45;
} }
if (yych == 'e') if (yych == 'e')
{ {
goto json_parser_38; goto json_parser_45;
} }
goto json_parser_13;
} }
json_parser_23: json_parser_44:
yych = *++m_cursor;
if (yych <= '/')
{ {
return token_type::value_number; goto json_parser_29;
} }
json_parser_24: if (yych <= '9')
{
goto json_parser_49;
}
goto json_parser_29;
json_parser_45:
yych = *++m_cursor;
if (yych <= ',')
{
if (yych != '+')
{
goto json_parser_29;
}
}
else
{
if (yych <= '-')
{
goto json_parser_46;
}
if (yych <= '/')
{
goto json_parser_29;
}
if (yych <= '9')
{
goto json_parser_47;
}
goto json_parser_29;
}
json_parser_46:
yych = *++m_cursor;
if (yych <= '/')
{
goto json_parser_29;
}
if (yych >= ':')
{
goto json_parser_29;
}
json_parser_47:
++m_cursor;
yych = *m_cursor;
if (yych <= '/')
{
goto json_parser_13;
}
if (yych <= '9')
{
goto json_parser_47;
}
goto json_parser_13;
json_parser_49:
yyaccept = 1; yyaccept = 1;
m_marker = ++m_cursor; m_marker = ++m_cursor;
yych = *m_cursor; yych = *m_cursor;
if (yybm[0 + yych] & 64) if (yych <= 'D')
{ {
goto json_parser_24; if (yych <= '/')
{
goto json_parser_13;
}
if (yych <= '9')
{
goto json_parser_49;
}
goto json_parser_13;
}
else
{
if (yych <= 'E')
{
goto json_parser_45;
} }
if (yych == 'e')
{
goto json_parser_45;
}
goto json_parser_13;
}
json_parser_51:
yyaccept = 1;
yych = *(m_marker = ++m_cursor);
if (yych <= 'D') if (yych <= 'D')
{ {
if (yych == '.') if (yych == '.')
{ {
goto json_parser_37; goto json_parser_44;
} }
goto json_parser_23; goto json_parser_13;
} }
else else
{ {
if (yych <= 'E') if (yych <= 'E')
{ {
goto json_parser_38; goto json_parser_45;
} }
if (yych == 'e') if (yych == 'e')
{ {
goto json_parser_38; goto json_parser_45;
} }
goto json_parser_23; goto json_parser_13;
} }
json_parser_26: json_parser_52:
++m_cursor; ++m_cursor;
yych = *m_cursor; yych = *m_cursor;
if (yybm[0 + yych] & 128) json_parser_53:
if (yybm[0 + yych] & 64)
{ {
goto json_parser_26; goto json_parser_52;
} }
if (yych <= '"') if (yych <= '"')
{ {
goto json_parser_31; goto json_parser_55;
} }
goto json_parser_30;
json_parser_28:
++m_cursor;
{
return token_type::end_of_input;
}
json_parser_30:
++m_cursor; ++m_cursor;
yych = *m_cursor; yych = *m_cursor;
if (yych <= 'e') if (yych <= 'e')
...@@ -2742,13 +2967,13 @@ json_parser_30: ...@@ -2742,13 +2967,13 @@ json_parser_30:
{ {
if (yych == '"') if (yych == '"')
{ {
goto json_parser_26; goto json_parser_52;
} }
if (yych <= '.') if (yych <= '.')
{ {
goto json_parser_18; goto json_parser_29;
} }
goto json_parser_26; goto json_parser_52;
} }
else else
{ {
...@@ -2756,17 +2981,17 @@ json_parser_30: ...@@ -2756,17 +2981,17 @@ json_parser_30:
{ {
if (yych <= '[') if (yych <= '[')
{ {
goto json_parser_18; goto json_parser_29;
} }
goto json_parser_26; goto json_parser_52;
} }
else else
{ {
if (yych == 'b') if (yych == 'b')
{ {
goto json_parser_26; goto json_parser_52;
} }
goto json_parser_18; goto json_parser_29;
} }
} }
} }
...@@ -2776,13 +3001,13 @@ json_parser_30: ...@@ -2776,13 +3001,13 @@ json_parser_30:
{ {
if (yych <= 'f') if (yych <= 'f')
{ {
goto json_parser_26; goto json_parser_52;
} }
if (yych == 'n') if (yych == 'n')
{ {
goto json_parser_26; goto json_parser_52;
} }
goto json_parser_18; goto json_parser_29;
} }
else else
{ {
...@@ -2790,283 +3015,156 @@ json_parser_30: ...@@ -2790,283 +3015,156 @@ json_parser_30:
{ {
if (yych <= 'r') if (yych <= 'r')
{ {
goto json_parser_26; goto json_parser_52;
} }
goto json_parser_18; goto json_parser_29;
} }
else else
{ {
if (yych <= 't') if (yych <= 't')
{ {
goto json_parser_26; goto json_parser_52;
} }
if (yych <= 'u') if (yych <= 'u')
{ {
goto json_parser_33; goto json_parser_57;
} }
goto json_parser_18; goto json_parser_29;
} }
} }
} }
json_parser_31: json_parser_55:
++m_cursor; ++m_cursor;
{ {
return token_type::value_string; return token_type::value_string;
} }
json_parser_33: json_parser_57:
++m_cursor; ++m_cursor;
yych = *m_cursor; yych = *m_cursor;
if (yych <= '@') if (yych <= '@')
{ {
if (yych <= '/') if (yych <= '/')
{ {
goto json_parser_18; goto json_parser_29;
} }
if (yych >= ':') if (yych >= ':')
{ {
goto json_parser_18; goto json_parser_29;
} }
} }
else else
{ {
if (yych <= 'F') if (yych <= 'F')
{ {
goto json_parser_34; goto json_parser_58;
} }
if (yych <= '`') if (yych <= '`')
{ {
goto json_parser_18; goto json_parser_29;
} }
if (yych >= 'g') if (yych >= 'g')
{ {
goto json_parser_18; goto json_parser_29;
} }
} }
json_parser_34: json_parser_58:
++m_cursor; ++m_cursor;
yych = *m_cursor; yych = *m_cursor;
if (yych <= '@') if (yych <= '@')
{ {
if (yych <= '/') if (yych <= '/')
{ {
goto json_parser_18; goto json_parser_29;
} }
if (yych >= ':') if (yych >= ':')
{ {
goto json_parser_18; goto json_parser_29;
} }
} }
else else
{ {
if (yych <= 'F') if (yych <= 'F')
{ {
goto json_parser_35; goto json_parser_59;
} }
if (yych <= '`') if (yych <= '`')
{ {
goto json_parser_18; goto json_parser_29;
} }
if (yych >= 'g') if (yych >= 'g')
{ {
goto json_parser_18; goto json_parser_29;
} }
} }
json_parser_35: json_parser_59:
++m_cursor; ++m_cursor;
yych = *m_cursor; yych = *m_cursor;
if (yych <= '@') if (yych <= '@')
{ {
if (yych <= '/') if (yych <= '/')
{ {
goto json_parser_18; goto json_parser_29;
} }
if (yych >= ':') if (yych >= ':')
{ {
goto json_parser_18; goto json_parser_29;
} }
} }
else else
{ {
if (yych <= 'F') if (yych <= 'F')
{ {
goto json_parser_36; goto json_parser_60;
} }
if (yych <= '`') if (yych <= '`')
{ {
goto json_parser_18; goto json_parser_29;
} }
if (yych >= 'g') if (yych >= 'g')
{ {
goto json_parser_18; goto json_parser_29;
} }
} }
json_parser_36: json_parser_60:
++m_cursor; ++m_cursor;
yych = *m_cursor; yych = *m_cursor;
if (yych <= '@') if (yych <= '@')
{ {
if (yych <= '/') if (yych <= '/')
{ {
goto json_parser_18; goto json_parser_29;
} }
if (yych <= '9') if (yych <= '9')
{ {
goto json_parser_26; goto json_parser_52;
} }
goto json_parser_18; goto json_parser_29;
} }
else else
{ {
if (yych <= 'F') if (yych <= 'F')
{ {
goto json_parser_26; goto json_parser_52;
} }
if (yych <= '`') if (yych <= '`')
{ {
goto json_parser_18; goto json_parser_29;
} }
if (yych <= 'f') if (yych <= 'f')
{ {
goto json_parser_26; goto json_parser_52;
}
goto json_parser_18;
}
json_parser_37:
yych = *++m_cursor;
if (yych <= '/')
{
goto json_parser_18;
}
if (yych <= '9')
{
goto json_parser_42;
}
goto json_parser_18;
json_parser_38:
yych = *++m_cursor;
if (yych <= ',')
{
if (yych != '+')
{
goto json_parser_18;
}
}
else
{
if (yych <= '-')
{
goto json_parser_39;
}
if (yych <= '/')
{
goto json_parser_18;
} }
if (yych <= '9') goto json_parser_29;
{
goto json_parser_40;
} }
goto json_parser_18; json_parser_61:
}
json_parser_39:
yych = *++m_cursor;
if (yych <= '/')
{
goto json_parser_18;
}
if (yych >= ':')
{
goto json_parser_18;
}
json_parser_40:
++m_cursor; ++m_cursor;
yych = *m_cursor; yych = *m_cursor;
if (yych <= '/') json_parser_62:
{ if (yybm[0 + yych] & 128)
goto json_parser_23;
}
if (yych <= '9')
{
goto json_parser_40;
}
goto json_parser_23;
json_parser_42:
yyaccept = 1;
m_marker = ++m_cursor;
yych = *m_cursor;
if (yych <= 'D')
{
if (yych <= '/')
{
goto json_parser_23;
}
if (yych <= '9')
{
goto json_parser_42;
}
goto json_parser_23;
}
else
{
if (yych <= 'E')
{
goto json_parser_38;
}
if (yych == 'e')
{
goto json_parser_38;
}
goto json_parser_23;
}
json_parser_44:
yych = *++m_cursor;
if (yych != 'l')
{
goto json_parser_18;
}
yych = *++m_cursor;
if (yych != 's')
{
goto json_parser_18;
}
yych = *++m_cursor;
if (yych != 'e')
{
goto json_parser_18;
}
++m_cursor;
{
return token_type::literal_false;
}
json_parser_49:
yych = *++m_cursor;
if (yych != 'u')
{
goto json_parser_18;
}
yych = *++m_cursor;
if (yych != 'e')
{
goto json_parser_18;
}
++m_cursor;
{
return token_type::literal_true;
}
json_parser_53:
yych = *++m_cursor;
if (yych != 'l')
{
goto json_parser_18;
}
yych = *++m_cursor;
if (yych != 'l')
{
goto json_parser_18;
}
++m_cursor;
{ {
return token_type::literal_null; goto json_parser_61;
} }
goto json_parser_2;
} }
} }
...@@ -3127,8 +3225,6 @@ json_parser_53: ...@@ -3127,8 +3225,6 @@ json_parser_53:
const char* m_cursor = nullptr; const char* m_cursor = nullptr;
/// pointer to the end of the buffer /// pointer to the end of the buffer
const char* m_limit = nullptr; const char* m_limit = nullptr;
/// pointer for backtracking information
const char* m_marker = nullptr;
}; };
class parser class parser
...@@ -3284,7 +3380,7 @@ json_parser_53: ...@@ -3284,7 +3380,7 @@ json_parser_53:
std::string error_msg = "parse error - unexpected \'"; std::string error_msg = "parse error - unexpected \'";
error_msg += m_lexer.get_string_value(); error_msg += m_lexer.get_string_value();
error_msg += "\' ("; error_msg += "\' (";
error_msg += token_type_name(last_token) + ")"; error_msg += lexer::token_type_name(last_token) + ")";
throw std::invalid_argument(error_msg); throw std::invalid_argument(error_msg);
} }
} }
...@@ -3298,49 +3394,14 @@ json_parser_53: ...@@ -3298,49 +3394,14 @@ json_parser_53:
return last_token; return last_token;
} }
inline static std::string token_type_name(typename lexer::token_type t)
{
switch (t)
{
case (lexer::token_type::uninitialized):
return "<uninitialized>";
case (lexer::token_type::literal_true):
return "true literal";
case (lexer::token_type::literal_false):
return "false literal";
case (lexer::token_type::literal_null):
return "null literal";
case (lexer::token_type::value_string):
return "string literal";
case (lexer::token_type::value_number):
return "number literal";
case (lexer::token_type::begin_array):
return "[";
case (lexer::token_type::begin_object):
return "{";
case (lexer::token_type::end_array):
return "]";
case (lexer::token_type::end_object):
return "}";
case (lexer::token_type::name_separator):
return ":";
case (lexer::token_type::value_separator):
return ",";
case (lexer::token_type::parse_error):
return "<parse error>";
case (lexer::token_type::end_of_input):
return "<end of input>";
}
}
inline void expect(typename lexer::token_type t) const inline void expect(typename lexer::token_type t) const
{ {
if (t != last_token) if (t != last_token)
{ {
std::string error_msg = "parse error - unexpected \'"; std::string error_msg = "parse error - unexpected \'";
error_msg += m_lexer.get_string_value(); error_msg += m_lexer.get_string_value();
error_msg += "\' (" + token_type_name(last_token); error_msg += "\' (" + lexer::token_type_name(last_token);
error_msg += "); expected " + token_type_name(t); error_msg += "); expected " + lexer::token_type_name(t);
throw std::invalid_argument(error_msg); throw std::invalid_argument(error_msg);
} }
} }
......
...@@ -2415,6 +2415,41 @@ class basic_json ...@@ -2415,6 +2415,41 @@ class basic_json
inline lexer() = default; inline lexer() = default;
inline static std::string token_type_name(token_type t)
{
switch (t)
{
case (token_type::uninitialized):
return "<uninitialized>";
case (token_type::literal_true):
return "true literal";
case (token_type::literal_false):
return "false literal";
case (token_type::literal_null):
return "null literal";
case (token_type::value_string):
return "string literal";
case (token_type::value_number):
return "number literal";
case (token_type::begin_array):
return "[";
case (token_type::begin_object):
return "{";
case (token_type::end_array):
return "]";
case (token_type::end_object):
return "}";
case (token_type::name_separator):
return ":";
case (token_type::value_separator):
return ",";
case (token_type::parse_error):
return "<parse error>";
case (token_type::end_of_input):
return "<end of input>";
}
}
/*! /*!
This function implements a scanner for JSON. It is specified using This function implements a scanner for JSON. It is specified using
regular expressions that try to follow RFC 7159 and ECMA-404 as close regular expressions that try to follow RFC 7159 and ECMA-404 as close
...@@ -2429,6 +2464,10 @@ class basic_json ...@@ -2429,6 +2464,10 @@ class basic_json
*/ */
inline token_type scan() inline token_type scan()
{ {
// pointer for backtracking information
const char* m_marker = nullptr;
// remember the begin of the token
m_start = m_cursor; m_start = m_cursor;
/*!re2c /*!re2c
...@@ -2483,6 +2522,9 @@ class basic_json ...@@ -2483,6 +2522,9 @@ class basic_json
// end of file // end of file
'\000' { return token_type::end_of_input; } '\000' { return token_type::end_of_input; }
// anything else is an error
* { return token_type::parse_error; }
*/ */
} }
...@@ -2542,8 +2584,6 @@ class basic_json ...@@ -2542,8 +2584,6 @@ class basic_json
const char* m_cursor = nullptr; const char* m_cursor = nullptr;
/// pointer to the end of the buffer /// pointer to the end of the buffer
const char* m_limit = nullptr; const char* m_limit = nullptr;
/// pointer for backtracking information
const char* m_marker = nullptr;
}; };
class parser class parser
...@@ -2699,7 +2739,7 @@ class basic_json ...@@ -2699,7 +2739,7 @@ class basic_json
std::string error_msg = "parse error - unexpected \'"; std::string error_msg = "parse error - unexpected \'";
error_msg += m_lexer.get_string_value(); error_msg += m_lexer.get_string_value();
error_msg += "\' ("; error_msg += "\' (";
error_msg += token_type_name(last_token) + ")"; error_msg += lexer::token_type_name(last_token) + ")";
throw std::invalid_argument(error_msg); throw std::invalid_argument(error_msg);
} }
} }
...@@ -2713,49 +2753,14 @@ class basic_json ...@@ -2713,49 +2753,14 @@ class basic_json
return last_token; return last_token;
} }
inline static std::string token_type_name(typename lexer::token_type t)
{
switch (t)
{
case (lexer::token_type::uninitialized):
return "<uninitialized>";
case (lexer::token_type::literal_true):
return "true literal";
case (lexer::token_type::literal_false):
return "false literal";
case (lexer::token_type::literal_null):
return "null literal";
case (lexer::token_type::value_string):
return "string literal";
case (lexer::token_type::value_number):
return "number literal";
case (lexer::token_type::begin_array):
return "[";
case (lexer::token_type::begin_object):
return "{";
case (lexer::token_type::end_array):
return "]";
case (lexer::token_type::end_object):
return "}";
case (lexer::token_type::name_separator):
return ":";
case (lexer::token_type::value_separator):
return ",";
case (lexer::token_type::parse_error):
return "<parse error>";
case (lexer::token_type::end_of_input):
return "<end of input>";
}
}
inline void expect(typename lexer::token_type t) const inline void expect(typename lexer::token_type t) const
{ {
if (t != last_token) if (t != last_token)
{ {
std::string error_msg = "parse error - unexpected \'"; std::string error_msg = "parse error - unexpected \'";
error_msg += m_lexer.get_string_value(); error_msg += m_lexer.get_string_value();
error_msg += "\' (" + token_type_name(last_token); error_msg += "\' (" + lexer::token_type_name(last_token);
error_msg += "); expected " + token_type_name(t); error_msg += "); expected " + lexer::token_type_name(t);
throw std::invalid_argument(error_msg); throw std::invalid_argument(error_msg);
} }
} }
......
...@@ -3974,50 +3974,75 @@ TEST_CASE("convenience functions") ...@@ -3974,50 +3974,75 @@ TEST_CASE("convenience functions")
} }
} }
TEST_CASE("parser class") TEST_CASE("lexer class")
{ {
SECTION("get_token") SECTION("scan")
{ {
SECTION("structural characters") SECTION("structural characters")
{ {
CHECK(json::parser("[").last_token == json::lexer::token_type::begin_array); CHECK(json::lexer("[").scan() == json::lexer::token_type::begin_array);
CHECK(json::parser("]").last_token == json::lexer::token_type::end_array); CHECK(json::lexer("]").scan() == json::lexer::token_type::end_array);
CHECK(json::parser("{").last_token == json::lexer::token_type::begin_object); CHECK(json::lexer("{").scan() == json::lexer::token_type::begin_object);
CHECK(json::parser("}").last_token == json::lexer::token_type::end_object); CHECK(json::lexer("}").scan() == json::lexer::token_type::end_object);
CHECK(json::parser(",").last_token == json::lexer::token_type::value_separator); CHECK(json::lexer(",").scan() == json::lexer::token_type::value_separator);
CHECK(json::parser(":").last_token == json::lexer::token_type::name_separator); CHECK(json::lexer(":").scan() == json::lexer::token_type::name_separator);
} }
SECTION("literal names") SECTION("literal names")
{ {
CHECK(json::parser("null").last_token == json::lexer::token_type::literal_null); CHECK(json::lexer("null").scan() == json::lexer::token_type::literal_null);
CHECK(json::parser("true").last_token == json::lexer::token_type::literal_true); CHECK(json::lexer("true").scan() == json::lexer::token_type::literal_true);
CHECK(json::parser("false").last_token == json::lexer::token_type::literal_false); CHECK(json::lexer("false").scan() == json::lexer::token_type::literal_false);
} }
SECTION("numbers") SECTION("numbers")
{ {
CHECK(json::parser("0").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("0").scan() == json::lexer::token_type::value_number);
CHECK(json::parser("1").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("1").scan() == json::lexer::token_type::value_number);
CHECK(json::parser("2").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("2").scan() == json::lexer::token_type::value_number);
CHECK(json::parser("3").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("3").scan() == json::lexer::token_type::value_number);
CHECK(json::parser("4").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("4").scan() == json::lexer::token_type::value_number);
CHECK(json::parser("5").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("5").scan() == json::lexer::token_type::value_number);
CHECK(json::parser("6").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("6").scan() == json::lexer::token_type::value_number);
CHECK(json::parser("7").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("7").scan() == json::lexer::token_type::value_number);
CHECK(json::parser("8").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("8").scan() == json::lexer::token_type::value_number);
CHECK(json::parser("9").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("9").scan() == json::lexer::token_type::value_number);
} }
SECTION("whitespace") SECTION("whitespace")
{ {
CHECK(json::parser(" 0").last_token == json::lexer::token_type::value_number); // result is end_of_input, because not token is following
CHECK(json::parser("\t0").last_token == json::lexer::token_type::value_number); CHECK(json::lexer(" ").scan() == json::lexer::token_type::end_of_input);
CHECK(json::parser("\n0").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("\t").scan() == json::lexer::token_type::end_of_input);
CHECK(json::parser("\r0").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("\n").scan() == json::lexer::token_type::end_of_input);
CHECK(json::parser(" \t\n\r\n\t 0").last_token == json::lexer::token_type::value_number); CHECK(json::lexer("\r").scan() == json::lexer::token_type::end_of_input);
CHECK(json::lexer(" \t\n\r\n\t ").scan() == json::lexer::token_type::end_of_input);
}
}
SECTION("token_type_name")
{
CHECK(json::lexer::token_type_name(json::lexer::token_type::uninitialized) == "<uninitialized>");
CHECK(json::lexer::token_type_name(json::lexer::token_type::literal_true) == "true literal");
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::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) == "]");
CHECK(json::lexer::token_type_name(json::lexer::token_type::end_object) == "}");
CHECK(json::lexer::token_type_name(json::lexer::token_type::name_separator) == ":");
CHECK(json::lexer::token_type_name(json::lexer::token_type::value_separator) == ",");
CHECK(json::lexer::token_type_name(json::lexer::token_type::parse_error) == "<parse error>");
CHECK(json::lexer::token_type_name(json::lexer::token_type::end_of_input) == "<end of input>");
} }
}
TEST_CASE("parser class")
{
SECTION("get_token")
{
/* /*
SECTION("parse errors on first character") SECTION("parse errors on first character")
{ {
...@@ -4090,22 +4115,4 @@ TEST_CASE("parser class") ...@@ -4090,22 +4115,4 @@ TEST_CASE("parser class")
CHECK(json::parser("false").parse() == json(false)); CHECK(json::parser("false").parse() == json(false));
} }
} }
SECTION("token_type_name")
{
CHECK(json::parser::token_type_name(json::lexer::token_type::uninitialized) == "<uninitialized>");
CHECK(json::parser::token_type_name(json::lexer::token_type::literal_true) == "true literal");
CHECK(json::parser::token_type_name(json::lexer::token_type::literal_false) == "false literal");
CHECK(json::parser::token_type_name(json::lexer::token_type::literal_null) == "null literal");
CHECK(json::parser::token_type_name(json::lexer::token_type::value_string) == "string literal");
CHECK(json::parser::token_type_name(json::lexer::token_type::value_number) == "number literal");
CHECK(json::parser::token_type_name(json::lexer::token_type::begin_array) == "[");
CHECK(json::parser::token_type_name(json::lexer::token_type::begin_object) == "{");
CHECK(json::parser::token_type_name(json::lexer::token_type::end_array) == "]");
CHECK(json::parser::token_type_name(json::lexer::token_type::end_object) == "}");
CHECK(json::parser::token_type_name(json::lexer::token_type::name_separator) == ":");
CHECK(json::parser::token_type_name(json::lexer::token_type::value_separator) == ",");
CHECK(json::parser::token_type_name(json::lexer::token_type::parse_error) == "<parse error>");
CHECK(json::parser::token_type_name(json::lexer::token_type::end_of_input) == "<end of input>");
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment