🔨 using a vector<bool> for the parser hierarchy

parent 5f723bbe
...@@ -162,10 +162,9 @@ class parser ...@@ -162,10 +162,9 @@ class parser
private: private:
bool sax_parse_internal(json_sax_t* sax) bool sax_parse_internal(json_sax_t* sax)
{ {
// two values for the structured values
enum class parse_state_t { array_value, object_value };
// stack to remember the hieararchy of structured values we are parsing // stack to remember the hieararchy of structured values we are parsing
std::vector<parse_state_t> states; // true = array; false = object
std::vector<bool> states;
// value to avoid a goto (see comment where set to true) // value to avoid a goto (see comment where set to true)
bool skip_to_state_evaluation = false; bool skip_to_state_evaluation = false;
...@@ -221,7 +220,7 @@ class parser ...@@ -221,7 +220,7 @@ class parser
} }
// remember we are now inside an object // remember we are now inside an object
states.push_back(parse_state_t::object_value); states.push_back(false);
// parse values // parse values
get_token(); get_token();
...@@ -249,7 +248,7 @@ class parser ...@@ -249,7 +248,7 @@ class parser
} }
// remember we are now inside an array // remember we are now inside an array
states.push_back(parse_state_t::array_value); states.push_back(true);
// parse values (no need to call get_token) // parse values (no need to call get_token)
continue; continue;
...@@ -359,104 +358,98 @@ class parser ...@@ -359,104 +358,98 @@ class parser
else else
{ {
get_token(); get_token();
switch (states.back()) if (states.back()) // array
{ {
case parse_state_t::array_value: // comma -> next value
if (last_token == token_type::value_separator)
{ {
// comma -> next value // parse a new value
if (last_token == token_type::value_separator) get_token();
continue;
}
// closing ]
if (JSON_LIKELY(last_token == token_type::end_array))
{
if (JSON_UNLIKELY(not sax->end_array()))
{ {
// parse a new value return false;
get_token();
continue;
} }
// closing ] // We are done with this array. Before we can parse a
if (JSON_LIKELY(last_token == token_type::end_array)) // new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
assert(not states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
else
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
}
}
else // object
{
// comma -> next value
if (last_token == token_type::value_separator)
{
get_token();
// parse key
if (JSON_UNLIKELY(last_token != token_type::value_string))
{ {
if (JSON_UNLIKELY(not sax->end_array())) return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
}
else
{
if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
{ {
return false; return false;
} }
// We are done with this array. Before we can parse
// a new value, we need to evaluate the new state
// first. By setting skip_to_state_evaluation to
// false, we are effectively jumping to the
// beginning of this switch.
assert(not states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
} }
else
// parse separator (:)
get_token();
if (JSON_UNLIKELY(last_token != token_type::name_separator))
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array))); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
} }
// parse values
get_token();
continue;
} }
case parse_state_t::object_value: // closing }
if (JSON_LIKELY(last_token == token_type::end_object))
{ {
// comma -> next value if (JSON_UNLIKELY(not sax->end_object()))
if (last_token == token_type::value_separator)
{ {
get_token(); return false;
// parse key
if (JSON_UNLIKELY(last_token != token_type::value_string))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
}
else
{
if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
{
return false;
}
}
// parse separator (:)
get_token();
if (JSON_UNLIKELY(last_token != token_type::name_separator))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
}
// parse values
get_token();
continue;
} }
// closing } // We are done with this object. Before we can parse a
if (JSON_LIKELY(last_token == token_type::end_object)) // new value, we need to evaluate the new state first.
{ // By setting skip_to_state_evaluation to false, we
if (JSON_UNLIKELY(not sax->end_object())) // are effectively jumping to the beginning of this if.
{ assert(not states.empty());
return false; states.pop_back();
} skip_to_state_evaluation = true;
continue;
// We are done with this object. Before we can }
// parse a new value, we need to evaluate the new else
// state first. By setting skip_to_state_evaluation {
// to false, we are effectively jumping to the return sax->parse_error(m_lexer.get_position(),
// beginning of this switch. m_lexer.get_token_string(),
assert(not states.empty()); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
else
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
}
} }
} }
} }
......
...@@ -3955,10 +3955,9 @@ class parser ...@@ -3955,10 +3955,9 @@ class parser
private: private:
bool sax_parse_internal(json_sax_t* sax) bool sax_parse_internal(json_sax_t* sax)
{ {
// two values for the structured values
enum class parse_state_t { array_value, object_value };
// stack to remember the hieararchy of structured values we are parsing // stack to remember the hieararchy of structured values we are parsing
std::vector<parse_state_t> states; // true = array; false = object
std::vector<bool> states;
// value to avoid a goto (see comment where set to true) // value to avoid a goto (see comment where set to true)
bool skip_to_state_evaluation = false; bool skip_to_state_evaluation = false;
...@@ -4014,7 +4013,7 @@ class parser ...@@ -4014,7 +4013,7 @@ class parser
} }
// remember we are now inside an object // remember we are now inside an object
states.push_back(parse_state_t::object_value); states.push_back(false);
// parse values // parse values
get_token(); get_token();
...@@ -4042,7 +4041,7 @@ class parser ...@@ -4042,7 +4041,7 @@ class parser
} }
// remember we are now inside an array // remember we are now inside an array
states.push_back(parse_state_t::array_value); states.push_back(true);
// parse values (no need to call get_token) // parse values (no need to call get_token)
continue; continue;
...@@ -4152,104 +4151,98 @@ class parser ...@@ -4152,104 +4151,98 @@ class parser
else else
{ {
get_token(); get_token();
switch (states.back()) if (states.back()) // array
{ {
case parse_state_t::array_value: // comma -> next value
if (last_token == token_type::value_separator)
{ {
// comma -> next value // parse a new value
if (last_token == token_type::value_separator) get_token();
continue;
}
// closing ]
if (JSON_LIKELY(last_token == token_type::end_array))
{
if (JSON_UNLIKELY(not sax->end_array()))
{ {
// parse a new value return false;
get_token();
continue;
} }
// closing ] // We are done with this array. Before we can parse a
if (JSON_LIKELY(last_token == token_type::end_array)) // new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
assert(not states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
else
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
}
}
else // object
{
// comma -> next value
if (last_token == token_type::value_separator)
{
get_token();
// parse key
if (JSON_UNLIKELY(last_token != token_type::value_string))
{ {
if (JSON_UNLIKELY(not sax->end_array())) return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
}
else
{
if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
{ {
return false; return false;
} }
// We are done with this array. Before we can parse
// a new value, we need to evaluate the new state
// first. By setting skip_to_state_evaluation to
// false, we are effectively jumping to the
// beginning of this switch.
assert(not states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
} }
else
// parse separator (:)
get_token();
if (JSON_UNLIKELY(last_token != token_type::name_separator))
{ {
return sax->parse_error(m_lexer.get_position(), return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(), m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array))); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
} }
// parse values
get_token();
continue;
} }
case parse_state_t::object_value: // closing }
if (JSON_LIKELY(last_token == token_type::end_object))
{ {
// comma -> next value if (JSON_UNLIKELY(not sax->end_object()))
if (last_token == token_type::value_separator)
{ {
get_token(); return false;
// parse key
if (JSON_UNLIKELY(last_token != token_type::value_string))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
}
else
{
if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
{
return false;
}
}
// parse separator (:)
get_token();
if (JSON_UNLIKELY(last_token != token_type::name_separator))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
}
// parse values
get_token();
continue;
} }
// closing } // We are done with this object. Before we can parse a
if (JSON_LIKELY(last_token == token_type::end_object)) // new value, we need to evaluate the new state first.
{ // By setting skip_to_state_evaluation to false, we
if (JSON_UNLIKELY(not sax->end_object())) // are effectively jumping to the beginning of this if.
{ assert(not states.empty());
return false; states.pop_back();
} skip_to_state_evaluation = true;
continue;
// We are done with this object. Before we can }
// parse a new value, we need to evaluate the new else
// state first. By setting skip_to_state_evaluation {
// to false, we are effectively jumping to the return sax->parse_error(m_lexer.get_position(),
// beginning of this switch. m_lexer.get_token_string(),
assert(not states.empty()); parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
else
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
}
} }
} }
} }
......
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