diff --git a/documentation/lang/Grammar.md b/documentation/lang/Grammar.md new file mode 100644 index 0000000..4b5be7c --- /dev/null +++ b/documentation/lang/Grammar.md @@ -0,0 +1,10 @@ +# Grammar +Basically just an outline of how to type things out and how things work syntactically. +$$ +\begin{align} +[\text{exit}] &\to exit([\text{expr}]); +\\ +[\text{expr}] &\to \text{int\_lit} +\end{align} +$$ +### Note: i hate laytec or however you spell it. Its hell. \ No newline at end of file diff --git a/documentation/lang/Limitations.md b/documentation/lang/Limitations.md new file mode 100644 index 0000000..0c5e0a7 --- /dev/null +++ b/documentation/lang/Limitations.md @@ -0,0 +1,2 @@ +# Some limits of the lang +- Cannot have varible names or funtion names that start with a number, they MUST start with a letter. they however can contain numbers. \ No newline at end of file diff --git a/examples/compact.x b/examples/compact.x deleted file mode 100644 index f023caf..0000000 --- a/examples/compact.x +++ /dev/null @@ -1 +0,0 @@ -return 0; \ No newline at end of file diff --git a/examples/exitcompact.x b/examples/exitcompact.x new file mode 100644 index 0000000..fe99dd5 --- /dev/null +++ b/examples/exitcompact.x @@ -0,0 +1 @@ +exit 11; \ No newline at end of file diff --git a/src/main.cxx b/src/main.cxx index bbe029d..cf011cb 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -4,69 +4,14 @@ #include #include -enum class TokenType { - _return, - int_lit, - semi, -}; - -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++) { - // Words - if (std::isalpha(str.at(i))) { - buffer.push_back(str.at(i)); - i++; - while (std::isalnum(str.at(i))) { - buffer.push_back(str.at(i)); - i++; - } - i--; - if (buffer == "return") { - tokens.push_back({.type = TokenType::_return}); - buffer.clear(); - continue; - } else { - std::cerr << "xlang: \033[1;31merror:\033[0m \033[1;37munknown type name \'" << buffer << "\'\033[0m" << std::endl; - exit(EXIT_FAILURE); - } - } else if (std::isdigit(str.at(i))) { // Handle Numbers - buffer.push_back(str.at(i)); - i++; - while (std::isdigit(str.at(i))) { // im going insane - buffer.push_back(str.at(i)); - i++; - } - i--; - tokens.push_back({.type = TokenType::int_lit, .value = buffer}); - buffer.clear(); - } else if (str.at(i) == ';') { - tokens.push_back({.type = TokenType::semi}); - } else if (std::isspace(str.at(i))) { // Handle White Space - continue; - } else { - std::cerr << "xlang: \033[1;31merror:\033[0m \033[1;37munknown type name \'" << buffer << "\'\033[0m" << std::endl; - exit(EXIT_FAILURE); - } - } - - // Return mah shit - return tokens; -} +#include "tokenization.hxx" std::string tokens_to_asm(std::vector& 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::_return) { + 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"; @@ -94,7 +39,8 @@ int main(int argc, char* argv[]) { contents = contents_stream.str(); } - std::vector tokens = tokenize(contents); + Tokenizer tokenizer(std::move(contents)); + std::vector tokens = tokenizer.tokenize(); { std::fstream output("out.asm", std::ios::out); diff --git a/src/tokenization.hxx b/src/tokenization.hxx new file mode 100644 index 0000000..50c7a77 --- /dev/null +++ b/src/tokenization.hxx @@ -0,0 +1,84 @@ +#pragma once + +#include +#include +#include +#include +#include + +enum class TokenType { + exit, + int_lit, + semi, +}; + +struct Token { + TokenType type; + std::optional value {}; +}; + +class Tokenizer { +public: + inline explicit Tokenizer(const std::string& src) : m_src(std::move(src)) { + // Erm erm erm erm erm... i like erm + } + + inline std::vector tokenize() { + std::vector tokens; + std::string buffer; + + while (peak().has_value()) { + if (std::isalpha(peak().value())) { + buffer.push_back(consume()); + while (peak().has_value() && std::isalnum(peak().value())) { + buffer.push_back(consume()); + } + if (buffer == "exit") { + tokens.push_back({.type = TokenType::exit}); + buffer.clear(); + continue; + } else { + std::cerr << "xlang: \033[1;31merror:\033[0m \033[1;37munknown type name \'" << buffer << "\'\033[0m" << std::endl; + exit(EXIT_FAILURE); + } + } else if (std::isdigit(peak().value())) { + buffer.push_back(consume()); + while (peak().has_value() && std::isdigit(peak().value())) { + buffer.push_back(consume()); + } + tokens.push_back({.type = TokenType::int_lit, .value = buffer}); + buffer.clear(); + continue; + } else if (peak().value() == ';') { + consume(); + tokens.push_back({.type = TokenType::semi}); + continue; + } else if (std::isspace(peak().value())) { + consume(); + continue; + } else { + std::cerr << "xlang: \033[1;31merror:\033[0m \033[1;37munknown type name \'" << buffer << "\'\033[0m" << std::endl; + exit(EXIT_FAILURE); + } + } + // Return mah shit + m_index = 0; + return tokens; + } + +private: + [[nodiscard]] std::optional peak(int ahead = 1) const { + if (m_index + ahead > m_src.length()) { + return {}; + } else { + return m_src.at(m_index); + } + } + + char consume() { + return m_src.at(m_index++); + } + + const std::string m_src; + int m_index = 0; +}; \ No newline at end of file