From 650771e6fe6eedc8509cb0256fdbb21b60801cef Mon Sep 17 00:00:00 2001 From: Bobby Lucero Date: Sat, 20 May 2023 16:07:51 -0400 Subject: [PATCH] Initial Commit --- .gitignore | 2 ++ Makefile | 37 +++++++++++++++++++++++ README.md | 1 + headers/Lexer.h | 31 ++++++++++++++++++++ headers/test.h | 14 +++++++++ source.bob | 9 ++++++ src/Lexer.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ src/bob.cpp | 40 +++++++++++++++++++++++++ src/test.cpp | 9 ++++++ 9 files changed, 221 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 headers/Lexer.h create mode 100644 headers/test.h create mode 100644 source.bob create mode 100644 src/Lexer.cpp create mode 100644 src/bob.cpp create mode 100644 src/test.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e524d79 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode/ +build/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..51b581f --- /dev/null +++ b/Makefile @@ -0,0 +1,37 @@ +# Makefile + +# Compiler +CC = g++ + +# Compiler flags +CFLAGS = -Wall -Wextra -std=c++11 + +# Source directory +SRC_DIR = ./src + +# Output directory +BUILD_DIR = ./build + +# Get all CPP files in the source directory +CPP_FILES := $(wildcard $(SRC_DIR)/*.cpp) + +# Generate object file names by replacing the source directory with the build directory +OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_DIR)/%.o,$(CPP_FILES)) + +# Default target +all: $(BUILD_DIR)/bob + +# Rule to create the build directory if it doesn't exist +$(shell mkdir -p $(BUILD_DIR)) + +# Rule to compile object files +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp + $(CC) $(CFLAGS) -c $< -o $@ + +# Rule to link object files into the final executable +$(BUILD_DIR)/bob: $(OBJ_FILES) + $(CC) $(CFLAGS) $^ -o $@ + +# Clean build directory +clean: + rm -rf $(BUILD_DIR)/* diff --git a/README.md b/README.md new file mode 100644 index 0000000..d01fdce --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Bob diff --git a/headers/Lexer.h b/headers/Lexer.h new file mode 100644 index 0000000..d9edbce --- /dev/null +++ b/headers/Lexer.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +enum TokenType{ + Identifier, + Number, + Equals, + OpenParenthesis, + CloseParenthesis, + BinaryOperator, + Test +}; + +const std::map KEYWORDS { + {"test", Test} +}; + +struct Token +{ + TokenType type; + std::string value; +}; + + +class Lexer{ +public: + std::vector Tokenize(std::string source); + +}; diff --git a/headers/test.h b/headers/test.h new file mode 100644 index 0000000..c64536b --- /dev/null +++ b/headers/test.h @@ -0,0 +1,14 @@ + +#include +#include + +class Test +{ +public: + std::string message; + + Test(std::string msg); + +public: + void Hello(); +}; \ No newline at end of file diff --git a/source.bob b/source.bob new file mode 100644 index 0000000..61c423f --- /dev/null +++ b/source.bob @@ -0,0 +1,9 @@ +x = 45 * ( 4 / 3 ) * (45 / (20 * 3)) +x = 45 * ( 4 / 3 ) * (45 / (20 * 3)) +x = 45 * ( 4 / 3 ) * (45 / (20 * 3)) +x = 45 * ( 4 / 3 ) * (45 / (20 * 3)) +x = 45 * ( 4 / 3 ) * (45 / (20 * 3)) +x = 45 * ( 4 / 3 ) * (45 / (20 * 3)) +x = 45 * ( 4 / 3 ) * (45 / (20 * 3)) +x = 45 * ( 4 / 3 ) * (45 / (20 * 3)) +x = 45 * ( 4 / 3 ) * (45 / (20 * 3)) \ No newline at end of file diff --git a/src/Lexer.cpp b/src/Lexer.cpp new file mode 100644 index 0000000..2901089 --- /dev/null +++ b/src/Lexer.cpp @@ -0,0 +1,78 @@ +#include "../headers/Lexer.h" +#include +#include + +std::vector Lexer::Tokenize(std::string source){ + std::vector tokens; + std::vector src{source.begin(), source.end()}; + + while(src.size() > 0) + { + char t = src[0]; + if(t == '(') + { + tokens.push_back(Token{OpenParenthesis, std::string(1, t)}); //brace initialization in case you forget + src.erase(src.begin()); + } + else if(t == ')') + { + tokens.push_back(Token{CloseParenthesis, std::string(1, t)}); + src.erase(src.begin()); + } + else if(t == '+' || t == '-' || t == '*' || t == '/') + { + tokens.push_back(Token{BinaryOperator, std::string(1, t)}); + src.erase(src.begin()); + } + else if(t == '=') + { + tokens.push_back(Token{Equals, std::string(1, t)}); + src.erase(src.begin()); + } + else + { + //Multi char tokens + if(std::isdigit(t)) + { + std::string num = ""; + while(src.size() > 0 && std::isdigit(src[0])) + { + num += src[0]; + src.erase(src.begin()); + } + + tokens.push_back(Token{Number, num}); + } + else if(std::isalpha(t)) + { + std::string ident = ""; + while(src.size() > 0 && std::isalpha(src[0])) + { + ident += src[0]; + src.erase(src.begin()); + } + + if(KEYWORDS.find(ident) != KEYWORDS.end()) //identifier is a keyword + { + tokens.push_back(Token{KEYWORDS.at(ident), ident}); + } + else + { + tokens.push_back(Token{Identifier, ident}); + } + + } + else if(t == ' ' || t == '\t' || t == '\n') + { + src.erase(src.begin()); + } + else + { + throw std::runtime_error("Unknown Token: '" + std::string(1, t) + "'"); + } + } + + } + + return tokens; +} diff --git a/src/bob.cpp b/src/bob.cpp new file mode 100644 index 0000000..fc2879d --- /dev/null +++ b/src/bob.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include "../headers/Lexer.h" + +using namespace std; + +int main(){ + + string TokenTypeMappings[] = { + "Identifier", + "Number", + "Equals", + "OpenParen", + "CloseParen", + "BinaryOperator", + "TestKeyword" + }; + Lexer l; + + string path = "source.bob"; + ifstream file = ifstream(path); + + string source = ""; + + if(file.is_open()){ + source = string(istreambuf_iterator(file), istreambuf_iterator()); + } + else + { + cout << "File not found" << endl; + } + + + vector tokens = l.Tokenize(source); + for(Token t : tokens){ + cout << "Type: " << TokenTypeMappings[t.type] << ", Value: " + t.value << endl; + } + return 0; +} diff --git a/src/test.cpp b/src/test.cpp new file mode 100644 index 0000000..02edaac --- /dev/null +++ b/src/test.cpp @@ -0,0 +1,9 @@ +#include "../headers/test.h" + +Test::Test(std::string msg){ + this->message = msg; +} + +void Test::Hello(){ + std::cout << this->message << std::endl; +} \ No newline at end of file