瀏覽代碼

CSV parse now parses lisp correctly

master
Ludovic 'Archivist' Lagouardette 5 年之前
父節點
當前提交
29be54af13
共有 3 個檔案被更改,包括 237 行新增10 行删除
  1. +1
    -0
      .gitignore
  2. +217
    -9
      include/rigid_paradise/lispy/lispy.hpp
  3. +19
    -1
      src/csv-sheet/csv-parse.cpp

+ 1
- 0
.gitignore 查看文件

@ -1,3 +1,4 @@
build/*
vgcore.*
a.out
\#*

+ 217
- 9
include/rigid_paradise/lispy/lispy.hpp 查看文件

@ -46,6 +46,24 @@ namespace lispy {
std::unordered_map<int, std::shared_ptr<function>> function_table;
std::unordered_map<int, lvalue> variable_table;
std::function<lvalue(sp_coords)> resolve_coords = [&](sp_coords) -> lvalue {
std::cerr << "no coord system provided" << std::endl;
if(error_crash)
{
std::exit(-1);
}
return (int64_t)0;
};
std::function<lvalue(sp_range)> resolve_range = [&](sp_range) -> lvalue {
std::cerr << "no coord system provided" << std::endl;
if(error_crash)
{
std::exit(-1);
}
return empty{};
};
int get_atom(const std::string& key)
{
if(atoms.count(key)) {
@ -100,7 +118,7 @@ namespace lispy {
cons(cons&& oth)
: self(oth.self)
, other(oth.other ? std::move(std::make_shared<cons>(*(oth.other))) : std::shared_ptr<cons>{})
, other(oth.other ? std::make_shared<cons>(*(oth.other)) : std::shared_ptr<cons>{})
{}
void append(lvalue value)
@ -221,7 +239,14 @@ namespace lispy {
}
assert(false);
} else {
std::cerr << typeid(T).name() << " detected in print_visitor ?" << std::endl;
std::cerr <<
#ifdef __cpp_rtti
typeid(T).name()
#else
"unknown type"
#endif
<< " detected in print_visitor ?" << std::endl;
if(ctx.error_crash)
{
std::exit(-1);
@ -268,7 +293,13 @@ namespace lispy {
} else if constexpr (std::is_same_v<T, atom>) {
stream << "atom";
} else {
std::cerr << typeid(T).name() << " detected in print_types_visitor ?" << std::endl;
std::cerr <<
#ifdef __cpp_rtti
typeid(T).name()
#else
"unknown type"
#endif
<< " detected in print_types_visitor ?" << std::endl;
if(ctx.error_crash)
{
std::exit(-1);
@ -306,7 +337,6 @@ namespace lispy {
char* end_f;
char* end_d;
double try_f = strtod (data.data(), &end_f);
int err_f = errno;
int64_t try_d = strtoll(data.data(), &end_d, 10);
int err_d = errno;
@ -427,12 +457,24 @@ namespace lispy {
skip = matching - idx;
++sz;
} else if constexpr (std::is_same_v<T, cons_end>) {
std::cerr << typeid(T).name() << " mismatched parenthesis" << std::endl;
std::cerr <<
#ifdef __cpp_rtti
typeid(T).name()
#else
"unknown type"
#endif
<< " mismatched parenthesis" << std::endl;
} else if constexpr (std::is_same_v<T, lvalue>) {
ret->append(arg);
++sz;
} else {
std::cerr << typeid(T).name() << " cat in the parser ?" << std::endl;
std::cerr <<
#ifdef __cpp_rtti
typeid(T).name()
#else
"unknown type"
#endif
<< " cat in the parser ?" << std::endl;
if(ctx.error_crash)
{
std::exit(-1);
@ -473,7 +515,7 @@ namespace lispy {
} else if (*it == '$' || *it == '@') {
auto value = parse_selector(std::string_view{it, (size_t)(data.end() - it)});
ret.push_back(value.first);
it += value.second.size()o">+1;
it += value.second.size();
} else {
auto value = parse_atom(std::string_view{it, (size_t)(data.end() - it)}, ctx);
ret.push_back(value.first);
@ -542,6 +584,10 @@ namespace lispy {
}
}
namespace lispy_math {
int64_t next_as_int(std::shared_ptr<lispy::cons>& arguments, lispy::context& ctx) {
@ -555,7 +601,8 @@ namespace lispy_math {
}
return ret;
}
std::visit([&](auto arg) {
auto extractor = [&](auto arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int64_t>) {
ret = arg;
@ -568,6 +615,15 @@ namespace lispy_math {
std::exit(-1);
}
}
};
std::visit([&](auto arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, lispy::sp_coords>) {
std::visit(extractor, ctx.resolve_coords(arg));
} else {
std::visit(extractor, arguments->self);
}
}, arguments->self);
arguments = arguments->other;
return ret;
@ -584,7 +640,8 @@ namespace lispy_math {
}
return ret;
}
std::visit([&](auto arg) {
auto extractor = [&](auto arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int64_t>) {
ret = arg;
@ -597,11 +654,89 @@ namespace lispy_math {
std::exit(-1);
}
}
};
std::visit([&](auto arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, lispy::sp_coords>) {
std::visit(extractor, ctx.resolve_coords(arg));
} else {
std::visit(extractor, arguments->self);
}
}, arguments->self);
arguments = arguments->other;
return ret;
}
lispy::lvalue next_as_floating_aggregate(std::shared_ptr<lispy::cons>& arguments, lispy::context& ctx) {
lispy::lvalue src = lispy::empty{};
if(!arguments)
{
std::cerr << "no argument provided, s-exp or range expected" << std::endl;
if(ctx.error_crash)
{
std::exit(-1);
}
return src;
}
auto extractor = [&](auto arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, lispy::empty>) {
src = arg;
} else if constexpr (std::is_same_v<T, std::shared_ptr<lispy::cons>>) {
src = arg;
} else {
std::cerr << "bad argument provided, s-exp or range expected" << std::endl;
if(ctx.error_crash)
{
std::exit(-1);
}
}
};
std::visit([&](auto arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, lispy::sp_range>) {
std::visit(extractor, ctx.resolve_range(arg));
} else if constexpr (std::is_same_v<T, std::shared_ptr<lispy::cons>>) {
std::visit(extractor, arguments->self);
} else {
std::cerr << "bad argument provided, s-exp or range expected" << std::endl;
if(ctx.error_crash)
{
std::exit(-1);
}
}
}, arguments->self);
std::shared_ptr<lispy::cons> dest;
std::visit([&](auto arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, lispy::empty>) {}
else if constexpr (std::is_same_v<T, std::shared_ptr<lispy::cons>>) {
dest = std::make_shared<lispy::cons>(lispy_math::next_as_floating(arg, ctx));
while(arg){
dest->append(lispy_math::next_as_floating(arg, ctx));
}
} else {
std::cerr << "bad argument provided, s-exp or range expected" << std::endl;
if(ctx.error_crash)
{
std::exit(-1);
}
}
}, src);
arguments = arguments->other;
if(dest)
{
return dest;
}
return lispy::empty{};
}
namespace integer_functions {
class plus : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr<lispy::cons> arguments, lispy::context& ctx) {
auto p = arguments;
@ -683,6 +818,41 @@ namespace lispy_math {
}
return a%b;
}};
class iota : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr<lispy::cons> arguments, lispy::context& ctx) {
auto p = arguments;
int64_t a = next_as_int(p, ctx);
int64_t b = next_as_int(p, ctx);
if(p)
{
std::cerr << "expected arity of 2 but more arguments provided" << std::endl;
if(ctx.error_crash)
{
std::exit(-1);
}
}
if(b<=a)
{
std::cerr << "expected first argument lower than second" << std::endl;
if(ctx.error_crash)
{
std::exit(-1);
}
return lispy::empty{};
}
std::shared_ptr<lispy::cons> ret = std::make_shared<lispy::cons>(a);
a+=1;
for(;a<b;a++)
{
ret->append(a);
}
return ret;
}};
};
namespace float_functions {
@ -752,6 +922,36 @@ namespace lispy_math {
return a/b;
}};
};
namespace aggregate_functions {
class sum : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr<lispy::cons> arguments, lispy::context& ctx) {
auto p = arguments;
lispy::lvalue cells = next_as_floating_aggregate(p, ctx);
if(p)
{
std::cerr << "expected arity of 1 but more arguments provided" << std::endl;
if(ctx.error_crash)
{
std::exit(-1);
}
}
double ret = 0;
while(std::get<std::shared_ptr<lispy::cons>>(cells)) {
ret += lispy_math::next_as_floating(std::get<std::shared_ptr<lispy::cons>>(cells), ctx);
}
return ret;
}};
};
inline void add_integer_functions(lispy::context& ctx) {
using func_ptr = std::shared_ptr<lispy::function>;
@ -761,6 +961,8 @@ namespace lispy_math {
ctx.function_table[ctx.get_atom("*")] = func_ptr{(lispy::function*)new integer_functions::product()};
ctx.function_table[ctx.get_atom("/")] = func_ptr{(lispy::function*)new integer_functions::divide()};
ctx.function_table[ctx.get_atom("%")] = func_ptr{(lispy::function*)new integer_functions::remainder()};
ctx.function_table[ctx.get_atom("iota")] = func_ptr{(lispy::function*)new integer_functions::iota()};
}
inline void add_floatingp_functions(lispy::context& ctx) {
@ -771,4 +973,10 @@ namespace lispy_math {
ctx.function_table[ctx.get_atom("*.")] = func_ptr{(lispy::function*)new float_functions::product()};
ctx.function_table[ctx.get_atom("/.")] = func_ptr{(lispy::function*)new float_functions::divide()};
}
inline void add_aggregate_functions(lispy::context& ctx) {
using func_ptr = std::shared_ptr<lispy::function>;
ctx.function_table[ctx.get_atom("sum")] = func_ptr{(lispy::function*)new aggregate_functions::sum()};
}
}

+ 19
- 1
src/csv-sheet/csv-parse.cpp 查看文件

@ -4,11 +4,29 @@
int main() {
lispy::context ctx;
ctx.print_parse_results = true;
ctx.resolve_coords = [](lispy::sp_coords c) -> lispy::lvalue {
return (int64_t)c.x;
};
lispy_math::add_integer_functions(ctx);
lispy_math::add_floatingp_functions(ctx);
lispy::lvalue v = lispy::eval("cat $AA12 @A12:C23 (/. (+ 3 (* 5 6)) 10) \"data \\ ひらがな \n\ttabulated\" \"\" \"test 2 \\x65\"", ctx);
lispy_math::add_aggregate_functions(ctx);
lispy::lvalue v = lispy::eval("cat $AA12 @A12:C23 (+ $A1 @B2) (sum (13 1.2 15 1 (+. 16 2.3))) (/. (+ 3 (* 5 6)) 10) \"data \\ ひらがな \n\ttabulated\" \"\" \"test 2 \\x65\"", ctx);
lispy::print_types_visitor(std::cout, v, ctx);
std::cout << std::endl;
lispy::print_visitor(std::cout, v, ctx);
std::cout << std::endl;
v = lispy::eval("sum (1.2)", ctx);
ctx.print_parse_results = false;
std::string data;
while(std::getline(std::cin, data))
{
lispy::print_visitor(
std::cout,
lispy::eval(data, ctx),
ctx
);
std::cout << std::endl;
}
}

Loading…
取消
儲存