sm parser: instuction builder

This commit is contained in:
ProgramSnail 2025-05-18 14:32:42 +03:00
parent 956dde00a3
commit a7f2377124
3 changed files with 201 additions and 57 deletions

View file

@ -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,

View file

@ -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.

View file

@ -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();
}