Browse Source

CSV parse now parses lisp correctly

master
Ludovic 'Archivist' Lagouardette 5 years ago
parent
commit
29be54af13
3 changed files with 237 additions and 10 deletions
  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 View File

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

+ 217
- 9
include/rigid_paradise/lispy/lispy.hpp View File

@ -46,6 +46,24 @@ namespace lispy {
std::unordered_map<int, std::shared_ptr<function>> function_table; std::unordered_map<int, std::shared_ptr<function>> function_table;
std::unordered_map<int, lvalue> variable_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) int get_atom(const std::string& key)
{ {
if(atoms.count(key)) { if(atoms.count(key)) {
@ -100,7 +118,7 @@ namespace lispy {
cons(cons&& oth) cons(cons&& oth)
: self(oth.self) : 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) void append(lvalue value)
@ -221,7 +239,14 @@ namespace lispy {
} }
assert(false); assert(false);
} else { } 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) if(ctx.error_crash)
{ {
std::exit(-1); std::exit(-1);
@ -268,7 +293,13 @@ namespace lispy {
} else if constexpr (std::is_same_v<T, atom>) { } else if constexpr (std::is_same_v<T, atom>) {
stream << "atom"; stream << "atom";
} else { } 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) if(ctx.error_crash)
{ {
std::exit(-1); std::exit(-1);
@ -306,7 +337,6 @@ namespace lispy {
char* end_f; char* end_f;
char* end_d; char* end_d;
double try_f = strtod (data.data(), &end_f); double try_f = strtod (data.data(), &end_f);
int err_f = errno;
int64_t try_d = strtoll(data.data(), &end_d, 10); int64_t try_d = strtoll(data.data(), &end_d, 10);
int err_d = errno; int err_d = errno;
@ -427,12 +457,24 @@ namespace lispy {
skip = matching - idx; skip = matching - idx;
++sz; ++sz;
} else if constexpr (std::is_same_v<T, cons_end>) { } 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>) { } else if constexpr (std::is_same_v<T, lvalue>) {
ret->append(arg); ret->append(arg);
++sz; ++sz;
} else { } 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) if(ctx.error_crash)
{ {
std::exit(-1); std::exit(-1);
@ -473,7 +515,7 @@ namespace lispy {
} else if (*it == '$' || *it == '@') { } else if (*it == '$' || *it == '@') {
auto value = parse_selector(std::string_view{it, (size_t)(data.end() - it)}); auto value = parse_selector(std::string_view{it, (size_t)(data.end() - it)});
ret.push_back(value.first); ret.push_back(value.first);
it += value.second.size()o">+1;
it += value.second.size();
} else { } else {
auto value = parse_atom(std::string_view{it, (size_t)(data.end() - it)}, ctx); auto value = parse_atom(std::string_view{it, (size_t)(data.end() - it)}, ctx);
ret.push_back(value.first); ret.push_back(value.first);
@ -542,6 +584,10 @@ namespace lispy {
} }
} }
namespace lispy_math { namespace lispy_math {
int64_t next_as_int(std::shared_ptr<lispy::cons>& arguments, lispy::context& ctx) { int64_t next_as_int(std::shared_ptr<lispy::cons>& arguments, lispy::context& ctx) {
@ -555,7 +601,8 @@ namespace lispy_math {
} }
return ret; return ret;
} }
std::visit([&](auto arg) {
auto extractor = [&](auto arg) {
using T = std::decay_t<decltype(arg)>; using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int64_t>) { if constexpr (std::is_same_v<T, int64_t>) {
ret = arg; ret = arg;
@ -568,6 +615,15 @@ namespace lispy_math {
std::exit(-1); 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->self);
arguments = arguments->other; arguments = arguments->other;
return ret; return ret;
@ -584,7 +640,8 @@ namespace lispy_math {
} }
return ret; return ret;
} }
std::visit([&](auto arg) {
auto extractor = [&](auto arg) {
using T = std::decay_t<decltype(arg)>; using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int64_t>) { if constexpr (std::is_same_v<T, int64_t>) {
ret = arg; ret = arg;
@ -597,11 +654,89 @@ namespace lispy_math {
std::exit(-1); 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->self);
arguments = arguments->other; arguments = arguments->other;
return ret; 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 { namespace integer_functions {
class plus : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr<lispy::cons> arguments, lispy::context& ctx) { class plus : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr<lispy::cons> arguments, lispy::context& ctx) {
auto p = arguments; auto p = arguments;
@ -683,6 +818,41 @@ namespace lispy_math {
} }
return a%b; 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 { namespace float_functions {
@ -752,6 +922,36 @@ namespace lispy_math {
return a/b; 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) { inline void add_integer_functions(lispy::context& ctx) {
using func_ptr = std::shared_ptr<lispy::function>; 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::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::divide()};
ctx.function_table[ctx.get_atom("%")] = func_ptr{(lispy::function*)new integer_functions::remainder()}; 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) { 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::product()};
ctx.function_table[ctx.get_atom("/.")] = func_ptr{(lispy::function*)new float_functions::divide()}; 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 View File

@ -4,11 +4,29 @@
int main() { int main() {
lispy::context ctx; lispy::context ctx;
ctx.print_parse_results = true; 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_integer_functions(ctx);
lispy_math::add_floatingp_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); lispy::print_types_visitor(std::cout, v, ctx);
std::cout << std::endl; std::cout << std::endl;
lispy::print_visitor(std::cout, v, ctx); 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…
Cancel
Save