Beginnings of a reader
This commit is contained in:
parent
ded19f7962
commit
46381cccef
10 changed files with 343 additions and 79 deletions
|
@ -14,6 +14,7 @@ target_sources(vm_lib
|
||||||
src/vm.cpp
|
src/vm.cpp
|
||||||
src/common.cpp
|
src/common.cpp
|
||||||
src/arena.cpp
|
src/arena.cpp
|
||||||
|
src/reader.cpp
|
||||||
|
|
||||||
PUBLIC
|
PUBLIC
|
||||||
FILE_SET HEADERS
|
FILE_SET HEADERS
|
||||||
|
@ -25,6 +26,8 @@ target_sources(vm_lib
|
||||||
src/pod.hpp
|
src/pod.hpp
|
||||||
src/result.hpp
|
src/result.hpp
|
||||||
src/vm.hpp
|
src/vm.hpp
|
||||||
|
src/sourcerange.hpp
|
||||||
|
src/reader.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(vli src/vli.cpp)
|
add_executable(vli src/vli.cpp)
|
||||||
|
|
|
@ -17,6 +17,8 @@ class GcRootBase {
|
||||||
|
|
||||||
~GcRootBase();
|
~GcRootBase();
|
||||||
|
|
||||||
|
PodObject* get() { return _ptr; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PodObject* _ptr;
|
PodObject* _ptr;
|
||||||
GcRootList* _node;
|
GcRootList* _node;
|
||||||
|
@ -35,6 +37,7 @@ class GcRoot : public GcRootBase {
|
||||||
return GcRoot<T>::create((T*)_ptr, arena);
|
return GcRoot<T>::create((T*)_ptr, arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T* get() { return (T*)_ptr; }
|
||||||
T& operator*() { return *(T*)_ptr; }
|
T& operator*() { return *(T*)_ptr; }
|
||||||
T* operator->() { return (T*)_ptr; }
|
T* operator->() { return (T*)_ptr; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
|
||||||
#include "arena.hpp"
|
#include "arena.hpp"
|
||||||
|
#include "error.hpp"
|
||||||
|
#include "pod.hpp"
|
||||||
|
|
||||||
Syntax::Syntax(String filename, String modulename, Value expression) {}
|
Syntax::Syntax(String filename, String modulename, Value expression) {}
|
||||||
|
|
||||||
|
@ -11,11 +13,11 @@ Result<Value> Syntax::get_value(Arena& arena) {
|
||||||
Result<Value> Value::create(Arena& arena, PodObject* obj) {
|
Result<Value> Value::create(Arena& arena, PodObject* obj) {
|
||||||
switch (obj->header.tag) {
|
switch (obj->header.tag) {
|
||||||
case Tag::Nil:
|
case Tag::Nil:
|
||||||
return Value();
|
return Value(TRY(Nil::create(arena, (PodNil*)obj)));
|
||||||
case Tag::Int64:
|
case Tag::Int64:
|
||||||
return Value(Int64(((PodInt64*)obj)->value));
|
return Value(TRY(Int64::create(arena, (PodInt64*)obj)));
|
||||||
case Tag::Float:
|
case Tag::Float:
|
||||||
return Value(Int64(((PodFloat*)obj)->value));
|
return Value(TRY(Float::create(arena, (PodFloat*)obj)));
|
||||||
case Tag::String:
|
case Tag::String:
|
||||||
return Value(TRY(String::create(arena, (PodString*)obj)));
|
return Value(TRY(String::create(arena, (PodString*)obj)));
|
||||||
case Tag::Symbol:
|
case Tag::Symbol:
|
||||||
|
@ -37,8 +39,12 @@ Result<Value> syntax_unwrap(Arena& arena, Value& val) {
|
||||||
|
|
||||||
Result<Value> Nil::copy(Arena& arena) { return Value(Nil()); }
|
Result<Value> Nil::copy(Arena& arena) { return Value(Nil()); }
|
||||||
|
|
||||||
Result<Value> Int64::copy(Arena& arena) { return Value(Int64(_value)); }
|
Result<Value> Int64::copy(Arena& arena) {
|
||||||
Result<Value> Float::copy(Arena& arena) { return Value(Float(_value)); }
|
return Value(Int64(TRY(_value.copy(arena))));
|
||||||
|
}
|
||||||
|
Result<Value> Float::copy(Arena& arena) {
|
||||||
|
return Value(Float(TRY(_value.copy(arena))));
|
||||||
|
}
|
||||||
|
|
||||||
Result<Value> String::copy(Arena& arena) {
|
Result<Value> String::copy(Arena& arena) {
|
||||||
return Value(String(TRY(_value.copy(arena))));
|
return Value(String(TRY(_value.copy(arena))));
|
||||||
|
@ -55,3 +61,37 @@ Result<Value> Syntax::copy(Arena& arena) {
|
||||||
Result<Value> Pair::copy(Arena& arena) {
|
Result<Value> Pair::copy(Arena& arena) {
|
||||||
return Value(Pair(TRY(_value.copy(arena))));
|
return Value(Pair(TRY(_value.copy(arena))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<Pair> Pair::create(Arena& arena, Value& first, Value& rest) {
|
||||||
|
auto pod = TRY(arena.alloc<PodPair>());
|
||||||
|
pod->first = OffPtr<PodObject>(pod, first.pod());
|
||||||
|
pod->rest = OffPtr<PodObject>(pod, rest.pod());
|
||||||
|
|
||||||
|
return Pair(TRY(MkGcRoot(pod, arena)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<Value> Pair::first(Arena& arena) {
|
||||||
|
auto val = _value->first.get(pod());
|
||||||
|
return Value::create(arena, val);
|
||||||
|
}
|
||||||
|
Result<Value> Pair::rest(Arena& arena) {
|
||||||
|
auto val = _value->rest.get(pod());
|
||||||
|
return Value::create(arena, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<Value> reverse(Arena& arena, Value& val) {
|
||||||
|
if (!val.is<Pair>()) return ErrorCode::TypeMismatch;
|
||||||
|
|
||||||
|
auto res = Value(TRY(Nil::create(arena)));
|
||||||
|
auto cur = TRY(val.copy(arena));
|
||||||
|
|
||||||
|
while (!cur.is<Nil>()) {
|
||||||
|
if (!cur.is<Pair>()) return ErrorCode::TypeMismatch;
|
||||||
|
Pair& pair = *cur.to<Pair>();
|
||||||
|
Value first = TRY(pair.first(arena));
|
||||||
|
cur = TRY(pair.rest(arena));
|
||||||
|
res = TRY(Pair::create(arena, first, res));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
136
src/common.hpp
136
src/common.hpp
|
@ -12,75 +12,35 @@
|
||||||
|
|
||||||
class Value;
|
class Value;
|
||||||
|
|
||||||
struct SourcePosition {
|
|
||||||
size_t line{1};
|
|
||||||
size_t column{1};
|
|
||||||
size_t offset{0};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SourceRange {
|
|
||||||
SourcePosition start;
|
|
||||||
SourcePosition end;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PodInt64 final : public PodObject {
|
|
||||||
public:
|
|
||||||
PodInt64() : PodObject(Tag::Int64){};
|
|
||||||
|
|
||||||
int64_t value;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PodFloat final : public PodObject {
|
|
||||||
public:
|
|
||||||
PodFloat() : PodObject(Tag::Float){};
|
|
||||||
|
|
||||||
double value;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PodString final : public PodObject {
|
|
||||||
public:
|
|
||||||
PodString() : PodObject(Tag::String){};
|
|
||||||
|
|
||||||
uint64_t size;
|
|
||||||
char32_t data[];
|
|
||||||
};
|
|
||||||
|
|
||||||
class PodSymbol final : public PodObject {
|
|
||||||
public:
|
|
||||||
PodSymbol() : PodObject(Tag::Symbol){};
|
|
||||||
|
|
||||||
uint64_t size;
|
|
||||||
char32_t data[];
|
|
||||||
};
|
|
||||||
|
|
||||||
class PodSyntax : public PodObject {
|
|
||||||
public:
|
|
||||||
PodSyntax() : PodObject(Tag::Syntax){};
|
|
||||||
OffPtr<PodString> filename;
|
|
||||||
OffPtr<PodString> modulename;
|
|
||||||
OffPtr<PodObject> expression;
|
|
||||||
SourceRange sourcerange;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PodPair : public PodObject {
|
|
||||||
public:
|
|
||||||
PodPair() : PodObject(Tag::Pair){};
|
|
||||||
OffPtr<PodObject> first;
|
|
||||||
OffPtr<PodObject> second;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Object {
|
class Object {
|
||||||
public:
|
public:
|
||||||
virtual Tag tag() = 0;
|
virtual Tag tag() = 0;
|
||||||
virtual Result<Value> copy(Arena& arena) = 0;
|
virtual Result<Value> copy(Arena& arena) = 0;
|
||||||
|
virtual PodObject* pod() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Nil : public Object {
|
class Nil : public Object {
|
||||||
public:
|
public:
|
||||||
Nil() {}
|
Nil() {}
|
||||||
|
Nil(GcRoot<PodNil>&& val) : _value(std::move(val)) {}
|
||||||
|
|
||||||
virtual Tag tag() final { return Tag::Nil; }
|
virtual Tag tag() final { return Tag::Nil; }
|
||||||
|
virtual PodObject* pod() final { return _value.get(); }
|
||||||
|
|
||||||
|
static Result<Nil> create(Arena& arena, PodNil* obj) {
|
||||||
|
return Nil(TRY(MkGcRoot(obj, arena)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<Nil> create(Arena& arena) {
|
||||||
|
auto pod = TRY(arena.alloc<PodNil>());
|
||||||
|
|
||||||
|
return Nil(TRY(MkGcRoot(pod, arena)));
|
||||||
|
}
|
||||||
|
|
||||||
virtual Result<Value> copy(Arena& arena) final;
|
virtual Result<Value> copy(Arena& arena) final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GcRoot<PodNil> _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
class String : public Object {
|
class String : public Object {
|
||||||
|
@ -88,6 +48,7 @@ class String : public Object {
|
||||||
String() {}
|
String() {}
|
||||||
String(GcRoot<PodString>&& val) : _value(std::move(val)) {}
|
String(GcRoot<PodString>&& val) : _value(std::move(val)) {}
|
||||||
virtual Tag tag() final { return Tag::String; }
|
virtual Tag tag() final { return Tag::String; }
|
||||||
|
virtual PodObject* pod() final { return _value.get(); }
|
||||||
|
|
||||||
static Result<String> create(Arena& arena, PodString* obj) {
|
static Result<String> create(Arena& arena, PodString* obj) {
|
||||||
return String(TRY(MkGcRoot(obj, arena)));
|
return String(TRY(MkGcRoot(obj, arena)));
|
||||||
|
@ -129,6 +90,7 @@ class Symbol : public Object {
|
||||||
Symbol() {}
|
Symbol() {}
|
||||||
Symbol(GcRoot<PodSymbol>&& val) : _value(std::move(val)) {}
|
Symbol(GcRoot<PodSymbol>&& val) : _value(std::move(val)) {}
|
||||||
virtual Tag tag() final { return Tag::Symbol; }
|
virtual Tag tag() final { return Tag::Symbol; }
|
||||||
|
virtual PodObject* pod() final { return _value.get(); }
|
||||||
|
|
||||||
static Result<Symbol> create(Arena& arena, PodSymbol* obj) {
|
static Result<Symbol> create(Arena& arena, PodSymbol* obj) {
|
||||||
return Symbol(TRY(MkGcRoot(obj, arena)));
|
return Symbol(TRY(MkGcRoot(obj, arena)));
|
||||||
|
@ -154,6 +116,7 @@ class Syntax : public Object {
|
||||||
Syntax(GcRoot<PodSyntax>&& val) : _value(std::move(val)) {}
|
Syntax(GcRoot<PodSyntax>&& val) : _value(std::move(val)) {}
|
||||||
Syntax(String filename, String modulename, Value expression);
|
Syntax(String filename, String modulename, Value expression);
|
||||||
virtual Tag tag() final { return Tag::Syntax; }
|
virtual Tag tag() final { return Tag::Syntax; }
|
||||||
|
virtual PodObject* pod() final { return _value.get(); }
|
||||||
|
|
||||||
static Result<Syntax> create(Arena& arena, PodSyntax* obj) {
|
static Result<Syntax> create(Arena& arena, PodSyntax* obj) {
|
||||||
return Syntax(TRY(MkGcRoot(obj, arena)));
|
return Syntax(TRY(MkGcRoot(obj, arena)));
|
||||||
|
@ -172,12 +135,15 @@ class Pair : public Object {
|
||||||
Pair() {}
|
Pair() {}
|
||||||
Pair(GcRoot<PodPair>&& val) : _value(std::move(val)) {}
|
Pair(GcRoot<PodPair>&& val) : _value(std::move(val)) {}
|
||||||
virtual Tag tag() final { return Tag::Pair; }
|
virtual Tag tag() final { return Tag::Pair; }
|
||||||
|
virtual PodObject* pod() final { return _value.get(); }
|
||||||
|
|
||||||
static Result<Pair> create(Arena& arena, PodPair* obj) {
|
static Result<Pair> create(Arena& arena, PodPair* obj) {
|
||||||
return Pair(TRY(MkGcRoot(obj, arena)));
|
return Pair(TRY(MkGcRoot(obj, arena)));
|
||||||
}
|
}
|
||||||
|
static Result<Pair> create(Arena& arena, Value& first, Value& rest);
|
||||||
|
|
||||||
static Result<Value> first(Arena& arena);
|
Result<Value> first(Arena& arena);
|
||||||
|
Result<Value> rest(Arena& arena);
|
||||||
|
|
||||||
virtual Result<Value> copy(Arena& arena) final;
|
virtual Result<Value> copy(Arena& arena) final;
|
||||||
|
|
||||||
|
@ -187,34 +153,54 @@ class Pair : public Object {
|
||||||
|
|
||||||
class Int64 : public Object {
|
class Int64 : public Object {
|
||||||
public:
|
public:
|
||||||
Int64() : _value(0) {}
|
Int64() {}
|
||||||
Int64(int64_t val) : _value(val) {}
|
Int64(GcRoot<PodInt64>&& val) : _value(std::move(val)) {}
|
||||||
virtual ~Int64() = default;
|
|
||||||
|
|
||||||
virtual Tag tag() final { return Tag::Int64; }
|
virtual Tag tag() final { return Tag::Int64; }
|
||||||
|
virtual PodObject* pod() final { return _value.get(); }
|
||||||
|
|
||||||
int64_t value() { return _value; }
|
static Result<Int64> create(Arena& arena, PodInt64* obj) {
|
||||||
|
return Int64(TRY(MkGcRoot(obj, arena)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<Int64> create(Arena& arena, double val) {
|
||||||
|
auto pod = TRY(arena.alloc<PodInt64>());
|
||||||
|
pod->value = val;
|
||||||
|
|
||||||
|
return Int64(TRY(MkGcRoot(pod, arena)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t value() { return _value->value; }
|
||||||
|
|
||||||
virtual Result<Value> copy(Arena& arena) final;
|
virtual Result<Value> copy(Arena& arena) final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int64_t _value;
|
GcRoot<PodInt64> _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Float : public Object {
|
class Float : public Object {
|
||||||
public:
|
public:
|
||||||
Float() : _value(0) {}
|
Float() {}
|
||||||
Float(double val) : _value(val) {}
|
Float(GcRoot<PodFloat>&& val) : _value(std::move(val)) {}
|
||||||
virtual ~Float() = default;
|
|
||||||
|
|
||||||
virtual Tag tag() final { return Tag::Float; }
|
virtual Tag tag() final { return Tag::Float; }
|
||||||
|
virtual PodObject* pod() final { return _value.get(); }
|
||||||
|
|
||||||
double value() { return _value; }
|
static Result<Float> create(Arena& arena, PodFloat* obj) {
|
||||||
|
return Float(TRY(MkGcRoot(obj, arena)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<Float> create(Arena& arena, double val) {
|
||||||
|
auto pod = TRY(arena.alloc<PodFloat>());
|
||||||
|
pod->value = val;
|
||||||
|
|
||||||
|
return Float(TRY(MkGcRoot(pod, arena)));
|
||||||
|
}
|
||||||
|
|
||||||
|
double value() { return _value->value; }
|
||||||
|
|
||||||
virtual Result<Value> copy(Arena& arena) final;
|
virtual Result<Value> copy(Arena& arena) final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double _value;
|
GcRoot<PodFloat> _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// note: this class doesn't perform proper destruction of objects in some cases
|
// note: this class doesn't perform proper destruction of objects in some cases
|
||||||
|
@ -235,6 +221,12 @@ class Value {
|
||||||
new (buf) T(std::move(obj));
|
new (buf) T(std::move(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value& operator=(Value&& val) {
|
||||||
|
memcpy(buf, val.buf, 24);
|
||||||
|
new (val.buf) Nil();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
static Result<Value> create(Arena& arena, PodObject* obj);
|
static Result<Value> create(Arena& arena, PodObject* obj);
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -247,6 +239,8 @@ class Value {
|
||||||
return dynamic_cast<T*>((Object*)buf);
|
return dynamic_cast<T*>((Object*)buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PodObject* pod() { return ((Object*)buf)->pod(); }
|
||||||
|
|
||||||
Object& operator*() { return *(Object*)(buf); }
|
Object& operator*() { return *(Object*)(buf); }
|
||||||
Object* operator->() { return (Object*)(buf); }
|
Object* operator->() { return (Object*)(buf); }
|
||||||
|
|
||||||
|
@ -257,3 +251,5 @@ class Value {
|
||||||
};
|
};
|
||||||
|
|
||||||
Result<Value> syntax_unwrap(Value& val);
|
Result<Value> syntax_unwrap(Value& val);
|
||||||
|
|
||||||
|
Result<Value> reverse(Arena& arena, Value& val);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
enum class ErrorCode {
|
enum class ErrorCode {
|
||||||
Success,
|
Success,
|
||||||
OutOfMemory,
|
OutOfMemory,
|
||||||
IndexOutOfRange
|
IndexOutOfRange,
|
||||||
|
TypeMismatch,
|
||||||
|
ReadError
|
||||||
};
|
};
|
||||||
|
|
78
src/pod.hpp
78
src/pod.hpp
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "result.hpp"
|
||||||
|
#include "sourcerange.hpp"
|
||||||
|
|
||||||
enum class Tag : uint8_t {
|
enum class Tag : uint8_t {
|
||||||
Nil,
|
Nil,
|
||||||
Int64,
|
Int64,
|
||||||
|
@ -43,3 +46,78 @@ static_assert(sizeof(PodHeader) == 8);
|
||||||
struct PodObject {
|
struct PodObject {
|
||||||
PodHeader header;
|
PodHeader header;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PodNil final : public PodObject {
|
||||||
|
public:
|
||||||
|
PodNil() : PodObject(Tag::Nil){};
|
||||||
|
};
|
||||||
|
|
||||||
|
class PodInt64 final : public PodObject {
|
||||||
|
public:
|
||||||
|
PodInt64() : PodObject(Tag::Int64){};
|
||||||
|
|
||||||
|
int64_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PodFloat final : public PodObject {
|
||||||
|
public:
|
||||||
|
PodFloat() : PodObject(Tag::Float){};
|
||||||
|
|
||||||
|
double value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PodString final : public PodObject {
|
||||||
|
public:
|
||||||
|
PodString() : PodObject(Tag::String){};
|
||||||
|
|
||||||
|
uint64_t size;
|
||||||
|
char32_t data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
class PodSymbol final : public PodObject {
|
||||||
|
public:
|
||||||
|
PodSymbol() : PodObject(Tag::Symbol){};
|
||||||
|
|
||||||
|
uint64_t size;
|
||||||
|
char32_t data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
class PodSyntax : public PodObject {
|
||||||
|
public:
|
||||||
|
PodSyntax() : PodObject(Tag::Syntax){};
|
||||||
|
OffPtr<PodString> filename;
|
||||||
|
OffPtr<PodString> modulename;
|
||||||
|
OffPtr<PodObject> expression;
|
||||||
|
SourceRange sourcerange;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PodPair : public PodObject {
|
||||||
|
public:
|
||||||
|
PodPair() : PodObject(Tag::Pair){};
|
||||||
|
OffPtr<PodObject> first;
|
||||||
|
OffPtr<PodObject> rest;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class Ptr {
|
||||||
|
public:
|
||||||
|
Ptr() : _ptr(0) {}
|
||||||
|
Ptr(T* ptr) : _ptr(ptr){};
|
||||||
|
|
||||||
|
T* get() { return _ptr; }
|
||||||
|
T& operator*() { return *_ptr; }
|
||||||
|
T* operator->() { return _ptr; }
|
||||||
|
|
||||||
|
Result<int64_t> get_int() {
|
||||||
|
if (_ptr->tag != Tag::Int64) return ErrorCode::TypeMismatch;
|
||||||
|
return ((PodInt64*)_ptr)->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<double> get_float() {
|
||||||
|
if (_ptr->tag != Tag::Float) return ErrorCode::TypeMismatch;
|
||||||
|
return ((PodFloat*)_ptr)->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* _ptr;
|
||||||
|
};
|
||||||
|
|
85
src/reader.cpp
Normal file
85
src/reader.cpp
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
#include "reader.hpp"
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
static bool is_digit(char32_t c) { return c >= '0' && c <= '9'; }
|
||||||
|
static bool is_alpha(char32_t c) {
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_hex_digit(char32_t c) {
|
||||||
|
return is_digit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_symbol_char(char32_t c) {
|
||||||
|
static char valid_char[] = {'!', '$', '%', '&', '*', '+', '-', '.', '/',
|
||||||
|
':', '<', '=', '>', '?', '@', '^', '_', '~'};
|
||||||
|
|
||||||
|
if (is_digit(c)) return true;
|
||||||
|
if (is_alpha(c)) return true;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(valid_char); ++i) {
|
||||||
|
if (char32_t(valid_char[i]) == c) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_whitespace(char32_t c) {
|
||||||
|
return c == ' ' || c == '\t' || c == '\v' || c == '\f';
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_brace(char32_t c) {
|
||||||
|
return c == '[' || c == ']' || c == '(' || c == ')' || c == '{' || c == '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_newline(char32_t c) { return c == '\r' || c == '\n'; }
|
||||||
|
|
||||||
|
static bool is_separator(char32_t c) {
|
||||||
|
return is_whitespace(c) || is_brace(c) || is_newline(c) || c == ';';
|
||||||
|
}
|
||||||
|
|
||||||
|
#define EOS 0
|
||||||
|
|
||||||
|
Result<Value> Reader::read_one() {
|
||||||
|
forward_whitespace();
|
||||||
|
|
||||||
|
auto saved_position = position_;
|
||||||
|
if (is_numeric_start()) {
|
||||||
|
auto res = read_number();
|
||||||
|
if (res.has_value()) return res;
|
||||||
|
} else if (match("true") || match("false")) {
|
||||||
|
auto res = read_bool();
|
||||||
|
if (res.has_value()) return res;
|
||||||
|
} else if (is_string_start()) {
|
||||||
|
return read_string();
|
||||||
|
} else if (match('(')) {
|
||||||
|
return read_list();
|
||||||
|
} else if (match('[')) {
|
||||||
|
return read_array();
|
||||||
|
} else if (match('{')) {
|
||||||
|
return read_dict();
|
||||||
|
}
|
||||||
|
|
||||||
|
position_ = saved_position;
|
||||||
|
if (is_symbol_start()) {
|
||||||
|
return read_symbol();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorCode::ReadError;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<Value> Reader::read_multiple() {
|
||||||
|
Value res = TRY(Nil::create(_arena));
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
forward_whitespace();
|
||||||
|
if (is_eof()) {
|
||||||
|
return reverse(_arena, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto val = TRY(read_one());
|
||||||
|
res = Value(TRY(Pair::create(_arena, val, res)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorCode::ReadError;
|
||||||
|
}
|
44
src/reader.hpp
Normal file
44
src/reader.hpp
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#pragma once
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "result.hpp"
|
||||||
|
#include "sourcerange.hpp"
|
||||||
|
|
||||||
|
class Reader {
|
||||||
|
public:
|
||||||
|
Reader(Arena& arena, String&& str) : _arena(arena), _str(std::move(str)) {}
|
||||||
|
|
||||||
|
Result<Value> read_one();
|
||||||
|
Result<Value> read_multiple();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void forward();
|
||||||
|
void forward(size_t n);
|
||||||
|
bool forward_exponent();
|
||||||
|
bool forward_decimal_number();
|
||||||
|
bool forward_hex_number();
|
||||||
|
void forward_whitespace();
|
||||||
|
|
||||||
|
bool is_eol();
|
||||||
|
bool is_eof();
|
||||||
|
bool is_whitespace();
|
||||||
|
bool is_comment_start();
|
||||||
|
bool is_numeric_start();
|
||||||
|
bool is_symbol_start();
|
||||||
|
bool is_string_start();
|
||||||
|
|
||||||
|
Result<Value> read_list();
|
||||||
|
Result<Value> read_string();
|
||||||
|
Result<Value> read_array();
|
||||||
|
Result<Value> read_dict();
|
||||||
|
Result<Value> read_number();
|
||||||
|
Result<Value> read_symbol();
|
||||||
|
Result<Value> read_bool();
|
||||||
|
|
||||||
|
char32_t get(size_t offset = 0);
|
||||||
|
bool match(const char* str);
|
||||||
|
bool match(char c);
|
||||||
|
|
||||||
|
Arena& _arena;
|
||||||
|
String _str;
|
||||||
|
SourcePosition position_{1, 1, 0};
|
||||||
|
};
|
14
src/sourcerange.hpp
Normal file
14
src/sourcerange.hpp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
struct SourcePosition {
|
||||||
|
size_t line{1};
|
||||||
|
size_t column{1};
|
||||||
|
size_t offset{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SourceRange {
|
||||||
|
SourcePosition start;
|
||||||
|
SourcePosition end;
|
||||||
|
};
|
|
@ -21,10 +21,10 @@ int main() {
|
||||||
{
|
{
|
||||||
auto s = DIEIF(String::create(arena, "foo"));
|
auto s = DIEIF(String::create(arena, "foo"));
|
||||||
|
|
||||||
std::cout << "roout count: " << arena.root_count() << "\n";
|
std::cout << "root count: " << arena.root_count() << "\n";
|
||||||
std::cout << "char: " << (char)DIEIF(s[2]) << "\n";
|
std::cout << "char: " << (char)DIEIF(s[2]) << "\n";
|
||||||
}
|
}
|
||||||
std::cout << "roout count: " << arena.root_count() << "\n";
|
std::cout << "root count: " << arena.root_count() << "\n";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue