*dies of die*

This commit is contained in:
Tyler McGurrin 2025-10-14 13:00:20 -04:00
parent 4e9354a3d9
commit 6f525e2b9d
5 changed files with 99 additions and 10 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
.ccls-cache/
.vscode/
build/
test.x
out.asm

View File

@ -5,7 +5,7 @@ A short and relatively detailed list of all the basics of XILANG. Also yes, the
## Extremly Basic Functions
* `ret` then a value (can be a numeral or a string) will return that value
* `func` then a name (ex: `func main() {}`) allows you to define a new function
* `func` then a name (ex: `func main() {};`) allows you to define a new function
* `import` and a filename (either in `""` or `<>` depending on if it is a local file in the dir or a file from the include path, similar to C) allows you to import the functions from another file (ex: `import Example.xh`)
* `print` then a value will allow to print a character or string to the screen (you can also print any other type of varible)
@ -21,7 +21,8 @@ you define something by doing the type of var you want to define then a name the
## Ifs and Loops
* `if` is pretty simple its just `if x = y {do this}`
* `if` is pretty simple its just `if x = y {do this};`
* `else` if's best friend! simple as `if x = y {}; else {};`
* `loop` is a bit more... dangerous. you can loop... well... basically forever if you were to... forget the value... `loop 100 {print "This"}` or `loop {print "This"}` are both valid ways to use loop, one does the same thing 100 times the other does it until your CPU stops CPUing.
* `while` does something while something is true, for example `while x = 1 {print "This"}` or `while x > 1 {print "This"}`

View File

@ -1,7 +1,7 @@
;This is a comment
global _start
_start:
start:
mov rax, 60
mov rsi, 0
syscall

View File

@ -2,4 +2,4 @@
func main() {
ret 0;
}
};

View File

@ -1,22 +1,108 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <optional>
#include <vector>
#define version "RD-00002"
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
const char *output_filename = "out.asm";
enum class TokenType {
ret,
int_lit,
semicolon,
comment
};
struct Token {
TokenType type;
std::optional<std::string> value {};
};
std::vector<Token> Tokenize(const std::string& str) {
std::vector<Token> Tokens;
std::string buffer {};
for (int i = 0; i < str.length(); i++) {
char c = str.at(i);
if (std::isalpha(c)) {
buffer.push_back(c);
i++;
while (std::isalnum(str.at(i))) {
buffer.push_back(str.at(i));
i++;
}
i--;
if (buffer == "ret") { // return func checkor
Tokens.push_back({.type = TokenType::ret});
buffer.clear();
continue;
}
} else if (std::isdigit(c)) {
buffer.push_back(c);
i++;
while (std::isdigit(str.at(i))) {
buffer.push_back(str.at(i));
i++;
}
i--;
Tokens.push_back({.type = TokenType::int_lit, .value = buffer});
buffer.clear();
}
else if (c == ';') { // legit only checks for a semicolon
Tokens.push_back({.type = TokenType::semicolon});
}
else if (std::isspace(c)) {
continue;
}
}
return Tokens;
}
std::string Tokens_To_Asm(const std::vector<Token>& Tokens) {
std::stringstream output;
output << "global _start\nstart:\n";
for (int i = 0; i < Tokens.size(); i++) {
const Token& Token = Tokens.at(i);
if (Token.type == TokenType::ret) {
if (i + 1 < Tokens.size() && Tokens.at(i+1).type == TokenType::int_lit) {
if (i + 2 < Tokens.size() && Tokens.at(i+2).type == TokenType::semicolon) {
output << " mov rax, 60\n";
output << " mov rdi, " << Tokens.at(i+1).value.value() << "\n";
output << " syscall";
}
}
}
}
return output.str();
}
int main(int argC, char *argV[]) {
if(argC > 2) {
std::cerr << "Usage: xic [OPTIONS] [INPUT FILE]\n" << std::endl;
return EXIT_FAILURE;
}
std::fstream input(argV[1], std::ios::in);
std::string contents;
{
std::stringstream contents_stream;
std::fstream input(argV[1], std::ios::in);
contents_stream << input.rdbuf();
input.close();
contents = contents_stream.str();
}
return 0;
std::vector<Token> Tokens = Tokenize(contents);
{
std::fstream file(output_filename, std::ios::out);
file << Tokens_To_Asm(Tokens);
}
return EXIT_SUCCESS;
}