Commit f6235b21 authored by thebusytypist's avatar thebusytypist

Add basic error handling.

parent 91aaa346
......@@ -813,7 +813,7 @@ private:
}
}
IterativeParsingState Transit(IterativeParsingState state, IterativeParsingToken token) {
IterativeParsingState Deduce(IterativeParsingState state, IterativeParsingToken token) {
// current state x one lookahead token -> new state
static const IterativeParsingState G[cIterativeParsingStateCount][cIterativeParsingTokenCount] = {
// Start
......@@ -974,7 +974,7 @@ private:
// Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
// May return a new state on state pop.
template <unsigned parseFlags, typename InputStream, typename Handler>
IterativeParsingState Advance(IterativeParsingState src, IterativeParsingToken token, IterativeParsingState dst, InputStream& is, Handler& handler) {
IterativeParsingState Transit(IterativeParsingState src, IterativeParsingToken token, IterativeParsingState dst, InputStream& is, Handler& handler) {
int c = 0;
IterativeParsingState n;
......@@ -1087,6 +1087,35 @@ private:
}
}
template <typename InputStream>
void HandleError(IterativeParsingState src, InputStream& is) {
if (HasParseError()) {
// Error flag has been set.
return;
}
if (src == IterativeParsingStartState && is.Peek() == '\0')
RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell());
else if (src == IterativeParsingStartState)
RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotObjectOrArray, is.Tell());
else if (src == IterativeParsingFinishState)
RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell());
else if (src == IterativeParsingObjectInitialState || src == IterativeParsingMemberDelimiterState)
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
else if (src == IterativeParsingMemberKeyState)
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
else if (src == IterativeParsingMemberValueState)
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
else if (src == IterativeParsingElementState)
RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
}
template <unsigned parseFlags, typename InputStream, typename Handler>
bool IterativeParse(InputStream& is, Handler& handler) {
IterativeParsingState state = IterativeParsingStartState;
......@@ -1094,16 +1123,22 @@ private:
SkipWhitespace(is);
while (is.Peek() != '\0') {
IterativeParsingToken t = GuessToken(is.Peek());
IterativeParsingState n = Transit(state, t);
IterativeParsingState n = Deduce(state, t);
IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
if ((n = Advance<parseFlags>(state, t, n, is, handler)) != IterativeParsingErrorState)
state = n;
else
if (d == IterativeParsingErrorState) {
HandleError(state, is);
break;
}
state = d;
SkipWhitespace(is);
}
// Handle the end of file.
if (state != IterativeParsingFinishState)
HandleError(state, is);
stack_.Clear();
return state == IterativeParsingFinishState;
}
......
......@@ -706,6 +706,30 @@ TEST(Reader, Parse_IStreamWrapper_StringStream) {
EXPECT_FALSE(reader.HasParseError());
}
#define TESTERRORHANDLING(text, errorCode)\
{\
StringStream json(text);\
BaseReaderHandler<> handler;\
Reader reader;\
reader.IterativeParse<kParseDefaultFlags>(json, handler);\
EXPECT_TRUE(reader.HasParseError());\
EXPECT_EQ(errorCode, reader.GetParseErrorCode());\
}
TEST(Reader, IterativeParsing_ErrorHandling) {
TESTERRORHANDLING("{\"a\": a}", kParseErrorValueInvalid);
TESTERRORHANDLING("", kParseErrorDocumentEmpty);
TESTERRORHANDLING("1", kParseErrorDocumentRootNotObjectOrArray);
TESTERRORHANDLING("{}{}", kParseErrorDocumentRootNotSingular);
TESTERRORHANDLING("{1}", kParseErrorObjectMissName);
TESTERRORHANDLING("{\"a\", 1}", kParseErrorObjectMissColon);
TESTERRORHANDLING("{\"a\"}", kParseErrorObjectMissColon);
TESTERRORHANDLING("{\"a\": 1", kParseErrorObjectMissCommaOrCurlyBracket);
TESTERRORHANDLING("[1 2 3]", kParseErrorArrayMissCommaOrSquareBracket);
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
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