Return Status instead of bool

This commit is contained in:
2025-05-14 20:38:01 -04:00
parent adbdae5730
commit 8720220303

View File

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