mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-05 22:38:44 +00:00
sm parser: instuction builder
This commit is contained in:
parent
956dde00a3
commit
a7f2377124
3 changed files with 201 additions and 57 deletions
|
|
@ -5,6 +5,14 @@
|
|||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace utils {
|
||||
// https://en.cppreference.com/w/cpp/utility/variant/visit2
|
||||
template <class... Ts> struct multifunc : Ts... {
|
||||
using Ts::operator()...;
|
||||
};
|
||||
template <class... Ts> multifunc(Ts...) -> multifunc<Ts...>;
|
||||
} // namespace utils
|
||||
|
||||
enum class Patt {
|
||||
BOXED,
|
||||
UNBOXED,
|
||||
|
|
|
|||
|
|
@ -16,12 +16,6 @@
|
|||
|
||||
namespace utils {
|
||||
|
||||
// https://en.cppreference.com/w/cpp/utility/variant/visit2
|
||||
template <class... Ts> struct multifunc : Ts... {
|
||||
using Ts::operator()...;
|
||||
};
|
||||
template <class... Ts> multifunc(Ts...) -> multifunc<Ts...>;
|
||||
|
||||
// https://en.cppreference.com/w/cpp/utility/unreachable
|
||||
[[noreturn]] inline void unreachable() {
|
||||
// Uses compiler specific extensions if possible.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#include "sm_parser.hpp"
|
||||
|
||||
#include <any>
|
||||
#include <charconv>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
|
||||
std::vector<SMInstr> parse_sm(std::istream &in) {
|
||||
|
|
@ -28,13 +28,6 @@ std::vector<SMInstr> parse_sm(std::istream &in) {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::optional<std::pair<size_t, std::string::iterator>>
|
||||
parse(std::string::iterator begin, std::string::iterator end) {
|
||||
size_t result = 0;
|
||||
std::from_chars(&*begin, &*end, result);
|
||||
// TODO
|
||||
}
|
||||
|
||||
std::string substr_to(const std::string &line, size_t &pos, char to) {
|
||||
auto offset = line.find(pos, to);
|
||||
|
||||
|
|
@ -48,29 +41,169 @@ std::string substr_to(const std::string &line, size_t &pos, char to) {
|
|||
return result;
|
||||
}
|
||||
|
||||
// TODO: parsers + combinators
|
||||
|
||||
// parse_str
|
||||
// parse_int
|
||||
// parse_bool
|
||||
// parse_opr
|
||||
// parse_patt
|
||||
// parse_var
|
||||
|
||||
// parse_array
|
||||
// parse_scope
|
||||
|
||||
// parse_or
|
||||
|
||||
struct SMInstrBuilder {
|
||||
public:
|
||||
SMInstrBuilder(SMInstr instr) : instr(instr), args_pushed(0) {}
|
||||
SMInstrBuilder(SMInstr instr) : instr(instr) {}
|
||||
|
||||
SMInstr build() {
|
||||
// TODO: check for all arps
|
||||
return instr;
|
||||
std::optional<SMInstr> build() {
|
||||
// TODO: check too many args ??
|
||||
try {
|
||||
// TODO: check for all args present
|
||||
return {std::visit<SMInstr>( //
|
||||
utils::multifunc{
|
||||
//
|
||||
[&args = args](SMInstr::PUBLIC x) -> SMInstr {
|
||||
x.name = std::any_cast<std::string>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::EXTERN x) -> SMInstr {
|
||||
x.name = std::any_cast<std::string>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::IMPORT x) -> SMInstr {
|
||||
x.name = std::any_cast<std::string>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::CLOSURE x) -> SMInstr {
|
||||
x.name = std::any_cast<int>(args.at(0));
|
||||
x.closure = std::any_cast<std::vector<ValT>>(args.at(1));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::CONST x) -> SMInstr {
|
||||
x.n = std::any_cast<int>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::STRING x) -> SMInstr {
|
||||
x.str = std::any_cast<std::string>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::LDA x) -> SMInstr {
|
||||
x.v = std::any_cast<ValT>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::LD x) -> SMInstr {
|
||||
x.v = std::any_cast<ValT>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::ST x) -> SMInstr {
|
||||
x.v = std::any_cast<ValT>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[](SMInstr::STA x) -> SMInstr { return x; },
|
||||
[](SMInstr::STI x) -> SMInstr { return x; },
|
||||
[&args = args](SMInstr::BINOP x) -> SMInstr {
|
||||
x.opr = std::any_cast<Opr>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::LABEL x) -> SMInstr {
|
||||
x.s = std::any_cast<std::string>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::FLABEL x) -> SMInstr {
|
||||
x.s = std::any_cast<std::string>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::SLABEL x) -> SMInstr {
|
||||
x.s = std::any_cast<std::string>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::JMP x) -> SMInstr {
|
||||
x.l = std::any_cast<std::string>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::CJMP x) -> SMInstr {
|
||||
x.s = std::any_cast<std::string>(args.at(0));
|
||||
x.l = std::any_cast<std::string>(args.at(1));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::BEGIN x) -> SMInstr {
|
||||
x.f = std::any_cast<std::string>(args.at(0));
|
||||
x.nargs = std::any_cast<int>(args.at(1));
|
||||
x.nlocals = std::any_cast<int>(args.at(2));
|
||||
x.closure = std::any_cast<std::vector<ValT>>(args.at(3));
|
||||
x.args = std::any_cast<std::vector<std::string>>(args.at(4));
|
||||
x.scopes = std::any_cast<std::vector<Scope>>(args.at(5));
|
||||
return x;
|
||||
},
|
||||
[](SMInstr::END x) -> SMInstr { return x; },
|
||||
[](SMInstr::RET x) -> SMInstr { return x; },
|
||||
[](SMInstr::ELEM x) -> SMInstr { return x; },
|
||||
[&args = args](SMInstr::CALL x) -> SMInstr {
|
||||
x.fname = std::any_cast<std::string>(args.at(0));
|
||||
x.n = std::any_cast<int>(args.at(1));
|
||||
x.tail = std::any_cast<bool>(args.at(2));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::CALLC x) -> SMInstr {
|
||||
x.n = std::any_cast<int>(args.at(1));
|
||||
x.tail = std::any_cast<bool>(args.at(2));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::SEXP x) -> SMInstr {
|
||||
x.tag = std::any_cast<std::string>(args.at(0));
|
||||
x.n = std::any_cast<int>(args.at(1));
|
||||
return x;
|
||||
},
|
||||
[](SMInstr::DROP x) -> SMInstr { return x; },
|
||||
[](SMInstr::DUP x) -> SMInstr { return x; },
|
||||
[](SMInstr::SWAP x) -> SMInstr { return x; },
|
||||
[&args = args](SMInstr::TAG x) -> SMInstr {
|
||||
x.tag = std::any_cast<std::string>(args.at(0));
|
||||
x.n = std::any_cast<int>(args.at(1));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::ARRAY x) -> SMInstr {
|
||||
x.n = std::any_cast<int>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::PATT x) -> SMInstr {
|
||||
x.patt = std::any_cast<Patt>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::LINE x) -> SMInstr {
|
||||
x.n = std::any_cast<int>(args.at(0));
|
||||
return x;
|
||||
},
|
||||
[&args = args](SMInstr::FAIL x) -> SMInstr {
|
||||
x.line = std::any_cast<int>(args.at(0));
|
||||
x.col = std::any_cast<int>(args.at(1));
|
||||
x.val = std::any_cast<bool>(args.at(2));
|
||||
return x;
|
||||
},
|
||||
// [](auto) -> SMInstr {
|
||||
// throw std::bad_any_cast{}; // create another error ?
|
||||
// },
|
||||
},
|
||||
*instr)};
|
||||
} catch (const std::bad_any_cast &) {
|
||||
return {};
|
||||
} catch (const std::out_of_range &) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
void push_arg(std::string &&value) {}
|
||||
void push_arg(bool value) {}
|
||||
void push_arg(int value) {}
|
||||
void push_arg(ValT value) {}
|
||||
void push_arg(Patt value) {}
|
||||
template <typename T> void push_arg(T &&value) { args.emplace_back(value); }
|
||||
|
||||
private:
|
||||
SMInstr instr;
|
||||
size_t args_pushed = 0;
|
||||
}
|
||||
std::vector<std::any> args;
|
||||
};
|
||||
|
||||
std::optional<SMInstr>
|
||||
parse_sm(const std::string &line) {
|
||||
std::optional<SMInstr> parse_sm(const std::string &line) {
|
||||
std::unordered_map<std::string, SMInstr> to_instr = {
|
||||
{"BINOP", SMInstr{SMInstr::BINOP{}}},
|
||||
{"CONST", SMInstr{SMInstr::CONST{}}},
|
||||
|
|
@ -106,8 +239,6 @@ parse_sm(const std::string &line) {
|
|||
{"LINE", SMInstr{SMInstr::LINE{}}},
|
||||
};
|
||||
|
||||
char ch; // NOTE: for helpers
|
||||
|
||||
size_t pos = 0;
|
||||
std::string cmd = substr_to(line, pos, ' ');
|
||||
|
||||
|
|
@ -126,35 +257,46 @@ parse_sm(const std::string &line) {
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool was_last_arg = false;
|
||||
while (!was_last_arg) {
|
||||
std::string arg = substr_to(line, pos, '(');
|
||||
++pos;
|
||||
// TODO: Automatically parse any structures with parser combinators
|
||||
// if (cmd == "BEGIN") {
|
||||
// // TODO: BEGIN
|
||||
// } else {
|
||||
|
||||
if (arg.empty()) {
|
||||
arg = line.substr(pos);
|
||||
arg.pop_back(); // ')'
|
||||
was_last_arg = true;
|
||||
}
|
||||
// bool was_last_arg = false;
|
||||
// while (!was_last_arg) {
|
||||
// std::string arg = substr_to(line, pos, '(');
|
||||
// ++pos;
|
||||
|
||||
if (arg.front() == '"') {
|
||||
instr.push_arg(arg.substr(1, arg.size() - 2));
|
||||
} else if (arg == "true") {
|
||||
instr.push_arg(true);
|
||||
} else if (arg == "false") {
|
||||
instr.push_arg(false);
|
||||
} else if () { // TODO: Local, Global, Arg
|
||||
} else if () { // TODO: BEGIN vectors, etc
|
||||
} else if () { // TODO: PATT patterns
|
||||
} else if () { // TODO: CLUSURE vector
|
||||
} else if (int n = 0; std::from_chars(line.data() + pos,
|
||||
line.data() + pos + line.size(), n)
|
||||
.ec == std::errc{}) {
|
||||
instr.push_arg(n);
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
// if (arg.empty()) {
|
||||
// arg = line.substr(pos);
|
||||
// arg.pop_back(); // ')'
|
||||
// was_last_arg = true;
|
||||
// }
|
||||
|
||||
// if (arg.front() == '"') {
|
||||
// instr.push_arg(arg.substr(1, arg.size() - 2));
|
||||
// } else if (arg.front() == '[') {
|
||||
// // TODO: parse array
|
||||
// instr.push_arg(arg.substr(1, arg.size() - 2));
|
||||
// } else if (arg == "true") {
|
||||
// instr.push_arg(true);
|
||||
// } else if (arg == "false") {
|
||||
// instr.push_arg(false);
|
||||
// } else if (auto maybe_var = parse_var(arg); maybe_var) {
|
||||
// instr.push_arg(*maybe_var);
|
||||
// } else if () { // TODO: CLUSURE vector
|
||||
// } else if (auto maybe_patt = parse_patt(arg); maybe_patt) {
|
||||
// instr.push_arg(*maybe_patt);
|
||||
// } else if (int n = 0; std::from_chars(line.data() + pos,
|
||||
// line.data() + pos + line.size(),
|
||||
// n)
|
||||
// .ec == std::errc{}) {
|
||||
// instr.push_arg(n);
|
||||
// } else {
|
||||
// return std::nullopt;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return instr.build();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue