Return Status instead of bool
This commit is contained in:
133
src/test.cpp
133
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<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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user