diff --git a/.gitignore b/.gitignore index 3bd52ca..999acfa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .ccls-cache/ .vscode/ -build/ \ No newline at end of file +build/ +test.x +out.asm \ No newline at end of file diff --git a/documentation/Basics.md b/documentation/Basics.md index 0a70899..50f958a 100644 --- a/documentation/Basics.md +++ b/documentation/Basics.md @@ -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"}` diff --git a/examples/return.s b/examples/return.s index ec8b1e4..78e02c4 100644 --- a/examples/return.s +++ b/examples/return.s @@ -1,7 +1,7 @@ ;This is a comment global _start -_start: +start: mov rax, 60 mov rsi, 0 syscall \ No newline at end of file diff --git a/examples/return.x b/examples/return.x index beff8df..10a0f13 100644 --- a/examples/return.x +++ b/examples/return.x @@ -2,4 +2,4 @@ func main() { ret 0; -} +}; diff --git a/src/main.cxx b/src/main.cxx index 81214a4..a366317 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -1,22 +1,108 @@ #include #include #include +#include +#include #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 value {}; +}; + +std::vector Tokenize(const std::string& str) { + std::vector 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& 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::stringstream contents_stream; - contents_stream << input.rdbuf(); - input.close(); + std::string contents; + { + std::stringstream contents_stream; + std::fstream input(argV[1], std::ios::in); + contents_stream << input.rdbuf(); + contents = contents_stream.str(); + } - return 0; + std::vector Tokens = Tokenize(contents); + + { + std::fstream file(output_filename, std::ios::out); + file << Tokens_To_Asm(Tokens); + } + + return EXIT_SUCCESS; } \ No newline at end of file