Use recursion for reading lists
This commit is contained in:
parent
8f10ca2b50
commit
8515d45b1e
3 changed files with 49 additions and 38 deletions
|
@ -88,14 +88,7 @@ Result<Value> Reader::read_multiple() {
|
||||||
return ERROR(ReadError);
|
return ERROR(ReadError);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> Reader::read_list() {
|
Result<Value> Reader::read_list_rec(SourcePosition& end) {
|
||||||
if (!match('(')) return ERROR(ReadError);
|
|
||||||
|
|
||||||
forward();
|
|
||||||
|
|
||||||
Value res = TRY(Nil::create());
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
forward_whitespace();
|
forward_whitespace();
|
||||||
|
|
||||||
if (is_eof()) {
|
if (is_eof()) {
|
||||||
|
@ -104,15 +97,27 @@ Result<Value> Reader::read_list() {
|
||||||
|
|
||||||
if (match(')')) {
|
if (match(')')) {
|
||||||
forward();
|
forward();
|
||||||
return reverse(res);
|
end = position_;
|
||||||
|
return Value(TRY(Nil::create()));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto val = TRY(read_one());
|
auto val = TRY(read_one());
|
||||||
|
auto rest = TRY(read_list_rec(end));
|
||||||
|
|
||||||
res = Value(TRY(Pair::create(val, res)));
|
auto res = Value(TRY(Pair::create(val, rest)));
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR(ReadError);
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<Value> Reader::read_list() {
|
||||||
|
if (!match('(')) return ERROR(ReadError);
|
||||||
|
// SourcePosition start = position_;
|
||||||
|
forward();
|
||||||
|
|
||||||
|
SourcePosition end = position_;
|
||||||
|
auto res = read_list_rec(end);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> Reader::read_array_code() {
|
Result<Value> Reader::read_array_code() {
|
||||||
|
@ -517,22 +522,22 @@ bool Reader::forward_exponent() {
|
||||||
return forward_decimal_number();
|
return forward_decimal_number();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> read_one(const Value& value, bool as_code) {
|
Result<Value> read_one(const Value& value, bool syntax, bool as_code) {
|
||||||
if (!value.is<String>()) return ERROR(TypeMismatch);
|
if (!value.is<String>()) return ERROR(TypeMismatch);
|
||||||
auto r = Reader(*value.to<String>(), as_code);
|
auto r = Reader(*value.to<String>(), syntax, as_code);
|
||||||
return r.read_one();
|
return r.read_one();
|
||||||
}
|
}
|
||||||
Result<Value> read_one(const String& value, bool as_code) {
|
Result<Value> read_one(const String& value, bool syntax, bool as_code) {
|
||||||
auto r = Reader(value, as_code);
|
auto r = Reader(value, syntax, as_code);
|
||||||
return r.read_one();
|
return r.read_one();
|
||||||
}
|
}
|
||||||
Result<Value> read_one(const char* value, bool as_code) {
|
Result<Value> read_one(const char* value, bool syntax, bool as_code) {
|
||||||
auto s = TRY(String::create(value));
|
auto s = TRY(String::create(value));
|
||||||
auto r = Reader(s, as_code);
|
auto r = Reader(s, syntax, as_code);
|
||||||
return r.read_one();
|
return r.read_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> read_multiple(const String& value, bool as_code) {
|
Result<Value> read_multiple(const String& value, bool syntax, bool as_code) {
|
||||||
auto r = Reader(value, as_code);
|
auto r = Reader(value, syntax, as_code);
|
||||||
return r.read_multiple();
|
return r.read_multiple();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
class Reader {
|
class Reader {
|
||||||
public:
|
public:
|
||||||
Reader(const String& str, bool as_code = true)
|
Reader(const String& str, bool syntax = true, bool as_code = true)
|
||||||
: _str(str), _as_code(as_code) {}
|
: _str(str), _syntax(syntax), _as_code(as_code) {}
|
||||||
|
|
||||||
Result<Value> read_one();
|
Result<Value> read_one();
|
||||||
Result<Value> read_multiple();
|
Result<Value> read_multiple();
|
||||||
|
@ -28,6 +28,7 @@ class Reader {
|
||||||
bool is_string_start();
|
bool is_string_start();
|
||||||
|
|
||||||
Result<Value> read_list();
|
Result<Value> read_list();
|
||||||
|
Result<Value> read_list_rec(SourcePosition& end);
|
||||||
Result<Value> read_string();
|
Result<Value> read_string();
|
||||||
Result<Value> read_array();
|
Result<Value> read_array();
|
||||||
Result<Value> read_array_code();
|
Result<Value> read_array_code();
|
||||||
|
@ -45,12 +46,17 @@ class Reader {
|
||||||
bool match(char c);
|
bool match(char c);
|
||||||
|
|
||||||
const String& _str;
|
const String& _str;
|
||||||
|
bool _syntax;
|
||||||
bool _as_code;
|
bool _as_code;
|
||||||
SourcePosition position_{1, 1, 0};
|
SourcePosition position_{1, 1, 0};
|
||||||
};
|
};
|
||||||
|
|
||||||
Result<Value> read_one(const Value& value, bool as_code = true);
|
Result<Value> read_one(const Value& value, bool syntax = true,
|
||||||
Result<Value> read_one(const String& value, bool as_code = true);
|
bool as_code = true);
|
||||||
Result<Value> read_one(const char* value, bool as_code = true);
|
Result<Value> read_one(const String& value, bool syntax = true,
|
||||||
|
bool as_code = true);
|
||||||
|
Result<Value> read_one(const char* value, bool syntax = true,
|
||||||
|
bool as_code = true);
|
||||||
|
|
||||||
Result<Value> read_multiple(const String& value, bool as_code = true);
|
Result<Value> read_multiple(const String& value, bool syntax = true,
|
||||||
|
bool as_code = true);
|
||||||
|
|
|
@ -26,11 +26,11 @@ TEST_CASE(dict_insert) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(dict_read) {
|
TEST_CASE(dict_read) {
|
||||||
auto v = DIEX(read_one("{}", false));
|
auto v = DIEX(read_one("{}", false, false));
|
||||||
auto s = DIEX(write_one(v));
|
auto s = DIEX(write_one(v));
|
||||||
ASSERT_EQUALS(s, "{}");
|
ASSERT_EQUALS(s, "{}");
|
||||||
|
|
||||||
v = DIEX(read_one("{1 2 3 4}", false));
|
v = DIEX(read_one("{1 2 3 4}", false, false));
|
||||||
s = DIEX(write_one(v));
|
s = DIEX(write_one(v));
|
||||||
ASSERT_EQUALS(s, "{1 2 3 4}");
|
ASSERT_EQUALS(s, "{1 2 3 4}");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue