From 29be54af13f487ba57c14d4d385273d5705e4677 Mon Sep 17 00:00:00 2001 From: Ludovic 'Archivist' Lagouardette Date: Thu, 15 Aug 2019 11:43:48 +0200 Subject: [PATCH] CSV parse now parses lisp correctly --- .gitignore | 1 + include/rigid_paradise/lispy/lispy.hpp | 226 ++++++++++++++++++++++++- src/csv-sheet/csv-parse.cpp | 20 ++- 3 files changed, 237 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index d60e5a6..53f3795 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build/* vgcore.* a.out +\#* diff --git a/include/rigid_paradise/lispy/lispy.hpp b/include/rigid_paradise/lispy/lispy.hpp index bddf0cd..dd3b0d1 100644 --- a/include/rigid_paradise/lispy/lispy.hpp +++ b/include/rigid_paradise/lispy/lispy.hpp @@ -46,6 +46,24 @@ namespace lispy { std::unordered_map> function_table; std::unordered_map variable_table; + std::function 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 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(*(oth.other))) : std::shared_ptr{}) + , other(oth.other ? std::make_shared(*(oth.other)) : std::shared_ptr{}) {} 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) { 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) { - 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) { 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()+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& 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; if constexpr (std::is_same_v) { ret = arg; @@ -568,6 +615,15 @@ namespace lispy_math { std::exit(-1); } } + }; + + std::visit([&](auto arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + 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; if constexpr (std::is_same_v) { ret = arg; @@ -597,11 +654,89 @@ namespace lispy_math { std::exit(-1); } } + }; + + std::visit([&](auto arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + 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& 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; + if constexpr (std::is_same_v) { + src = arg; + } else if constexpr (std::is_same_v>) { + 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; + if constexpr (std::is_same_v) { + std::visit(extractor, ctx.resolve_range(arg)); + } else if constexpr (std::is_same_v>) { + 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 dest; + + std::visit([&](auto arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) {} + else if constexpr (std::is_same_v>) { + dest = std::make_shared(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 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 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 ret = std::make_shared(a); + a+=1; + for(;aappend(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 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>(cells)) { + ret += lispy_math::next_as_floating(std::get>(cells), ctx); + } + + return ret; + }}; + }; + + + + inline void add_integer_functions(lispy::context& ctx) { using func_ptr = std::shared_ptr; @@ -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; + + ctx.function_table[ctx.get_atom("sum")] = func_ptr{(lispy::function*)new aggregate_functions::sum()}; + } } \ No newline at end of file diff --git a/src/csv-sheet/csv-parse.cpp b/src/csv-sheet/csv-parse.cpp index 3eb1067..ce2b6c1 100644 --- a/src/csv-sheet/csv-parse.cpp +++ b/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; + } } \ No newline at end of file