parsing my tree frfr
This commit is contained in:
parent
c6e8882be0
commit
5cd0ea9206
24
src/generation.hxx
Normal file
24
src/generation.hxx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "parser.hxx"
|
||||||
|
|
||||||
|
class Generator {
|
||||||
|
public:
|
||||||
|
inline explicit Generator(node::Exit root) : m_root(std::move(root)) {
|
||||||
|
// Erm!!!
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline std::string generate() const {
|
||||||
|
std::stringstream output;
|
||||||
|
output << "global _start\n_start:\n";
|
||||||
|
output << " mov rax, 60\n";
|
||||||
|
output << " mov rdi, " << m_root.expr.int_lit.value.value() << "\n";
|
||||||
|
output << " syscall\n";
|
||||||
|
return output.str();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const node::Exit m_root;
|
||||||
|
};
|
||||||
33
src/main.cxx
33
src/main.cxx
@ -4,27 +4,10 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "parser.hxx"
|
||||||
|
#include "generation.hxx"
|
||||||
#include "tokenization.hxx"
|
#include "tokenization.hxx"
|
||||||
|
|
||||||
std::string tokens_to_asm(std::vector<Token>& tokens) {
|
|
||||||
std::stringstream output;
|
|
||||||
output << "global _start\n_start:\n";
|
|
||||||
for (int i = 0; i < tokens.size(); i++) {
|
|
||||||
const Token& token = tokens.at(i);
|
|
||||||
if (token.type == TokenType::exit) {
|
|
||||||
if (i + 1 < tokens.size() && tokens.at(i + 1).type == TokenType::int_lit) {
|
|
||||||
if (i + 2 < tokens.size() && tokens.at(i + 2).type == TokenType::semi) {
|
|
||||||
output << " mov rax, 60\n";
|
|
||||||
output << " mov rdi, " << tokens.at(i + 1).value.value() << "\n";
|
|
||||||
output << " syscall\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return output.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
std::cerr << "xlang: \033[1;31merror:\033[0m \033[1;37mno input files\033[0m" << std::endl; // yes i spent 10 minutes to emulate clangs output...
|
std::cerr << "xlang: \033[1;31merror:\033[0m \033[1;37mno input files\033[0m" << std::endl; // yes i spent 10 minutes to emulate clangs output...
|
||||||
@ -42,9 +25,19 @@ int main(int argc, char* argv[]) {
|
|||||||
Tokenizer tokenizer(std::move(contents));
|
Tokenizer tokenizer(std::move(contents));
|
||||||
std::vector<Token> tokens = tokenizer.tokenize();
|
std::vector<Token> tokens = tokenizer.tokenize();
|
||||||
|
|
||||||
|
Parser parser(std::move(tokens));
|
||||||
|
std::optional<node::Exit> tree = parser.parse();
|
||||||
|
|
||||||
|
if (!tree.has_value()) {
|
||||||
|
std::cerr << "xlang: \033[1;31merror:\033[0m \033[1;37mparse tree has no value, possibly empty file?\033[0m" << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Generator generator(tree.value());
|
||||||
|
|
||||||
{
|
{
|
||||||
std::fstream output("out.asm", std::ios::out);
|
std::fstream output("out.asm", std::ios::out);
|
||||||
output << tokens_to_asm(tokens);
|
output << generator.generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
system("nasm -felf64 out.asm");
|
system("nasm -felf64 out.asm");
|
||||||
|
|||||||
71
src/parser.hxx
Normal file
71
src/parser.hxx
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "tokenization.hxx"
|
||||||
|
|
||||||
|
namespace node {
|
||||||
|
struct Expr {
|
||||||
|
Token int_lit;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Exit {
|
||||||
|
Expr expr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parser {
|
||||||
|
public:
|
||||||
|
inline explicit Parser(std::vector<Token> tokens) : m_tokens(std::move(tokens)) {
|
||||||
|
// Erm!
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<node::Expr> parse_expr() {
|
||||||
|
if(peek().has_value() && peek().value().type == TokenType::int_lit) {
|
||||||
|
return node::Expr{.int_lit = consume()};
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<node::Exit> parse() {
|
||||||
|
std::optional<node::Exit> exit_node;
|
||||||
|
while(peek().has_value()) {
|
||||||
|
if (peek().value().type == TokenType::exit) {
|
||||||
|
consume();
|
||||||
|
if (auto node_expr = parse_expr()) {
|
||||||
|
exit_node = node::Exit {.expr = node_expr.value()};
|
||||||
|
} else {
|
||||||
|
std::cerr << "xlang: \033[1;31merror:\033[0m \033[1;37minvalid expression\033[0m" << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peek().has_value() && peek().value().type == TokenType::semi) {
|
||||||
|
consume();
|
||||||
|
} else {
|
||||||
|
std::cerr << "xlang: \033[1;31merror:\033[0m \033[1;37minvalid syntax\033[0m" << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_index = 0;
|
||||||
|
return exit_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
[[nodiscard]] inline std::optional<Token> peek(int ahead = 1) const {
|
||||||
|
if (m_index + ahead > m_tokens.size()) {
|
||||||
|
return {};
|
||||||
|
} else {
|
||||||
|
return m_tokens.at(m_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Token consume() {
|
||||||
|
return m_tokens.at(m_index++);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<Token> m_tokens;
|
||||||
|
size_t m_index = 0;
|
||||||
|
};
|
||||||
@ -27,10 +27,10 @@ public:
|
|||||||
std::vector<Token> tokens;
|
std::vector<Token> tokens;
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
|
|
||||||
while (peak().has_value()) {
|
while (peek().has_value()) {
|
||||||
if (std::isalpha(peak().value())) {
|
if (std::isalpha(peek().value())) {
|
||||||
buffer.push_back(consume());
|
buffer.push_back(consume());
|
||||||
while (peak().has_value() && std::isalnum(peak().value())) {
|
while (peek().has_value() && std::isalnum(peek().value())) {
|
||||||
buffer.push_back(consume());
|
buffer.push_back(consume());
|
||||||
}
|
}
|
||||||
if (buffer == "exit") {
|
if (buffer == "exit") {
|
||||||
@ -41,19 +41,19 @@ public:
|
|||||||
std::cerr << "xlang: \033[1;31merror:\033[0m \033[1;37munknown type name \'" << buffer << "\'\033[0m" << std::endl;
|
std::cerr << "xlang: \033[1;31merror:\033[0m \033[1;37munknown type name \'" << buffer << "\'\033[0m" << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
} else if (std::isdigit(peak().value())) {
|
} else if (std::isdigit(peek().value())) {
|
||||||
buffer.push_back(consume());
|
buffer.push_back(consume());
|
||||||
while (peak().has_value() && std::isdigit(peak().value())) {
|
while (peek().has_value() && std::isdigit(peek().value())) {
|
||||||
buffer.push_back(consume());
|
buffer.push_back(consume());
|
||||||
}
|
}
|
||||||
tokens.push_back({.type = TokenType::int_lit, .value = buffer});
|
tokens.push_back({.type = TokenType::int_lit, .value = buffer});
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
continue;
|
continue;
|
||||||
} else if (peak().value() == ';') {
|
} else if (peek().value() == ';') {
|
||||||
consume();
|
consume();
|
||||||
tokens.push_back({.type = TokenType::semi});
|
tokens.push_back({.type = TokenType::semi});
|
||||||
continue;
|
continue;
|
||||||
} else if (std::isspace(peak().value())) {
|
} else if (std::isspace(peek().value())) {
|
||||||
consume();
|
consume();
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
@ -67,7 +67,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] std::optional<char> peak(int ahead = 1) const {
|
[[nodiscard]] inline std::optional<char> peek(int ahead = 1) const {
|
||||||
if (m_index + ahead > m_src.length()) {
|
if (m_index + ahead > m_src.length()) {
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
@ -75,10 +75,10 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char consume() {
|
inline char consume() {
|
||||||
return m_src.at(m_index++);
|
return m_src.at(m_index++);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string m_src;
|
const std::string m_src;
|
||||||
int m_index = 0;
|
size_t m_index = 0;
|
||||||
};
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user