Add basic error handling.
This commit is contained in:
parent
91aaa346e4
commit
f6235b2160
@ -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
|
// current state x one lookahead token -> new state
|
||||||
static const IterativeParsingState G[cIterativeParsingStateCount][cIterativeParsingTokenCount] = {
|
static const IterativeParsingState G[cIterativeParsingStateCount][cIterativeParsingTokenCount] = {
|
||||||
// Start
|
// 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().
|
// 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.
|
// May return a new state on state pop.
|
||||||
template <unsigned parseFlags, typename InputStream, typename Handler>
|
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;
|
int c = 0;
|
||||||
IterativeParsingState n;
|
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>
|
template <unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
bool IterativeParse(InputStream& is, Handler& handler) {
|
bool IterativeParse(InputStream& is, Handler& handler) {
|
||||||
IterativeParsingState state = IterativeParsingStartState;
|
IterativeParsingState state = IterativeParsingStartState;
|
||||||
@ -1094,16 +1123,22 @@ private:
|
|||||||
SkipWhitespace(is);
|
SkipWhitespace(is);
|
||||||
while (is.Peek() != '\0') {
|
while (is.Peek() != '\0') {
|
||||||
IterativeParsingToken t = GuessToken(is.Peek());
|
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)
|
if (d == IterativeParsingErrorState) {
|
||||||
state = n;
|
HandleError(state, is);
|
||||||
else
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = d;
|
||||||
SkipWhitespace(is);
|
SkipWhitespace(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle the end of file.
|
||||||
|
if (state != IterativeParsingFinishState)
|
||||||
|
HandleError(state, is);
|
||||||
|
|
||||||
stack_.Clear();
|
stack_.Clear();
|
||||||
return state == IterativeParsingFinishState;
|
return state == IterativeParsingFinishState;
|
||||||
}
|
}
|
||||||
|
@ -706,6 +706,30 @@ TEST(Reader, Parse_IStreamWrapper_StringStream) {
|
|||||||
EXPECT_FALSE(reader.HasParseError());
|
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__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user