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
[[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<Symbol> symbols) {
[[nodiscard]] Status push(std::initializer_list<Symbol> 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;
}
};