From 8515d45b1e4d454ee0dda0e9c1d822d54d0d6b8b Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Wed, 4 Sep 2024 23:18:57 +0100 Subject: [PATCH] Use recursion for reading lists --- src/reader.cpp | 65 +++++++++++++++++++++++++++----------------------- src/reader.hpp | 18 +++++++++----- test/dict.cpp | 4 ++-- 3 files changed, 49 insertions(+), 38 deletions(-) diff --git a/src/reader.cpp b/src/reader.cpp index c773999..4a09ec5 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -88,31 +88,36 @@ Result Reader::read_multiple() { return ERROR(ReadError); } -Result Reader::read_list() { - if (!match('(')) return ERROR(ReadError); +Result 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 Reader::read_list() { + if (!match('(')) return ERROR(ReadError); + // SourcePosition start = position_; + forward(); + + SourcePosition end = position_; + auto res = read_list_rec(end); + + return res; } Result Reader::read_array_code() { @@ -517,22 +522,22 @@ bool Reader::forward_exponent() { return forward_decimal_number(); } -Result read_one(const Value& value, bool as_code) { +Result read_one(const Value& value, bool syntax, bool as_code) { if (!value.is()) return ERROR(TypeMismatch); - auto r = Reader(*value.to(), as_code); + auto r = Reader(*value.to(), syntax, as_code); return r.read_one(); } -Result read_one(const String& value, bool as_code) { - auto r = Reader(value, as_code); +Result read_one(const String& value, bool syntax, bool as_code) { + auto r = Reader(value, syntax, as_code); return r.read_one(); } -Result read_one(const char* value, bool as_code) { +Result 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 read_multiple(const String& value, bool as_code) { - auto r = Reader(value, as_code); +Result read_multiple(const String& value, bool syntax, bool as_code) { + auto r = Reader(value, syntax, as_code); return r.read_multiple(); } diff --git a/src/reader.hpp b/src/reader.hpp index 61c8e45..6fa28be 100644 --- a/src/reader.hpp +++ b/src/reader.hpp @@ -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 read_one(); Result read_multiple(); @@ -28,6 +28,7 @@ class Reader { bool is_string_start(); Result read_list(); + Result read_list_rec(SourcePosition& end); Result read_string(); Result read_array(); Result 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 read_one(const Value& value, bool as_code = true); -Result read_one(const String& value, bool as_code = true); -Result read_one(const char* value, bool as_code = true); +Result read_one(const Value& value, bool syntax = true, + bool as_code = true); +Result read_one(const String& value, bool syntax = true, + bool as_code = true); +Result read_one(const char* value, bool syntax = true, + bool as_code = true); -Result read_multiple(const String& value, bool as_code = true); +Result read_multiple(const String& value, bool syntax = true, + bool as_code = true); diff --git a/test/dict.cpp b/test/dict.cpp index 0909bb7..cc1e51f 100644 --- a/test/dict.cpp +++ b/test/dict.cpp @@ -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}");