initial commit

This commit is contained in:
skythedragon
2025-06-24 19:20:33 -07:00
parent fef7dc28e3
commit 1cfb6f4185
8 changed files with 401 additions and 0 deletions

13
CMakeLists.txt Normal file
View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.31)
project(TCompiler VERSION 0.0.0)
set(CMAKE_CXX_STANDARD 23)
add_executable(TFC src/tfc.cpp
src/lexer/Lexer.cpp
src/lexer/Lexer.hpp
src/parser/Parser.cpp
src/parser/Parser.hpp
)
target_compile_options(TFC PRIVATE -Wall -Wextra)
target_compile_definitions(TFC PRIVATE TEST)

17
src/alib/colors.h Normal file
View File

@@ -0,0 +1,17 @@
#define RESET "\033[0m" /* Reset */
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */

222
src/lexer/Lexer.cpp Normal file
View File

@@ -0,0 +1,222 @@
//
// Created by skythedragon on 6/24/25.
//
#include "Lexer.hpp"
#include <iostream>
inline std::string process_octal_escape(std::ifstream& file, char c)
{
std::string oct;
oct += c;
while (true)
{
c = file.get();
if (!std::isdigit(c))
{
std::string ret;
ret += static_cast<char>(std::stoi(oct, nullptr, 8));
ret += c;
return ret;
}
if (std::stoi(oct + c, 0, 8) > 256)
{
std::string ret;
ret += static_cast<char>(std::stoi(oct, nullptr, 8));
ret += c;
return ret;
}
oct += c;
}
}
inline char process_hex_escape(std::ifstream& file)
{
std::string hex;
for (int i = 0; i < 2; i++)
{
char c = file.get();
if (!std::isxdigit(c))
{
if (hex.empty())
{
std::cout << "ERR: Unexpected character '" << c << "', expected hex digit.\n";
exit(1);
}
return static_cast<char>(std::stoi(hex, nullptr, 16));
}
hex += c;
}
return static_cast<char>(std::stoi(hex, nullptr, 16));
}
Lexer::Lexer(std::ifstream& file) : file_(std::move(file)) {}
void Lexer::lex()
{
while (file_.peek() != EOF)
{
char c = file_.get();
if (isalpha(c))
{
std::string lexeme;
lexeme += c;
while (!std::isspace(file_.peek()) && file_.peek() != EOF)
{
lexeme += file_.get();
}
if (lexeme == "exit") {
tokens_.emplace_back(TokenType::exit);
} else {
std::cerr << "ERR: Identifiers not supported " << lexeme << "\n";
exit(1);
}
}
if (isdigit(c))
{
std::string lexeme;
lexeme += c;
bool isnum = false;
bool error = false;
while (std::isdigit(file_.peek()) || file_.peek() == '.')
{
lexeme += file_.get();
if (file_.peek() == '.')
{
isnum = true;
}
if (isnum && file_.peek() == '.')
{
error = true;
break;
}
}
c = file_.get();
if (isalpha(c))
{
std::cerr << "ERR: Literal operators are not yet supported.\n";
exit(1);
}
if (error)
{
std::cerr << "ERR: Ye dun bad\n";
exit(1);
}
if (isnum) {
tokens_.emplace_back(TokenType::number, lexeme);
} else {
tokens_.emplace_back(TokenType::integer, lexeme);
}
}
if (c == '"')
{
std::string lexeme;
while (true)
{
c = file_.get();
if (c == '"')
{
break;
}
if (c == EOF || c == '\n')
{
std::cerr << "ERR: Unterminated string\n";
}
if (c == '\\')
{
c = file_.get();
switch (c)
{
case '"':
case '\\':
lexeme += c;
break;
case 'n':
lexeme += '\n';
break;
case 't':
lexeme += '\t';
break;
case '0':
lexeme += '\0';
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
lexeme += process_octal_escape(file_, c);
break;
case 'x':
case 'X':
lexeme += process_hex_escape(file_);
break;
case 'b':
lexeme += '\b';
break;
case 'a':
lexeme += '\a';
break;
case 'v':
lexeme += '\v';
break;
case 'f':
lexeme += '\f';
break;
default:
std::cerr << "ERR: Improper escape sequence\n";
exit(1);
}
} else {
lexeme += c;
}
}
tokens_.emplace_back(TokenType::string, lexeme);
if (std::isalpha(file_.peek()))
{
std::cerr << "ERR: Literal operators are not yet supported\n";
exit(1);
}
}
if (c == ';')
{
tokens_.emplace_back(TokenType::statement_term);
}
}
}

40
src/lexer/Lexer.hpp Normal file
View File

@@ -0,0 +1,40 @@
//
// Created by skythedragon on 6/24/25.
//
#pragma once
#include <fstream>
#include <string>
#include <vector>
enum class TokenType
{
statement_term,
exit,
integer,
number,
string,
op_plus,
op_minus,
op_multiply,
op_divide
};
struct Token {
TokenType type;
std::optional<std::string> lexeme;
};
class Lexer {
#ifdef TEST
public:
#endif
std::ifstream file_;
std::vector<Token> tokens_;
public:
Lexer(std::ifstream& file);
void lex();
};

5
src/parser/Parser.cpp Normal file
View File

@@ -0,0 +1,5 @@
//
// Created by skythedragon on 6/24/25.
//
#include "Parser.hpp"

18
src/parser/Parser.hpp Normal file
View File

@@ -0,0 +1,18 @@
//
// Created by skythedragon on 6/24/25.
//
#pragma once
#include <vector>
#include "../lexer/Lexer.hpp"
struct ParseNode {
};
struct StatementNode : ParseNode {};
struct RootNode : ParseNode {};
class Parser {
};

84
src/tfc.cpp Normal file
View File

@@ -0,0 +1,84 @@
#include <filesystem>
#include <fstream>
#include <iostream>
#include <vector>
#include "alib/colors.h"
#include "lexer/Lexer.hpp"
using str = std::string;
int main(int argc, char** argv)
{
std::vector<str> args;
for (int i = 1; i < argc; i++)
{
args.emplace_back(argv[i]);
}
if (args.empty())
{
std::cerr << BOLDRED << "Error: " << WHITE << "no input file specified.\n";
exit(1);
}
std::ifstream input(args[0]);
Lexer lexer(input);
lexer.lex();
for (Token& token : lexer.tokens_)
{
str o;
switch (token.type)
{
case TokenType::exit:
o = "exit";
break;
case TokenType::number:
o = "number";
break;
case TokenType::integer:
o = "integer";
break;
case TokenType::op_divide:
o = "op_divide";
break;
case TokenType::string:
o = "string";
break;
case TokenType::op_minus:
o = "op_minus";
break;
case TokenType::op_multiply:
o = "op_multiply";
break;
case TokenType::op_plus:
o = "op_plus";
break;
case TokenType::statement_term:
o = "statement_term";
break;
default:
o = "error";
break;
}
std::cout << o;
if (token.lexeme)
{
std::cout << ": " << *token.lexeme;
}
std::cout << '\n';
}
std::cout << RESET;
return 0;
}

2
test.t Normal file
View File

@@ -0,0 +1,2 @@
exit 0;