diff --git a/src/test.cpp b/src/test.cpp index d044ebd..d6beddc 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -420,10 +420,10 @@ struct Parser2 { // Returns false to reject [[nodiscard]] bool parse() { - if (!push({N_VALUE})) { + if (push({N_VALUE}) != S_OK) { return false; } - return keepGoing(this); + return keepGoing(this) == S_OK; } Parser2(Parser2 const &) = delete; @@ -433,6 +433,13 @@ struct Parser2 { static constexpr int kMaxStackSize = 1 << 10; + enum Status { + S_OK, + S_AGAIN, + S_REJECT, + S_OVERFLOW, + }; + private: // Helpers void maybeSkipWs() { @@ -440,21 +447,21 @@ private: ++buf; } } - bool parseLiteral(const char *literal) { + Status parseLiteral(const char *literal) { const int litLen = strlen(literal); if (len() < litLen) { - return false; + return S_REJECT; } if (memcmp(buf, literal, litLen) == 0) { buf += litLen; - return true; + return S_OK; } - return false; + return S_REJECT; } - bool parse_number() { + Status parse_number() { char *const bufBefore = buf; if (len() == 0 || !('0' <= *buf && *buf <= '9' || (*buf == '.'))) { - return false; + return S_REJECT; } callbacks->on_begin_number(data); ++buf; @@ -467,28 +474,28 @@ private: } callbacks->on_number_data(data, bufBefore, buf - bufBefore); callbacks->on_end_number(data); - return true; + return S_OK; } - bool parse_string() { - if (!parseLiteral("\"")) { - return false; + Status parse_string() { + if (Status s = parseLiteral("\"")) { + return s; } callbacks->on_begin_string(data); auto *result = (char *)memchr(buf, '"', len()); if (result == nullptr) { - return false; + return S_REJECT; } int stringLen = result - buf; callbacks->on_string_data(data, buf, stringLen); buf += stringLen; - if (!parseLiteral("\"")) { - return false; + if (Status s = parseLiteral("\"")) { + return s; } callbacks->on_end_string(data); - return true; + return S_OK; } - typedef bool (*continuation)(Parser2 *); + typedef Status (*continuation)(Parser2 *); [[maybe_unused]] void debugPrint() { for (int i = 0; i < stackPtr - stack; ++i) { @@ -497,120 +504,122 @@ private: printf("\n"); } - static bool keepGoing(Parser2 *self) { + static Status keepGoing(Parser2 *self) { // self->debugPrint(); if (self->empty()) { - return true; + return S_OK; } auto top = *(self->stackPtr - 1); self->maybeSkipWs(); MUSTTAIL return table[top](self); } - static bool string(Parser2 *self) { - if (!self->parse_string()) { - return false; + static Status string(Parser2 *self) { + if (Status s = self->parse_string()) { + return s; } self->pop(); MUSTTAIL return keepGoing(self); } - static bool colon(Parser2 *self) { - if (!self->parseLiteral(":")) { - return false; + static Status colon(Parser2 *self) { + if (Status s = self->parseLiteral(":")) { + return s; } self->pop(); MUSTTAIL return keepGoing(self); } - static bool value(Parser2 *self) { - if (self->parse_string()) { + static Status value(Parser2 *self) { + if (self->parse_string() == S_OK) { self->pop(); MUSTTAIL return keepGoing(self); - } else if (self->parse_number()) { + } else if (self->parse_number() == S_OK) { self->pop(); MUSTTAIL return keepGoing(self); - } else if (self->parseLiteral("{")) { + } else if (self->parseLiteral("{") == S_OK) { self->pop(); self->callbacks->on_begin_object(self->data); - if (!self->push({N_OBJECT_VALUE_OR_END})) { - return false; + if (Status s = self->push({N_OBJECT_VALUE_OR_END})) { + return s; } MUSTTAIL return keepGoing(self); - } else if (self->parseLiteral("[")) { + } else if (self->parseLiteral("[") == S_OK) { self->pop(); self->callbacks->on_begin_array(self->data); - if (!self->push({N_ARRAY_VALUE_OR_END})) { - return false; + if (Status s = self->push({N_ARRAY_VALUE_OR_END})) { + return s; } MUSTTAIL return keepGoing(self); - } else if (self->parseLiteral("true")) { + } else if (self->parseLiteral("true") == S_OK) { self->pop(); self->callbacks->on_true_literal(self->data); MUSTTAIL return keepGoing(self); - } else if (self->parseLiteral("false")) { + } else if (self->parseLiteral("false") == S_OK) { self->pop(); self->callbacks->on_false_literal(self->data); MUSTTAIL return keepGoing(self); - } else if (self->parseLiteral("null")) { + } else if (self->parseLiteral("null") == S_OK) { self->pop(); self->callbacks->on_null_literal(self->data); MUSTTAIL return keepGoing(self); } - return false; + return S_REJECT; } - static bool arrayOrEnd(Parser2 *self) { - if (self->parseLiteral("]")) { + static Status arrayOrEnd(Parser2 *self) { + if (self->parseLiteral("]") == S_OK) { self->pop(); self->callbacks->on_end_array(self->data); MUSTTAIL return keepGoing(self); } else { self->pop(); - if (!self->push({N_VALUE, N_ARRAY_MAYBE_CONTINUE})) { - return false; + if (Status s = self->push({N_VALUE, N_ARRAY_MAYBE_CONTINUE})) { + return s; } MUSTTAIL return keepGoing(self); } } - static bool objectOrEnd(Parser2 *self) { - if (self->parseLiteral("}")) { + static Status objectOrEnd(Parser2 *self) { + if (self->parseLiteral("}") == S_OK) { self->pop(); self->callbacks->on_end_object(self->data); MUSTTAIL return keepGoing(self); } else { self->pop(); - if (!self->push({T_STRING, T_COLON, N_VALUE, N_OBJECT_MAYBE_CONTINUE})) { - return false; + if (Status s = self->push( + {T_STRING, T_COLON, N_VALUE, N_OBJECT_MAYBE_CONTINUE})) { + return s; } MUSTTAIL return keepGoing(self); } - return false; + return S_REJECT; } - static bool arrayContinue(Parser2 *self) { - if (self->parseLiteral(",")) { + static Status arrayContinue(Parser2 *self) { + if (self->parseLiteral(",") == S_OK) { self->pop(); - if (!self->push({N_VALUE, N_ARRAY_MAYBE_CONTINUE})) { - return false; + if (Status s = self->push({N_VALUE, N_ARRAY_MAYBE_CONTINUE})) { + return s; } MUSTTAIL return keepGoing(self); - } else if (self->parseLiteral("]")) { + } else if (self->parseLiteral("]") == S_OK) { self->pop(); self->callbacks->on_end_array(self->data); MUSTTAIL return keepGoing(self); } - return false; + return S_REJECT; } - static bool objectContinue(Parser2 *self) { - if (self->parseLiteral(",")) { + static Status objectContinue(Parser2 *self) { + if (self->parseLiteral(",") == S_OK) { self->pop(); - if (!self->push({T_STRING, T_COLON, N_VALUE, N_OBJECT_MAYBE_CONTINUE})) { - return false; + if (Status s = self->push( + {T_STRING, T_COLON, N_VALUE, N_OBJECT_MAYBE_CONTINUE})) { + return s; } MUSTTAIL return keepGoing(self); - } else if (self->parseLiteral("}")) { + } else if (self->parseLiteral("}") == S_OK) { self->pop(); self->callbacks->on_end_object(self->data); MUSTTAIL return keepGoing(self); } - return false; + return S_REJECT; } static constexpr continuation table[N_PAST_END] = { @@ -635,14 +644,14 @@ private: assert(!empty()); --stackPtr; } - [[nodiscard]] bool push(std::initializer_list symbols) { + [[nodiscard]] Status push(std::initializer_list symbols) { if (stackPtr >= std::end(stack) - symbols.size()) [[unlikely]] { - return false; + return S_OVERFLOW; } for (int i = symbols.size() - 1; i >= 0; --i) { *stackPtr++ = *(symbols.begin() + i); } - return true; + return S_OK; } };