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