From d7cd4947b37a168034e9fca2501d98553fdcc137 Mon Sep 17 00:00:00 2001
From: Ferenc Szontágh <szf@fsociety.hu>
Date: Mon, 14 Apr 2025 19:49:49 +0000
Subject: [PATCH] refactor phase1
---
include/BaseFunction.hpp | 1
include/SymbolFactory.hpp | 58 +++
include/VariableTypes.hpp | 46 ++
src/ScriptInterpreterHelpers.hpp | 11
src/ScriptInterpreter.cpp | 142 +++-----
src/StringHelpers.hpp | 20 +
include/ConstantSymbol.hpp | 28 +
include/SymbolTable.hpp | 67 ++++
CMakeLists.txt | 5
include/VariableSymbol.hpp | 20 +
include/FunctionSymbol.hpp | 31 +
/dev/null | 64 ----
include/BaseSymbol.hpp | 51 +++
include/SymbolContainer.hpp | 51 +++
src/Lexer.hpp | 8
src/Lexer.cpp | 100 +++---
include/SymbolKind.hpp | 18 +
src/Token.hpp | 200 +++---------
include/SymbolTypes.hpp | 22 +
19 files changed, 587 insertions(+), 356 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 29ae97b..013b4c9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -97,8 +97,6 @@
set(ARCHITECTURE "amd64")
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(ARCHITECTURE "i386")
- else()
- message(STATUS "Célarchitektúra: Nem meghatározható (CMAKE_SIZEOF_VOID_P: ${CMAKE_SIZEOF_VOID_P})")
endif()
endif()
@@ -115,7 +113,8 @@
configure_file("test_scripts/test1.vs" "test_scripts/test1.vs" @ONLY)
configure_file("test_scripts/test2.vs" "test_scripts/test2.vs" @ONLY)
-include_directories(${CMAKE_BINARY_DIR}/include src)
+include_directories(${CMAKE_BINARY_DIR}/include ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/include)
+
# LIBRARY TARGET
add_library(voidscript
diff --git a/src/BaseFunction.hpp b/include/BaseFunction.hpp
similarity index 98%
rename from src/BaseFunction.hpp
rename to include/BaseFunction.hpp
index 9038dbc..3cedf31 100644
--- a/src/BaseFunction.hpp
+++ b/include/BaseFunction.hpp
@@ -2,7 +2,6 @@
#define SCRIPT_FUNCTION_HPP
#include <functional>
-#include <stdexcept>
#include <unordered_map>
#include <utility>
#include <vector>
diff --git a/include/BaseSymbol.hpp b/include/BaseSymbol.hpp
new file mode 100644
index 0000000..b326e4b
--- /dev/null
+++ b/include/BaseSymbol.hpp
@@ -0,0 +1,51 @@
+// BaseSymbol.hpp
+#ifndef BASE_SYMBOL_HPP
+#define BASE_SYMBOL_HPP
+
+#include <string>
+#include <variant>
+
+#include "SymbolKind.hpp"
+
+namespace Symbols {
+
+using Value = std::variant<int, double, std::string, bool>;
+
+class Symbol {
+ protected:
+ std::string name_;
+ Value value_;
+ std::string context_;
+ Symbols::Kind kind_;
+
+ public:
+ Symbol(const std::string & name, const Value & value, const std::string & context, Symbols::Kind type) :
+ name_(name),
+ value_(value),
+ context_(context),
+ kind_(type) {}
+
+ virtual ~Symbol() = default;
+
+ // Polimorf azonosító
+ virtual Symbols::Kind kind() const = 0;
+
+ // Getterek
+ const std::string & name() const { return name_; }
+
+ const std::string & context() const { return context_; }
+
+ Symbols::Kind type() const { return kind_; }
+
+ // Virtuális getter/setter a value-hoz
+ virtual const Value & getValue() const { return value_; }
+
+ virtual void setValue(const Value & value) { value_ = value; }
+
+ // Templated getter
+ template <typename T> T getAs() const { return std::get<T>(value_); }
+};
+
+} // namespace Symbols
+
+#endif
diff --git a/include/ConstantSymbol.hpp b/include/ConstantSymbol.hpp
new file mode 100644
index 0000000..da78d79
--- /dev/null
+++ b/include/ConstantSymbol.hpp
@@ -0,0 +1,28 @@
+// ConstantSymbol.hpp
+#ifndef CONSTANT_SYMBOL_HPP
+#define CONSTANT_SYMBOL_HPP
+
+#include <stdexcept>
+
+#include "BaseSymbol.hpp"
+#include "VariableTypes.hpp"
+
+namespace Symbols {
+
+class ConstantSymbol : public Symbol {
+ protected:
+ Symbols::Variables::Type _vartype;
+ public:
+ ConstantSymbol(const std::string & name, const Symbols::Value & value, const std::string & context) :
+ Symbol(name, value, context, Symbols::Kind::Constant) {}
+
+ Symbols::Kind kind() const override { return Symbols::Kind::Constant; }
+
+ void setValue(const Symbols::Value & /*value*/) override {
+ throw std::logic_error("Cannot modify a constant symbol");
+ }
+};
+
+} // namespace Symbols
+
+#endif
diff --git a/include/FunctionSymbol.hpp b/include/FunctionSymbol.hpp
new file mode 100644
index 0000000..97c23f8
--- /dev/null
+++ b/include/FunctionSymbol.hpp
@@ -0,0 +1,31 @@
+// FunctionSymbol.hpp
+#ifndef FUNCTION_SYMBOL_HPP
+#define FUNCTION_SYMBOL_HPP
+
+#include <vector>
+
+#include "BaseSymbol.hpp"
+
+namespace Symbols {
+using ValueContainer = std::vector<Symbols::Value>;
+
+class FunctionSymbol : public Symbol {
+ std::vector<Symbols::Value> parameters_;
+ Symbols::Value returnType_;
+ std::string plainBody_;
+
+ public:
+ FunctionSymbol(const std::string & name, const std::string & context, const ValueContainer & parameters,
+ const std::string & plainbody = "") :
+ Symbol(name, {}, context, Symbols::Kind::Function),
+ parameters_(parameters),
+ plainBody_(plainbody) {}
+
+ Symbols::Kind kind() const override { return Symbols::Kind::Function; }
+
+ const ValueContainer & parameters() const { return parameters_; }
+};
+
+} // namespace Symbols
+
+#endif
diff --git a/include/SymbolContainer.hpp b/include/SymbolContainer.hpp
new file mode 100644
index 0000000..1985c50
--- /dev/null
+++ b/include/SymbolContainer.hpp
@@ -0,0 +1,51 @@
+// SymbolContainer.hpp
+#ifndef SYMBOL_CONTAINER_HPP
+#define SYMBOL_CONTAINER_HPP
+
+#include "SymbolTable.hpp"
+
+namespace Symbols {
+
+class SymbolContainer {
+ std::shared_ptr<SymbolTable> globalScope_;
+ std::shared_ptr<SymbolTable> currentScope_;
+
+public:
+ SymbolContainer() {
+ globalScope_ = std::make_shared<SymbolTable>();
+ currentScope_ = globalScope_;
+ }
+
+ void enterScope() {
+ currentScope_ = std::make_shared<SymbolTable>(currentScope_);
+ }
+
+ void leaveScope() {
+ if (currentScope_->getParent()) {
+ currentScope_ = currentScope_->getParent();
+ }
+ }
+
+ void define(const std::string& ns, const SymbolPtr& symbol) {
+ currentScope_->define(ns, symbol);
+ }
+
+ SymbolPtr resolve(const std::string& ns, const std::string& name) const {
+ return currentScope_->get(ns, name);
+ }
+
+ bool exists(const std::string& ns, const std::string& name) const {
+ return currentScope_->exists(ns, name);
+ }
+
+ std::vector<SymbolPtr> listNamespace(const std::string& ns) const {
+ return currentScope_->listAll(ns);
+ }
+
+ std::shared_ptr<SymbolTable> getGlobalScope() const { return globalScope_; }
+ std::shared_ptr<SymbolTable> getCurrentScope() const { return currentScope_; }
+};
+
+} // namespace Symbols
+
+#endif
diff --git a/include/SymbolFactory.hpp b/include/SymbolFactory.hpp
new file mode 100644
index 0000000..da37e15
--- /dev/null
+++ b/include/SymbolFactory.hpp
@@ -0,0 +1,58 @@
+// SymbolFactory.hpp
+#ifndef SYMBOL_FACTORY_HPP
+#define SYMBOL_FACTORY_HPP
+
+#include <memory>
+#include <string>
+
+#include "ConstantSymbol.hpp"
+#include "FunctionSymbol.hpp"
+#include "VariableSymbol.hpp"
+
+namespace Symbols {
+
+class SymbolFactory {
+ public:
+ static std::shared_ptr<Symbol> createVariable(const std::string & name, const Symbols::Value & value,
+ const std::string & context, Variables::Type type) {
+ return std::make_shared<VariableSymbol>(name, value, context, type);
+ }
+
+ static std::shared_ptr<Symbol> createConstant(const std::string & name, const Symbols::Value & value,
+ const std::string & context) {
+ return std::make_shared<ConstantSymbol>(name, value, context);
+ }
+
+ static std::shared_ptr<Symbol> createFunction(const std::string & name, const std::string & context,
+ const Symbols::ValueContainer & parameters = {}) {
+ return std::make_shared<FunctionSymbol>(name, context, parameters);
+ }
+
+ static std::shared_ptr<Symbol> createFunction(const std::string & name, const std::string & context,
+ const Symbols::ValueContainer & parameters,
+ const std::string & plainBody) {
+ return std::make_shared<FunctionSymbol>(name, context, parameters, plainBody);
+ }
+
+ // Overloadok
+ static std::shared_ptr<Symbol> createVariable(const std::string & name, int value, const std::string & context) {
+ return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::VT_INT);
+ }
+
+ static std::shared_ptr<Symbol> createVariable(const std::string & name, double value, const std::string & context) {
+ return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::VT_DOUBLE);
+ }
+
+ static std::shared_ptr<Symbol> createVariable(const std::string & name, const std::string & value,
+ const std::string & context) {
+ return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::VT_STRING);
+ }
+
+ static std::shared_ptr<Symbol> createVariable(const std::string & name, bool value, const std::string & context) {
+ return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::VT_BOOLEAN);
+ }
+};
+
+} // namespace Symbols
+
+#endif
diff --git a/include/SymbolKind.hpp b/include/SymbolKind.hpp
new file mode 100644
index 0000000..5f9c8e8
--- /dev/null
+++ b/include/SymbolKind.hpp
@@ -0,0 +1,18 @@
+// SymbolKind.hpp
+#ifndef SYMBOL_KIND_HPP
+#define SYMBOL_KIND_HPP
+
+#include <cstdint>
+
+namespace Symbols {
+
+enum class Kind : std::uint8_t {
+ Variable,
+ Constant,
+ Function
+ // Later: Module, Class, etc..
+};
+
+}; // namespace Symbols
+
+#endif
diff --git a/include/SymbolTable.hpp b/include/SymbolTable.hpp
new file mode 100644
index 0000000..db23889
--- /dev/null
+++ b/include/SymbolTable.hpp
@@ -0,0 +1,67 @@
+// SymbolTable.hpp
+#ifndef SYMBOL_TABLE_HPP
+#define SYMBOL_TABLE_HPP
+
+#include <memory>
+#include <optional>
+#include <vector>
+
+#include "SymbolTypes.hpp"
+
+namespace Symbols {
+
+class SymbolTable {
+ NamespaceMap symbols_;
+ std::shared_ptr<SymbolTable> parent_ = nullptr;
+
+ public:
+ SymbolTable(std::shared_ptr<SymbolTable> parent = nullptr) : parent_(std::move(parent)) {}
+
+ void define(const std::string & ns, const SymbolPtr & symbol) { symbols_[ns][symbol->name()] = symbol; }
+
+ bool exists(const std::string & ns, const std::string & name) const { return get(ns, name) != nullptr; }
+
+ SymbolPtr get(const std::string & ns, const std::string & name) const {
+ auto itNs = symbols_.find(ns);
+ if (itNs != symbols_.end()) {
+ const auto & map = itNs->second;
+ auto it = map.find(name);
+ if (it != map.end()) {
+ return it->second;
+ }
+ }
+ // Rekurzívan keresünk a szülő scope-ban
+ if (parent_) {
+ return parent_->get(ns, name);
+ }
+ return nullptr;
+ }
+
+ void remove(const std::string & ns, const std::string & name) {
+ auto itNs = symbols_.find(ns);
+ if (itNs != symbols_.end()) {
+ itNs->second.erase(name);
+ }
+ }
+
+ std::vector<SymbolPtr> listAll(const std::string & ns) const {
+ std::vector<SymbolPtr> result;
+ auto it = symbols_.find(ns);
+ if (it != symbols_.end()) {
+ for (const auto & [_, sym] : it->second) {
+ result.push_back(sym);
+ }
+ }
+ return result;
+ }
+
+ void clear(const std::string & ns) { symbols_.erase(ns); }
+
+ void clearAll() { symbols_.clear(); }
+
+ std::shared_ptr<SymbolTable> getParent() const { return parent_; }
+};
+
+} // namespace Symbols
+
+#endif
diff --git a/include/SymbolTypes.hpp b/include/SymbolTypes.hpp
new file mode 100644
index 0000000..ec0f773
--- /dev/null
+++ b/include/SymbolTypes.hpp
@@ -0,0 +1,22 @@
+// SymbolTypes.hpp
+#ifndef SYMBOL_TYPES_HPP
+#define SYMBOL_TYPES_HPP
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "BaseSymbol.hpp"
+
+namespace Symbols {
+
+
+using SymbolPtr = std::shared_ptr<Symbol>;
+
+// Namespace -> név -> szimbólum
+using SymbolMap = std::unordered_map<std::string, SymbolPtr>;
+using NamespaceMap = std::unordered_map<std::string, SymbolMap>;
+
+} // namespace Symbols
+
+#endif
diff --git a/include/VariableSymbol.hpp b/include/VariableSymbol.hpp
new file mode 100644
index 0000000..652565e
--- /dev/null
+++ b/include/VariableSymbol.hpp
@@ -0,0 +1,20 @@
+// VariableSymbol.hpp
+#ifndef VARIABLE_SYMBOL_HPP
+#define VARIABLE_SYMBOL_HPP
+
+#include "BaseSymbol.hpp"
+
+namespace Symbols {
+
+class VariableSymbol : public Symbol {
+ public:
+ VariableSymbol(const std::string & name, const Symbols::Value & value, const std::string & context,
+ Symbols::Kind type) :
+ Symbol(name, value, context, type) {}
+
+ Symbols::Kind kind() const override { return Symbols::Kind::Variable; }
+};
+
+} // namespace Symbols
+
+#endif
diff --git a/include/VariableTypes.hpp b/include/VariableTypes.hpp
new file mode 100644
index 0000000..8ac087d
--- /dev/null
+++ b/include/VariableTypes.hpp
@@ -0,0 +1,46 @@
+#ifndef VARIABLE_TYPES_HPP
+#define VARIABLE_TYPES_HPP
+
+#include <cstdint>
+#include <string>
+#include <unordered_map>
+
+namespace Symbols::Variables {
+
+enum class Type : std::uint8_t { VT_INT, VT_DOUBLE, VT_STRING, VT_BOOLEAN, VT_NULL, VT_UNDEFINED };
+
+const std::unordered_map<std::string, Type> StringToTypeMap = {
+ { "int", Type::VT_INT },
+ { "double", Type::VT_DOUBLE },
+ { "string", Type::VT_STRING },
+ { "bool", Type::VT_BOOLEAN },
+ { "boolean", Type::VT_BOOLEAN },
+ { "null", Type::VT_NULL },
+
+ { "undefined", Type::VT_UNDEFINED },
+};
+const std::unordered_map<Type, std::string> StypeToStringMap = {
+ { Type::VT_INT, "int" },
+ { Type::VT_DOUBLE, "double" },
+ { Type::VT_STRING, "string" },
+ { Type::VT_BOOLEAN, "bool" },
+ { Type::VT_NULL, "null" },
+ { Type::VT_UNDEFINED, "undeffined" },
+};
+
+inline static std::string TypeToString(Type type) {
+ if (StypeToStringMap.find(type) != StypeToStringMap.end()) {
+ return StypeToStringMap.at(type);
+ }
+ return "null";
+};
+
+inline static Type StringToType(const std::string & type) {
+ if (StringToTypeMap.find(type) != StringToTypeMap.end()) {
+ return StringToTypeMap.at(type);
+ }
+ return Type::VT_NULL;
+};
+
+}; // namespace Symbols
+#endif // VARIABLE_TYPES_HPP
diff --git a/src/Lexer.cpp b/src/Lexer.cpp
index 441ee40..362e4b8 100644
--- a/src/Lexer.cpp
+++ b/src/Lexer.cpp
@@ -40,14 +40,14 @@
return pos >= src.size();
}
-Token Lexer::createToken(TokenType type, const std::string & lexeme) const {
+Tokens::Token Lexer::createToken(Tokens::Type type, const std::string & lexeme) const {
size_t startChar = charNumber - lexeme.length();
return {
type, lexeme, filename, lineNumber, colNumber - lexeme.length(), { startChar, charNumber }
};
}
-Token Lexer::createSingleCharToken(TokenType type, const std::string & lexeme) {
+Tokens::Token Lexer::createSingleCharToken(Tokens::Type type, const std::string & lexeme) {
size_t startCol = colNumber;
size_t startChar = charNumber;
advance();
@@ -56,14 +56,14 @@
};
}
-Token Lexer::createUnknownToken(const std::string & lexeme) const {
+Tokens::Token Lexer::createUnknownToken(const std::string & lexeme) const {
size_t startChar = charNumber - lexeme.length();
return {
- TokenType::Unknown, lexeme, filename, lineNumber, colNumber - lexeme.length(), { startChar, charNumber }
+ Tokens::Type::Unknown, lexeme, filename, lineNumber, colNumber - lexeme.length(), { startChar, charNumber }
};
}
-Token Lexer::stringToken() {
+Tokens::Token Lexer::stringToken() {
std::string result;
size_t startChar = charNumber;
size_t startCol = colNumber;
@@ -73,28 +73,28 @@
}
if (isAtEnd() || peek() != '"') {
return {
- TokenType::Unknown, "Unterminated string", filename, lineNumber, startCol, { startChar, pos }
+ Tokens::Type::Unknown, "Unterminated string", filename, lineNumber, startCol, { startChar, pos }
};
}
advance(); // Skip closing quote
return {
- TokenType::StringLiteral, result, filename, lineNumber, startCol, { startChar, pos }
+ Tokens::Type::StringLiteral, result, filename, lineNumber, startCol, { startChar, pos }
};
}
-Token Lexer::numberToken() {
- std::string result;
- std::string found;
- TokenType type = TokenType::Unknown;
- bool decimalPointSeen = false;
- size_t startChar = charNumber;
- size_t startCol = colNumber;
+Tokens::Token Lexer::numberToken() {
+ std::string result;
+ std::string found;
+ Tokens::Type type = Tokens::Type::Unknown;
+ bool decimalPointSeen = false;
+ size_t startChar = charNumber;
+ size_t startCol = colNumber;
while (std::isdigit(peek()) || peek() == '.') {
if (peek() == '.') {
if (decimalPointSeen) {
return {
- TokenType::Unknown, "Invalid number format", filename, lineNumber, startCol, { startChar, pos }
+ Tokens::Type::Unknown, "Invalid number format", filename, lineNumber, startCol, { startChar, pos }
};
}
decimalPointSeen = true;
@@ -106,25 +106,25 @@
if (found.find('.') == std::string::npos) {
if (is_number<int>(found)) {
result = found;
- type = TokenType::IntLiteral;
+ type = Tokens::Type::IntLiteral;
} else {
return {
- TokenType::Unknown, "Invalid integer", filename, lineNumber, startCol, { startChar, pos }
+ Tokens::Type::Unknown, "Invalid integer", filename, lineNumber, startCol, { startChar, pos }
};
}
} else {
if (is_number<double>(found)) {
result = found;
- type = TokenType::DoubleLiteral;
+ type = Tokens::Type::DoubleLiteral;
} else {
return {
- TokenType::Unknown, "Invalid double", filename, lineNumber, startCol, { startChar, pos }
+ Tokens::Type::Unknown, "Invalid double", filename, lineNumber, startCol, { startChar, pos }
};
}
}
} else {
return {
- TokenType::Unknown, "Expected number", filename, lineNumber, startCol, { startChar, pos }
+ Tokens::Type::Unknown, "Expected number", filename, lineNumber, startCol, { startChar, pos }
};
}
@@ -133,7 +133,7 @@
};
}
-Token Lexer::identifierToken() {
+Tokens::Token Lexer::identifierToken() {
std::string result;
size_t startChar = charNumber;
size_t startCol = colNumber;
@@ -141,11 +141,11 @@
result += advance();
}
return {
- TokenType::Identifier, result, filename, lineNumber, startCol, { startChar, pos }
+ Tokens::Type::Identifier, result, filename, lineNumber, startCol, { startChar, pos }
};
}
-Token Lexer::variableToken() {
+Tokens::Token Lexer::variableToken() {
size_t startChar = charNumber;
size_t startCol = colNumber;
advance(); // Skip $
@@ -156,15 +156,15 @@
varName += advance();
}
return {
- TokenType::Variable, varName, filename, lineNumber, startCol, { startChar, pos }
+ Tokens::Type::Variable, varName, filename, lineNumber, startCol, { startChar, pos }
};
}
return {
- TokenType::Unknown, "$ followed by invalid character", filename, lineNumber, startCol, { startChar, pos }
+ Tokens::Type::Unknown, "$ followed by invalid character", filename, lineNumber, startCol, { startChar, pos }
};
}
-Token Lexer::commentToken() {
+Tokens::Token Lexer::commentToken() {
size_t startChar = charNumber;
size_t startCol = colNumber;
advance(); // Skip #
@@ -173,11 +173,11 @@
commentText += advance();
}
return {
- TokenType::Comment, commentText, filename, lineNumber, startCol, { startChar, pos }
+ Tokens::Type::Comment, commentText, filename, lineNumber, startCol, { startChar, pos }
};
}
-Token Lexer::keywordOrIdentifierToken() {
+Tokens::Token Lexer::keywordOrIdentifierToken() {
std::string lexeme;
while (isalpha(peek())) {
lexeme += advance();
@@ -187,14 +187,14 @@
}
if (lexeme == IDENTIFIER_RETURN) {
- return createToken(TokenType::Return, lexeme);
+ return createToken(Tokens::Type::Return, lexeme);
}
if (lexeme == IDENTIFIER_IF) {
- return createToken(TokenType::ParserIfStatement, lexeme);
+ return createToken(Tokens::Type::ParserIfStatement, lexeme);
}
if (peek() == '(') { // Function call
- return createToken(TokenType::FunctionCall, lexeme);
+ return createToken(Tokens::Type::FunctionCall, lexeme);
}
auto it = Variables::StringToTypeMap.find(lexeme);
@@ -207,12 +207,12 @@
if (peek() == IDENTIFIER_VARIABLE) {
return this->variableDeclarationToken(type);
}
- return createToken(TokenType::Identifier, lexeme);
+ return createToken(Tokens::Type::Identifier, lexeme);
}
- return createToken(TokenType::Identifier, lexeme);
+ return createToken(Tokens::Type::Identifier, lexeme);
}
-Token Lexer::functionDeclarationToken() {
+Tokens::Token Lexer::functionDeclarationToken() {
advance(); // Skip function
std::string functionName;
if (isalpha(peek()) || peek() == '_') {
@@ -220,12 +220,12 @@
while (isalnum(peek()) || peek() == '_') {
functionName += advance();
}
- return createToken(TokenType::FunctionDeclaration, functionName);
+ return createToken(Tokens::Type::FunctionDeclaration, functionName);
}
return createUnknownToken("function followed by invalid character");
}
-Token Lexer::variableDeclarationToken(Variables::Type type) {
+Tokens::Token Lexer::variableDeclarationToken(Variables::Type type) {
advance(); // Skip $
std::string varName;
if (isalpha(peek()) || peek() == '_') {
@@ -269,8 +269,8 @@
}
}
-std::vector<Token> Lexer::tokenize() {
- std::vector<Token> tokens;
+std::vector<Tokens::Token> Lexer::tokenize() {
+ std::vector<Tokens::Token> tokens;
tokens.reserve(src.size() / 4);
while (pos < src.size()) {
@@ -281,7 +281,7 @@
continue;
}
if (c == '\n') {
- tokens.push_back(createSingleCharToken(TokenType::EndOfLine, "\n"));
+ tokens.push_back(createSingleCharToken(Tokens::Type::EndOfLine, "\n"));
continue;
}
if (c == IDENTIFIER_COMMENT) {
@@ -291,12 +291,12 @@
}
if (matchSequence(PARSER_OPEN_TAG)) {
matchAndConsume(PARSER_OPEN_TAG);
- tokens.push_back(createToken(TokenType::ParserOpenTag, PARSER_OPEN_TAG));
+ tokens.push_back(createToken(Tokens::Type::ParserOpenTag, PARSER_OPEN_TAG));
continue;
}
if (matchSequence(PARSER_CLOSE_TAG)) {
matchAndConsume(PARSER_CLOSE_TAG);
- tokens.push_back(createToken(TokenType::ParserCloseTag, PARSER_CLOSE_TAG));
+ tokens.push_back(createToken(Tokens::Type::ParserCloseTag, PARSER_CLOSE_TAG));
continue;
}
switch (c) {
@@ -315,28 +315,28 @@
tokens.push_back(stringToken());
break;
case '(':
- tokens.push_back(createSingleCharToken(TokenType::LeftParenthesis, "("));
+ tokens.push_back(createSingleCharToken(Tokens::Type::LeftParenthesis, "("));
break;
case ')':
- tokens.push_back(createSingleCharToken(TokenType::RightParenthesis, ")"));
+ tokens.push_back(createSingleCharToken(Tokens::Type::RightParenthesis, ")"));
break;
case ',':
- tokens.push_back(createSingleCharToken(TokenType::Comma, ","));
+ tokens.push_back(createSingleCharToken(Tokens::Type::Comma, ","));
break;
case ';':
- tokens.push_back(createSingleCharToken(TokenType::Semicolon, ";"));
+ tokens.push_back(createSingleCharToken(Tokens::Type::Semicolon, ";"));
break;
case '=':
- tokens.push_back(createSingleCharToken(TokenType::Equals, "="));
+ tokens.push_back(createSingleCharToken(Tokens::Type::Equals, "="));
break;
case '+':
- tokens.push_back(createSingleCharToken(TokenType::Plus, "+"));
+ tokens.push_back(createSingleCharToken(Tokens::Type::Plus, "+"));
break;
case '{':
- tokens.push_back(createSingleCharToken(TokenType::LeftCurlyBracket, "{"));
+ tokens.push_back(createSingleCharToken(Tokens::Type::LeftCurlyBracket, "{"));
break;
case '}':
- tokens.push_back(createSingleCharToken(TokenType::RightCurlyBracket, "}"));
+ tokens.push_back(createSingleCharToken(Tokens::Type::RightCurlyBracket, "}"));
break;
default:
tokens.push_back(createUnknownToken(std::string(1, c)));
@@ -346,7 +346,7 @@
}
tokens.push_back({
- TokenType::EndOfFile, "", filename, lineNumber, colNumber, { charNumber, charNumber }
+ Tokens::Type::EndOfFile, "", filename, lineNumber, colNumber, { charNumber, charNumber }
});
return tokens;
}
diff --git a/src/Lexer.hpp b/src/Lexer.hpp
index 1207dd9..7274e47 100644
--- a/src/Lexer.hpp
+++ b/src/Lexer.hpp
@@ -6,6 +6,7 @@
#include <sstream>
#include <vector>
+#include "StringHelpers.hpp"
#include "Token.hpp"
#include "VariableTypes.hpp"
@@ -66,11 +67,8 @@
std::string srcSubstr = src.substr(pos, sequence.length());
std::string seqLower = sequence;
- std::transform(srcSubstr.begin(), srcSubstr.end(), srcSubstr.begin(),
- [](unsigned char c) { return std::tolower(c); });
-
- std::transform(seqLower.begin(), seqLower.end(), seqLower.begin(),
- [](unsigned char c) { return std::tolower(c); });
+ StringHelpers::strtolower(srcSubstr);
+ StringHelpers::strtolower(seqLower);
return srcSubstr == seqLower;
}
diff --git a/src/ScriptInterpreter.cpp b/src/ScriptInterpreter.cpp
index 1f353cf..8af8d43 100644
--- a/src/ScriptInterpreter.cpp
+++ b/src/ScriptInterpreter.cpp
@@ -14,37 +14,40 @@
}
Value ScriptInterpreter::evaluateExpression(const Token & token) const {
- if (token.type == TokenType::StringLiteral) {
- return Value::fromString(token);
+ switch (token.type) {
+ case TokenType::StringLiteral:
+ return Value::fromString(token);
+
+ case TokenType::IntLiteral:
+ try {
+ return Value::fromInt(token);
+ } catch (const std::invalid_argument & e) {
+ throw std::runtime_error("Invalid integer literal: " + token.lexeme);
+ } catch (const std::out_of_range & e) {
+ throw std::runtime_error("Integer literal out of range: " + token.lexeme);
+ }
+
+ case TokenType::DoubleLiteral:
+ try {
+ return Value::fromDouble(token);
+ } catch (const std::invalid_argument & e) {
+ throw std::runtime_error("Invalid double literal: " + token.lexeme);
+ } catch (const std::out_of_range & e) {
+ throw std::runtime_error("Double literal out of range: " + token.lexeme);
+ }
+
+ case TokenType::BooleanLiteral:
+ case TokenType::Identifier:
+ {
+ return Value::fromBoolean(token);
+ }
+
+ case TokenType::Variable:
+ return this->getVariable(token, this->contextPrefix, __FILE__, __LINE__);
+
+ default:
+ THROW_UNEXPECTED_TOKEN_ERROR(token, "string, integer, double, or variable");
}
- if (token.type == TokenType::IntLiteral) {
- try {
- return Value::fromInt(token);
- } catch (const std::invalid_argument & e) {
- throw std::runtime_error("Invalid integer literal: " + token.lexeme);
- } catch (const std::out_of_range & e) {
- throw std::runtime_error("Integer literal out of range: " + token.lexeme);
- }
- }
- if (token.type == TokenType::DoubleLiteral) {
- try {
- return Value::fromDouble(token);
- } catch (const std::invalid_argument & e) {
- throw std::runtime_error("Invalid double literal: " + token.lexeme);
- } catch (const std::out_of_range & e) {
- throw std::runtime_error("Double literal out of range: " + token.lexeme);
- }
- }
- if (token.type == TokenType::BooleanLiteral || token.type == TokenType::Identifier) {
- std::string lowered = token.lexeme;
- std::transform(lowered.begin(), lowered.end(), lowered.begin(),
- [](unsigned char c) { return std::tolower(c); });
- return Value::fromBoolean(token, (lowered == "true" ? true : false));
- }
- if (token.type == TokenType::Variable) {
- return this->getVariable(token, this->contextPrefix, __FILE__, __LINE__);
- }
- THROW_UNEXPECTED_TOKEN_ERROR(token, "string, integer, double, or variable");
return Value();
}
@@ -81,62 +84,39 @@
return args;
}
-void ScriptInterpreter::handleBooleanDeclaration(const std::vector<Token> & tokens, std::size_t & i) {
- const auto & varToken = tokens[i];
- i++; // Skip variable name
- if (i < tokens.size() && tokens[i].type == TokenType::Equals) {
- i++; // Skip '='
+void ScriptInterpreter::handleBooleanDeclaration(const std::vector<Token> & tokens, size_t & i) {
+ if (tokens.size() <= i || tokens[i].type != TokenType::Identifier) {
+ THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "variable name");
+ }
- if (i < tokens.size() && tokens[i].type == TokenType::Variable) {
- auto variable = this->getVariable(tokens[i], this->contextPrefix, __FILE__, __LINE__);
+ const Token & varToken = tokens[i++];
+ if (i >= tokens.size()) {
+ THROW_UNEXPECTED_TOKEN_ERROR(tokens[i + 1], "semicolon or assignment after variable name");
+ }
- if (variable.type != Variables::Type::VT_BOOLEAN) {
- THROW_VARIABLE_TYPE_MISSMATCH_ERROR(varToken.lexeme,
- Variables::TypeToString(Variables::Type::VT_BOOLEAN),
- tokens[i].lexeme, variable.TypeToString(), tokens[i]);
- }
- this->setVariable(varToken.lexeme, variable, this->contextPrefix, true);
- i++; // Skip variable name
- EXPECT_SEMICOLON(tokens, i, "after bool variable declaration");
-
- } else if (i < tokens.size() &&
- (tokens[i].type == TokenType::Identifier || tokens[i].type == TokenType::StringLiteral)) {
- std::string lowered = tokens[i].lexeme;
- std::transform(lowered.begin(), lowered.end(), lowered.begin(),
- [](unsigned char c) { return std::tolower(c); });
-
- if (lowered == "true") {
- auto value = Value::fromBoolean(tokens[i], true);
- this->setVariable(varToken.lexeme, value, this->contextPrefix, true);
- } else if (lowered == "false") {
- auto value = Value::fromBoolean(tokens[i], false);
- this->setVariable(varToken.lexeme, value, this->contextPrefix, true);
- } else {
- THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "true or false after '='");
- }
- i++; // Skip boolean literal
- EXPECT_SEMICOLON(tokens, i, "after bool declaration");
- } else if (i < tokens.size() && tokens[i].type == TokenType::IntLiteral) {
- const auto test = std::stoi(tokens[i].lexeme);
- if (test == 0) {
- auto value = Value::fromBoolean(tokens[i], false);
- this->setVariable(varToken.lexeme, value, this->contextPrefix, true);
- } else if (test > 0) {
- auto value = Value::fromBoolean(tokens[i], false);
- this->setVariable(varToken.lexeme, value, this->contextPrefix, true);
- } else {
- THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "bool literal after '='");
- }
- i++;
- EXPECT_SEMICOLON(tokens, i, "after bool declaration");
- } else {
- THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "bool literal after '='");
+ if (tokens[i].type == TokenType::Semicolon) {
+ auto val = Value::fromBoolean(tokens[i]);
+ this->setVariable(varToken.lexeme, val, this->contextPrefix, true);
+ i++;
+ } else if (tokens[i].type == TokenType::Equal) {
+ i++;
+ if (i >= tokens.size()) {
+ //throw InterpreterException("Expected value after assignment.", tokens[i - 1]);
+ THROW_UNEXPECTED_TOKEN_ERROR(tokens[i - 1], "value after assignment");
}
+ auto value = evaluateExpression(tokens[i]);
+ if (value.type != Variables::Type::VT_BOOLEAN) {
+ THROW_VARIABLE_TYPE_MISSMATCH_ERROR(varToken.lexeme, Variables::TypeToString(Variables::Type::VT_BOOLEAN),
+ tokens[i].lexeme, value.TypeToString(), tokens[i]);
+ }
+ this->setVariable(varToken.lexeme, value, this->contextPrefix, true);
+ i++;
+ EXPECT_SEMICOLON(tokens, i, "after bool declaration");
} else {
- THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "= after bool declaration");
+ EXPECT_SEMICOLON(tokens, i, "after bool declaration");
}
-};
+}
void ScriptInterpreter::handleStringDeclaration(const std::vector<Token> & tokens, std::size_t & i) {
const auto & varToken = tokens[i];
@@ -242,7 +222,7 @@
size_t end;
ScriptInterpreterHelpers::getFunctionBody(tokens, i, start, end);
- const std::string function_body = ScriptInterpreterHelpers::extractSubstring(this->source, start, end);
+ const std::string function_body = StringHelpers::extractSubstring(this->source, start, end);
if (function_body.empty()) {
std::cout << this->source << '\n';
THROW_FUNCTION_BODY_EMPTY(funcToken.lexeme, tokens[i - 1]);
diff --git a/src/ScriptInterpreterHelpers.hpp b/src/ScriptInterpreterHelpers.hpp
index bff499f..a8567fc 100644
--- a/src/ScriptInterpreterHelpers.hpp
+++ b/src/ScriptInterpreterHelpers.hpp
@@ -1,8 +1,7 @@
#ifndef SCRIPTINTERPRETERHELPERS_HPP
#define SCRIPTINTERPRETERHELPERS_HPP
-#include <iostream>
-#include <ostream>
+#include <algorithm>
#include <vector>
#include "ScriptExceptionMacros.h"
@@ -14,12 +13,7 @@
namespace ScriptInterpreterHelpers {
-static std::string extractSubstring(const std::string & str, const size_t & start, const size_t & end) {
- if (start >= 0 && start < str.length() && end >= start && end < str.length()) {
- return str.substr(start, end - start + 1);
- }
- return "";
-}
+
static void expectSemicolon(const std::vector<Token> & tokens, std::size_t & i, const std::string & message,
const std::string & file = __FILE__, int line = __LINE__) {
@@ -98,6 +92,7 @@
}
};
+
}; // namespace ScriptInterpreterHelpers
#endif // SCRIPTINTERPRETERHELPERS_HPP
diff --git a/src/StringHelpers.hpp b/src/StringHelpers.hpp
new file mode 100644
index 0000000..937959f
--- /dev/null
+++ b/src/StringHelpers.hpp
@@ -0,0 +1,20 @@
+#ifndef STRINGHELPERS_HPP
+#define STRINGHELPERS_HPP
+#include <algorithm>
+#include <string>
+
+namespace StringHelpers {
+
+static std::string extractSubstring(const std::string & str, const size_t & start, const size_t & end) {
+ if (start >= 0 && start < str.length() && end >= start && end < str.length()) {
+ return str.substr(start, end - start + 1);
+ }
+ return "";
+}
+
+static void strtolower(std::string & data) {
+ std::transform(data.begin(), data.end(), data.begin(), [](unsigned char c) { return std::tolower(c); });
+}
+
+}; // namespace StringHelpers
+#endif // STRINGHELPERS_HPP
diff --git a/src/Token.hpp b/src/Token.hpp
index 201d84b..564356a 100644
--- a/src/Token.hpp
+++ b/src/Token.hpp
@@ -1,13 +1,11 @@
#ifndef TOKEN_HPP
#define TOKEN_HPP
#include <cstdint>
-#include <iostream>
#include <string>
#include <unordered_map>
-#include "VariableTypes.hpp"
-
-enum class TokenType : std::uint8_t {
+namespace Tokens {
+enum class Type : std::uint8_t {
ParserOpenTag,
ParserCloseTag,
ParserIfStatement, // if
@@ -55,135 +53,52 @@
Unknown // Unknown
};
-const static std::unordered_map<TokenType, std::string> tokenTypeNames = {
- { TokenType::ParserOpenTag, "ParserOpenTag" },
- { TokenType::ParserCloseTag, "ParserCloseTag" },
- { TokenType::ParserIfStatement, "ParserIfStatement" },
- { TokenType::FileClose, "FileClose" },
- { TokenType::Identifier, "Identifier" },
- { TokenType::StringLiteral, "StringLiteral" },
- { TokenType::IntLiteral, "IntLiteral" },
- { TokenType::DoubleLiteral, "DoubleLiteral" },
- { TokenType::BooleanLiteral, "BooleanLiteral" },
- { TokenType::LeftParenthesis, "LeftParenthesis" },
- { TokenType::RightParenthesis, "RightParenthesis" },
- { TokenType::Comma, "Comma" },
- { TokenType::Semicolon, "Semicolon" },
- { TokenType::Variable, "Variable" },
- { TokenType::VariableSign, "VariableSign" },
- { TokenType::StringDeclaration, "StringDeclaration" },
- { TokenType::IntDeclaration, "IntDeclaration" },
- { TokenType::DoubleDeclaration, "DoubleDeclaration" },
- { TokenType::BooleanDeclaration, "BooleanDeclaration" },
- { TokenType::FunctionDeclaration, "FunctionDeclaration" },
- { TokenType::FunctionCall, "FunctionCall" },
- { TokenType::Return, "Return" },
- { TokenType::Equals, "Equals" },
- { TokenType::Plus, "Plus" },
- { TokenType::Minus, "Minus" },
- { TokenType::Multiply, "Multiply" },
- { TokenType::Divide, "Divide" },
- { TokenType::Modulo, "Modulo" },
- { TokenType::GreaterThan, "GreaterThan" },
- { TokenType::LessThan, "LessThan" },
- { TokenType::GreaterThanOrEqual, "GreaterThanOrEqual" },
- { TokenType::LessThanOrEqual, "LessThanOrEqual" },
- { TokenType::NotEqual, "NotEqual" },
- { TokenType::Equal, "Equal" },
- { TokenType::Not, "Not" },
- { TokenType::And, "And" },
- { TokenType::Or, "Or" },
- { TokenType::LeftBracket, "LeftBracket" },
- { TokenType::RightBracket, "RightBracket" },
- { TokenType::LeftCurlyBracket, "LeftCurlyBracket" },
- { TokenType::RightCurlyBracket, "RightCurlyBracket" },
- { TokenType::EndOfFile, "EndOfFile" },
- { TokenType::EndOfLine, "EndOfLine" },
- { TokenType::Comment, "Comment" },
- { TokenType::Unknown, "Unknown" }
-};
-
-[[nodiscard]] static inline std::string getTokenTypeAsString(TokenType type) {
- auto it = tokenTypeNames.find(type);
- if (it != tokenTypeNames.end()) {
- return it->second;
- }
- return "Unknown";
- //throw std::runtime_error("Unknown token type");
-};
-
-static const std::unordered_map<TokenType, Variables::Type> tokenTypeToVariableType = {
- { TokenType::StringLiteral, Variables::Type::VT_STRING },
- { TokenType::IntLiteral, Variables::Type::VT_INT },
- { TokenType::DoubleLiteral, Variables::Type::VT_DOUBLE },
- { TokenType::BooleanLiteral, Variables::Type::VT_BOOLEAN }
-};
-
-static const std::unordered_map<Variables::Type, TokenType> variableTypeToTokenType = {
- { Variables::Type::VT_STRING, TokenType::StringLiteral },
- { Variables::Type::VT_INT, TokenType::IntLiteral },
- { Variables::Type::VT_DOUBLE, TokenType::DoubleLiteral },
- { Variables::Type::VT_BOOLEAN, TokenType::BooleanLiteral }
-};
-
-[[nodiscard]] static inline Variables::Type getVariableTypeFromTokenType(TokenType type) {
- auto it = tokenTypeToVariableType.find(type);
- if (it != tokenTypeToVariableType.end()) {
- return it->second;
- }
-
- return Variables::Type::VT_NOT_DEFINED;
-}
-
-[[nodiscard]] static inline std::string getVariableTypeFromTokenTypeAsString(TokenType type) {
- return Variables::TypeToString(getVariableTypeFromTokenType(type));
-}
-
-[[nodiscard]] static inline TokenType getTokenTypeFromVariableType(Variables::Type type) {
- auto it = variableTypeToTokenType.find(type);
- if (it != variableTypeToTokenType.end()) {
- return it->second;
- }
- return TokenType::Unknown;
-};
-
-[[nodiscard]] static inline TokenType getTokenTypeFromValueDeclaration(const Variables::Type & declaration) {
- if (declaration == Variables::Type::VT_STRING) {
- return TokenType::StringDeclaration;
- }
- if (declaration == Variables::Type::VT_INT) {
- return TokenType::IntDeclaration;
- }
- if (declaration == Variables::Type::VT_DOUBLE) {
- return TokenType::DoubleDeclaration;
- }
- if (declaration == Variables::Type::VT_BOOLEAN) {
- return TokenType::BooleanDeclaration;
- }
- // if (declaration == Variables::Type::VT_FUNCTION) {
- // return TokenType::FunctionDeclaration;
- // }
- std::cout << "Unknown variable type: " << Variables::TypeToString(declaration) << "\n";
- return TokenType::Unknown;
-}
-
-[[nodiscard]] static inline Variables::Type getVariableTypeFromTokenTypeDeclaration(const TokenType & type) {
- if (type == TokenType::StringDeclaration) {
- return Variables::Type::VT_STRING;
- }
- if (type == TokenType::IntDeclaration) {
- return Variables::Type::VT_INT;
- }
- if (type == TokenType::DoubleDeclaration) {
- return Variables::Type::VT_DOUBLE;
- }
- if (type == TokenType::BooleanDeclaration) {
- return Variables::Type::VT_BOOLEAN;
- }
- //if (type == TokenType::FunctionDeclaration) {
- // return Variables::Type::VT_FUNCTION;
- //}
- return Variables::Type::VT_NULL;
+const static std::unordered_map<Tokens::Type, std::string> tokenTypeNames = {
+ { Tokens::Type::ParserOpenTag, "ParserOpenTag" },
+ { Tokens::Type::ParserCloseTag, "ParserCloseTag" },
+ { Tokens::Type::ParserIfStatement, "ParserIfStatement" },
+ { Tokens::Type::FileClose, "FileClose" },
+ { Tokens::Type::Identifier, "Identifier" },
+ { Tokens::Type::StringLiteral, "StringLiteral" },
+ { Tokens::Type::IntLiteral, "IntLiteral" },
+ { Tokens::Type::DoubleLiteral, "DoubleLiteral" },
+ { Tokens::Type::BooleanLiteral, "BooleanLiteral" },
+ { Tokens::Type::LeftParenthesis, "LeftParenthesis" },
+ { Tokens::Type::RightParenthesis, "RightParenthesis" },
+ { Tokens::Type::Comma, "Comma" },
+ { Tokens::Type::Semicolon, "Semicolon" },
+ { Tokens::Type::Variable, "Variable" },
+ { Tokens::Type::VariableSign, "VariableSign" },
+ { Tokens::Type::StringDeclaration, "StringDeclaration" },
+ { Tokens::Type::IntDeclaration, "IntDeclaration" },
+ { Tokens::Type::DoubleDeclaration, "DoubleDeclaration" },
+ { Tokens::Type::BooleanDeclaration, "BooleanDeclaration" },
+ { Tokens::Type::FunctionDeclaration, "FunctionDeclaration" },
+ { Tokens::Type::FunctionCall, "FunctionCall" },
+ { Tokens::Type::Return, "Return" },
+ { Tokens::Type::Equals, "Equals" },
+ { Tokens::Type::Plus, "Plus" },
+ { Tokens::Type::Minus, "Minus" },
+ { Tokens::Type::Multiply, "Multiply" },
+ { Tokens::Type::Divide, "Divide" },
+ { Tokens::Type::Modulo, "Modulo" },
+ { Tokens::Type::GreaterThan, "GreaterThan" },
+ { Tokens::Type::LessThan, "LessThan" },
+ { Tokens::Type::GreaterThanOrEqual, "GreaterThanOrEqual" },
+ { Tokens::Type::LessThanOrEqual, "LessThanOrEqual" },
+ { Tokens::Type::NotEqual, "NotEqual" },
+ { Tokens::Type::Equal, "Equal" },
+ { Tokens::Type::Not, "Not" },
+ { Tokens::Type::And, "And" },
+ { Tokens::Type::Or, "Or" },
+ { Tokens::Type::LeftBracket, "LeftBracket" },
+ { Tokens::Type::RightBracket, "RightBracket" },
+ { Tokens::Type::LeftCurlyBracket, "LeftCurlyBracket" },
+ { Tokens::Type::RightCurlyBracket, "RightCurlyBracket" },
+ { Tokens::Type::EndOfFile, "EndOfFile" },
+ { Tokens::Type::EndOfLine, "EndOfLine" },
+ { Tokens::Type::Comment, "Comment" },
+ { Tokens::Type::Unknown, "Unknown" }
};
struct TokenPos {
@@ -192,17 +107,14 @@
};
struct Token {
- TokenType type;
- std::string lexeme;
- std::string file;
- int lineNumber;
- size_t columnNumber;
- TokenPos pos;
- Variables::Type variableType = Variables::Type::VT_NULL;
+ Tokens::Type type;
+ std::string lexeme;
+ std::string file;
+ int lineNumber;
+ size_t columnNumber;
+ TokenPos pos;
- [[nodiscard]] std::string getTypeName() const { return tokenTypeNames.at(type); }
-
- [[nodiscard]] std::string getVariableTypeName() const { return Variables::TypeToString(variableType); }
+ [[nodiscard]] std::string getTokenName() const { return tokenTypeNames.at(type); }
};
-
+} // namespace Tokens
#endif // TOKEN_HPP
diff --git a/src/Value.hpp b/src/Value.hpp
deleted file mode 100644
index 8b649e6..0000000
--- a/src/Value.hpp
+++ /dev/null
@@ -1,212 +0,0 @@
-#ifndef VALUE_HPP
-#define VALUE_HPP
-#include <cstdint>
-#include <string>
-#include <variant>
-
-#include "Token.hpp"
-#include "VariableTypes.hpp"
-
-class Value {
- public:
- Variables::Type type = Variables::Type::VT_NULL;
- Variables::DataContainer data;
- Token token;
- std::string name;
- std::string context;
-
- Value() : type(Variables::Type::VT_NULL) {}
-
- //Value(Variables::Type t, double val) : type(t), data(std::move(val)) {}
-
- //Value(Variables::Type t, int val) : type(t), data(std::move(val)) {}
-
- //Value(Variables::Type t, const std::string & val) : type(t), data(val) {}
-
- //Value(Variables::Type t, bool val) : type(t), data(std::move(val)) {}
-
- Value(Variables::Type variable_type, const Token & token) : type(variable_type), token(token) {
- if (type == Variables::Type::VT_INT) {
- data = std::stoi(token.lexeme);
- } else if (type == Variables::Type::VT_DOUBLE) {
- data = std::stod(token.lexeme);
- } else if (type == Variables::Type::VT_BOOLEAN) {
- data = token.lexeme == "true";
- } else if (type == Variables::Type::VT_NULL) {
- data = Variables::TypeToString(type);
- } else if (type == Variables::Type::VT_NOT_DEFINED) {
- data = Variables::TypeToString(type);
- } else {
- data = token.lexeme;
- }
- }
-
- //Value(const Token & token) : token(token), type(token.variableType), data(token.lexeme) {}
-
- //static Value fromInt(int val) { return Value(Variables::Type::VT_INT, val); }
-
- //static Value fromDouble(double val) { return Value(Variables::Type::VT_DOUBLE, val); }
-
- //static Value fromString(const std::string & val) { return { Variables::Type::VT_STRING, val }; }
-
- //static Value fromBoolean(bool val) { return { Variables::Type::VT_BOOLEAN, val }; }
-
- static Value fromInt(const Token & token) { return Value(Variables::Type::VT_INT, token); }
-
- static Value fromDouble(const Token & token) { return Value(Variables::Type::VT_DOUBLE, token); }
-
- static Value fromString(const Token & token) { return Value(Variables::Type::VT_STRING, token); }
-
- static Value fromBoolean(const Token & token, bool state) {
- auto result = Value(Variables::Type::VT_BOOLEAN, token);
- result.data = state;
- return result;
- }
-
- std::string ToString() const { return decodeEscapes(Variables::ToString(data, type)); }
-
- int ToInt() const { return std::get<int>(data); }
-
- double ToDouble() const { return std::get<double>(data); }
-
- bool ToBool() const { return std::get<bool>(data); }
-
- std::string TypeToString() const { return Variables::TypeToString(type); }
-
- void SetToken(const Token & token) { this->token = token; }
-
- const Token & GetToken() const { return token; }
-
- private:
- Value(Variables::Type t, std::variant<int, double, std::string, bool> && val) : type(t), data(std::move(val)) {}
-
- static std::string decodeEscapes(const std::string & input) {
- std::string result;
- size_t i = 0;
-
- auto hexToChar = [](const std::string & hex) -> char {
- return static_cast<char>(std::stoi(hex, nullptr, 16));
- };
-
- auto hexToUTF8 = [](uint32_t codepoint) -> std::string {
- std::string out;
- if (codepoint <= 0x7F) {
- out += static_cast<char>(codepoint);
- } else if (codepoint <= 0x7FF) {
- out += static_cast<char>(0xC0 | ((codepoint >> 6) & 0x1F));
- out += static_cast<char>(0x80 | (codepoint & 0x3F));
- } else if (codepoint <= 0xFFFF) {
- out += static_cast<char>(0xE0 | ((codepoint >> 12) & 0x0F));
- out += static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F));
- out += static_cast<char>(0x80 | (codepoint & 0x3F));
- } else if (codepoint <= 0x10FFFF) {
- out += static_cast<char>(0xF0 | ((codepoint >> 18) & 0x07));
- out += static_cast<char>(0x80 | ((codepoint >> 12) & 0x3F));
- out += static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F));
- out += static_cast<char>(0x80 | (codepoint & 0x3F));
- }
- return out;
- };
-
- while (i < input.size()) {
- if (input[i] == '\\' && i + 1 < input.size()) {
- char esc = input[i + 1];
-
- // Standard short escape sequences
- switch (esc) {
- case 'n':
- result += '\n';
- i += 2;
- continue;
- case 't':
- result += '\t';
- i += 2;
- continue;
- case 'r':
- result += '\r';
- i += 2;
- continue;
- case 'b':
- result += '\b';
- i += 2;
- continue;
- case 'f':
- result += '\f';
- i += 2;
- continue;
- case 'v':
- result += '\v';
- i += 2;
- continue;
- case 'a':
- result += '\a';
- i += 2;
- continue;
- case '\\':
- result += '\\';
- i += 2;
- continue;
- case '"':
- result += '"';
- i += 2;
- continue;
- case '\'':
- result += '\'';
- i += 2;
- continue;
- case '?':
- result += '?';
- i += 2;
- continue;
- case '0':
- result += '\0';
- i += 2;
- continue;
- case 'x':
- {
- // Hexadecimal escape: \xHH
- size_t j = i + 2;
- std::string hex;
- while (j < input.size() && std::isxdigit(input[j]) && hex.size() < 2) {
- hex += input[j++];
- }
- if (!hex.empty()) {
- result += hexToChar(hex);
- i = j;
- continue;
- }
- }
- break;
- case 'u':
- case 'U':
- {
- // Unicode escape: \uHHHH or \UHHHHHHHH
- size_t expected_len = (esc == 'u') ? 4 : 8;
- size_t j = i + 2;
- std::string hex;
- while (j < input.size() && std::isxdigit(input[j]) && hex.size() < expected_len) {
- hex += input[j++];
- }
- if (hex.size() == expected_len) {
- uint32_t codepoint = std::stoul(hex, nullptr, 16);
- result += hexToUTF8(codepoint);
- i = j;
- continue;
- }
- }
- break;
- }
-
- // Ha ide jutunk, ismeretlen vagy érvénytelen escape
- result += '\\';
- result += esc;
- i += 2;
- } else {
- result += input[i++];
- }
- }
-
- return result;
- }
-};
-#endif // VALUE_HPP
diff --git a/src/VariableTypes.hpp b/src/VariableTypes.hpp
deleted file mode 100644
index 0f3f77d..0000000
--- a/src/VariableTypes.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef VARIABLE_TYPES_HPP
-#define VARIABLE_TYPES_HPP
-
-#include <cstdint>
-#include <string>
-#include <unordered_map>
-#include <variant>
-
-namespace Variables {
-
-using DataContainer = std::variant<int, double, std::string, bool>;
-
-enum class Type : std::uint8_t { VT_INT, VT_DOUBLE, VT_STRING, VT_BOOLEAN, VT_NULL, VT_NOT_DEFINED };
-
-const std::unordered_map<std::string, Type> StringToTypeMap = {
- { "int", Type::VT_INT },
- { "double", Type::VT_DOUBLE },
- { "string", Type::VT_STRING },
- { "bool", Type::VT_BOOLEAN },
- { "boolean", Type::VT_BOOLEAN },
- { "null", Type::VT_NULL },
- { "not_defined", Type::VT_NOT_DEFINED },
-};
-const std::unordered_map<Type, std::string> StypeToStringMap = {
- { Type::VT_INT, "int" },
- { Type::VT_DOUBLE, "double" },
- { Type::VT_STRING, "string" },
- { Type::VT_BOOLEAN, "bool" },
- { Type::VT_NULL, "null" },
- { Type::VT_NOT_DEFINED, "not_defined" },
-};
-
-inline static std::string TypeToString(Type type) {
- if (StypeToStringMap.find(type) != StypeToStringMap.end()) {
- return StypeToStringMap.at(type);
- }
- return "null";
-};
-
-inline static Type StringToType(const std::string & type) {
- if (StringToTypeMap.find(type) != StringToTypeMap.end()) {
- return StringToTypeMap.at(type);
- }
- return Type::VT_NULL;
-};
-
-inline static std::string ToString(const DataContainer & data, const Type & type) {
- switch (type) {
- case Type::VT_INT:
- return std::to_string(std::get<int>(data));
- case Type::VT_DOUBLE:
- return std::to_string(std::get<double>(data));
- case Type::VT_STRING:
- return std::get<std::string>(data);
- case Type::VT_BOOLEAN:
- return std::get<bool>(data) ? "true" : "false";
- case Type::VT_NULL:
- default:
- return "null";
- }
-};
-
-}; // namespace Variables
-#endif // VARIABLE_TYPES_HPP
--
Gitblit v1.9.3