From 36ec04c00fa540fcee0f2cff1f7b81dd8a98101a Mon Sep 17 00:00:00 2001
From: Ferenc Szontágh <szf@fsociety.hu>
Date: Thu, 17 Apr 2025 18:44:58 +0000
Subject: [PATCH] some refactor
---
src/Parser/Parser.cpp | 329 ++++++++++
src/BaseException.hpp | 25
src/Interpreter/ExpressionBuilder.hpp | 105 +++
src/Lexer/Lexer.hpp | 347 +----------
src/Lexer/Token.hpp | 14
src/Interpreter/UnaryExpressionNode.hpp | 8
src/Parser/Parser.hpp | 394 +------------
src/Lexer/Lexer.cpp | 307 ++++++++++
CMakeLists.txt | 1
src/Symbols/BaseSymbol.hpp | 2
src/VoidScript.hpp | 15
src/Parser/ParsedExpression.hpp | 41 +
src/Interpreter/OperationContainer.hpp | 2
src/Lexer/Operators.cpp | 26
src/Lexer/Operators.hpp | 79 ++
src/Symbols/SymbolTable.hpp | 1
src/Symbols/SymbolContainer.hpp | 2
17 files changed, 969 insertions(+), 729 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b9e1780..688a842 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -120,6 +120,7 @@
add_library(voidscript
src/Parser/Parser.cpp
src/Lexer/Lexer.cpp
+ src/Lexer/Operators.cpp
)
install(TARGETS voidscript DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT "lib")
diff --git a/src/BaseException.hpp b/src/BaseException.hpp
new file mode 100644
index 0000000..cf6be57
--- /dev/null
+++ b/src/BaseException.hpp
@@ -0,0 +1,25 @@
+#ifndef BASE_EXCEPTION_HPP
+#define BASE_EXCEPTION_HPP
+
+#include <string>
+
+class BaseException : public std::exception {
+ public:
+ BaseException(const std::string & msg, const std::string & context = "") : rawMessage_(msg), context_(context) {
+ formattedMessage_ = formatMessage();
+ }
+ BaseException() = default;
+ BaseException(const BaseException&) = default;
+
+
+ const char * what() const noexcept override { return formattedMessage_.c_str(); }
+
+ virtual std::string formatMessage() const { return "[BaseException] " + context_ + ": " + rawMessage_; }
+
+ protected:
+ std::string rawMessage_;
+ std::string context_;
+ std::string formattedMessage_;
+};
+
+#endif // BASE_EXCEPTION_HPP
diff --git a/src/Interpreter/ExpressionBuilder.hpp b/src/Interpreter/ExpressionBuilder.hpp
index 32b2e9b..5ee96d7 100644
--- a/src/Interpreter/ExpressionBuilder.hpp
+++ b/src/Interpreter/ExpressionBuilder.hpp
@@ -8,13 +8,13 @@
#include "Interpreter/ExpressionNode.hpp"
#include "Interpreter/IdentifierExpressionNode.hpp"
#include "Interpreter/LiteralExpressionNode.hpp"
-#include "Interpreter/UnaryExpressionNode.hpp" // <-- új include
+#include "Interpreter/UnaryExpressionNode.hpp" // <-- új include
#include "Parser/ParsedExpression.hpp"
namespace Parser {
static std::unique_ptr<Interpreter::ExpressionNode> buildExpressionFromParsed(
- const Parser::ParsedExpressionPtr & expr) {
- using Kind = Parser::ParsedExpression::Kind;
+ const ParsedExpressionPtr & expr) {
+ using Kind = ParsedExpression::Kind;
switch (expr->kind) {
case Kind::Literal:
@@ -23,20 +23,101 @@
case Kind::Variable:
return std::make_unique<Interpreter::IdentifierExpressionNode>(expr->name);
- case Kind::Binary: {
- auto lhs = buildExpressionFromParsed(expr->lhs);
- auto rhs = buildExpressionFromParsed(expr->rhs);
- return std::make_unique<Interpreter::BinaryExpressionNode>(std::move(lhs), expr->op, std::move(rhs));
- }
+ case Kind::Binary:
+ {
+ auto lhs = buildExpressionFromParsed(expr->lhs);
+ auto rhs = buildExpressionFromParsed(expr->rhs);
+ return std::make_unique<Interpreter::BinaryExpressionNode>(std::move(lhs), expr->op, std::move(rhs));
+ }
- case Kind::Unary: {
- auto operand = buildExpressionFromParsed(expr->rhs); // rhs az operandus
- return std::make_unique<Interpreter::UnaryExpressionNode>(expr->op, std::move(operand));
- }
+ case Kind::Unary:
+ {
+ auto operand = buildExpressionFromParsed(expr->rhs); // rhs az operandus
+ return std::make_unique<Interpreter::UnaryExpressionNode>(expr->op, std::move(operand));
+ }
}
throw std::runtime_error("Unknown ParsedExpression kind");
}
+
+void typecheckParsedExpression(const ParsedExpressionPtr & expr) {
+ using Kind = ParsedExpression::Kind;
+
+ switch (expr->kind) {
+ case Kind::Literal:
+ {
+ // Literál típusának ellenőrzése - a literál típusát a value.getType() adja vissza
+ // auto type = expr->value.getType();
+ // Nem szükséges semmilyen más típusellenőrzés a literálokhoz, mivel azok fix típusúak.
+ break;
+ }
+
+ case Kind::Variable:
+ {
+ const std::string ns = Symbols::SymbolContainer::instance()->currentScopeName() + ".variables";
+ auto symbol = Symbols::SymbolContainer::instance()->get(ns, expr->name);
+ if (!symbol) {
+ throw std::runtime_error("Variable not found in symbol table: " + expr->name);
+ }
+
+ // Ha a szimbólum nem egy változó, akkor hibát dobunk
+ if (symbol->getKind() == Symbols::Kind::Function) {
+ throw std::runtime_error("Cannot use function as variable: " + expr->name);
+ }
+ break;
+ }
+
+ case Kind::Binary:
+ {
+ // Bináris kifejezés operandusainak típusellenőrzése
+ typecheckParsedExpression(expr->lhs);
+ typecheckParsedExpression(expr->rhs);
+
+ auto lhsType = expr->lhs->getType();
+ auto rhsType = expr->rhs->getType();
+
+ if (lhsType != rhsType) {
+ throw std::runtime_error(
+ "Type mismatch in binary expression: " + Symbols::Variables::TypeToString(lhsType) + " and " +
+ Symbols::Variables::TypeToString(rhsType));
+ }
+
+ // Bináris operátoroknál is elvégezhetjük a típusellenőrzést:
+ // Ha numerikus operátor, akkor az operandusoknak numerikusnak kell lenniük
+ if (expr->op == "+" || expr->op == "-" || expr->op == "*" || expr->op == "/") {
+ if (lhsType != Symbols::Variables::Type::INTEGER && lhsType != Symbols::Variables::Type::FLOAT) {
+ throw std::runtime_error("Operands must be numeric for operator: " + expr->op);
+ }
+ }
+ // Ha logikai operátorok, akkor boolean típus szükséges
+ else if (expr->op == "&&" || expr->op == "||") {
+ if (lhsType != Symbols::Variables::Type::BOOLEAN) {
+ throw std::runtime_error("Operands must be boolean for operator: " + expr->op);
+ }
+ }
+ break;
+ }
+
+ case Kind::Unary:
+ {
+ // Unáris kifejezés operandusának típusellenőrzése
+ typecheckParsedExpression(expr->rhs); // 'rhs' tárolja az operandust az unáris kifejezésnél
+
+ auto operandType = expr->rhs->getType();
+
+ if (expr->op == "!") {
+ if (operandType != Symbols::Variables::Type::BOOLEAN) {
+ throw std::runtime_error("Operand must be boolean for unary operator '!'");
+ }
+ }
+ break;
+ }
+
+ default:
+ throw std::runtime_error("Unknown expression kind");
+ }
+}
+
} // namespace Parser
#endif // PARSEREXPRESSION_BUILDER_HPP
diff --git a/src/Interpreter/OperationContainer.hpp b/src/Interpreter/OperationContainer.hpp
index 20f9e2c..a8646a0 100644
--- a/src/Interpreter/OperationContainer.hpp
+++ b/src/Interpreter/OperationContainer.hpp
@@ -117,7 +117,7 @@
auto end() const { return _operations.end(); }
static std::string dump() {
- std::string result = "";
+ std::string result;
for (const auto & [_, table] : Operations::Container::instance()->_operations) {
result += "Namespace: " + _ + "\n";
for (const auto & operation : table) {
diff --git a/src/Interpreter/UnaryExpressionNode.hpp b/src/Interpreter/UnaryExpressionNode.hpp
index e3abde1..2173c74 100644
--- a/src/Interpreter/UnaryExpressionNode.hpp
+++ b/src/Interpreter/UnaryExpressionNode.hpp
@@ -50,6 +50,14 @@
if (op_ == "!") {
return Symbols::Value(!v);
}
+ } else if (type == Symbols::Variables::Type::STRING) {
+ std::string s = value.get<std::string>();
+ if (op_ == "-") {
+ return Symbols::Value(s);
+ }
+ if (op_ == "+") {
+ return Symbols::Value(s);
+ }
}
throw std::runtime_error("Unsupported unary operator '" + op_ +
diff --git a/src/Lexer/Lexer.cpp b/src/Lexer/Lexer.cpp
index 6f6cc35..b5a4261 100644
--- a/src/Lexer/Lexer.cpp
+++ b/src/Lexer/Lexer.cpp
@@ -1,14 +1,305 @@
#include "Lexer/Lexer.hpp"
-namespace Lexer {
-const std::vector<std::string> Lexer::Lexer::OPERATOR_RELATIONAL = { "==", "!=", "<", ">", "<=", ">=" };
-const std::vector<std::string> Lexer::Lexer::OPERATOR_INCREMENT = { "++", "--" };
-const std::vector<std::string> Lexer::Lexer::OPERATOR_ASSIGNMENT = { "=", "+=", "-=", "*=", "/=", "%=" };
-const std::vector<std::string> Lexer::Lexer::OPERATOR_LOGICAL = { "&&", "||" };
+#include "Lexer/Operators.hpp"
+#include "Symbols/SymbolContainer.hpp"
-const std::vector<std::string> Lexer::Lexer::OPERATOR_ARITHMETIC = { "+", "-", "*", "/", "%" };
-const std::vector<std::string> Lexer::Lexer::PUNCTUATION = { "(", ")", "{", "}", "[", "]", ",", ";" };
+std::vector<Lexer::Tokens::Token> Lexer::Lexer::tokenizeNamespace(const std::string & ns) {
+ if (inputs_.find(ns) == inputs_.end()) {
+ return {};
+ }
+ Symbols::SymbolContainer::instance()->enter(ns);
+ std::vector<Tokens::Token> tokens;
+ Tokens::Token token;
+ do {
+ token = nextToken();
+ tokens.push_back(token);
+ } while (token.type != Tokens::Type::END_OF_FILE);
-}; // namespace Lexer
+ tokens_[ns] = tokens;
+ return tokens;
+}
+
+void Lexer::Lexer::addNamespaceInput(const std::string & ns, const std::string & input) {
+ inputs_[ns] = input;
+ positions_[ns] = 0;
+ line_numbers_[ns] = 1;
+ column_numbers_[ns] = 1;
+}
+
+std::vector<Lexer::Tokens::Token> Lexer::Lexer::getTokens(const std::string & ns) const {
+ auto it = tokens_.find(ns);
+ if (it != tokens_.end()) {
+ return it->second;
+ }
+ return {};
+}
+
+void Lexer::Lexer::setKeyWords(const std::unordered_map<std::string, Tokens::Type> & new_keywords) {
+ keywords = new_keywords;
+}
+
+Lexer::Tokens::Token Lexer::Lexer::nextToken() {
+ skipWhitespaceAndComments();
+ size_t start = pos();
+
+ if (isAtEnd()) {
+ return createToken(Tokens::Type::END_OF_FILE, start, start);
+ }
+
+ char c = peek();
+ if (isalpha(c) || c == '_') {
+ return matchIdentifierOrKeyword(start);
+ }
+ if (isdigit(c) || (isdigit(c) && peek(1) == '.') || (c == '.' && isdigit(peek(1)))) {
+ return matchNumber(start);
+ }
+ if (c == '"' || c == '\'') {
+ return matchStringLiteral(start);
+ }
+ if (operators_.find(c) != std::string_view::npos) {
+ return matchOperatorOrPunctuation(start);
+ }
+
+ advance();
+ return createToken(Tokens::Type::UNKNOWN, start, pos());
+}
+
+const std::string & Lexer::Lexer::input() const {
+ const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
+ auto it = inputs_.find(ns);
+ if (it != inputs_.end()) {
+ return it->second;
+ }
+ throw Exception("Input not found in namespace: " + ns);
+}
+
+size_t & Lexer::Lexer::pos() {
+ const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
+ auto it = positions_.find(ns);
+ if (it != positions_.end()) {
+ return it->second;
+ }
+ throw Exception("Unknown position in namespace: " + ns);
+}
+
+int & Lexer::Lexer::line() {
+ const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
+ auto it = line_numbers_.find(ns);
+ if (it != line_numbers_.end()) {
+ return it->second;
+ }
+ throw Exception("Unknown line number in namespace: " + ns);
+}
+
+int & Lexer::Lexer::col() {
+ const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
+ auto it = column_numbers_.find(ns);
+ if (it != column_numbers_.end()) {
+ return it->second;
+ }
+ throw Exception("Unknown column number in namespace: " + ns);
+}
+
+Lexer::Tokens::Token Lexer::Lexer::createToken(Tokens::Type type, size_t start, size_t end, const std::string & value) {
+ Tokens::Token token;
+ token.type = type;
+ token.start_pos = start;
+ token.end_pos = end;
+ token.line_number = line();
+ token.column_number = col();
+ if (start <= end && end <= input().length()) {
+ token.lexeme = std::string_view(input()).substr(start, end - start);
+ token.value = value.empty() ? std::string(token.lexeme) : value;
+ }
+ return token;
+}
+
+char Lexer::Lexer::peek(size_t offset) const {
+ const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
+ const auto & in = inputs_.at(ns);
+ size_t cp = positions_.at(ns);
+ if (cp + offset >= in.length()) {
+ return '\0';
+ }
+ return in[cp + offset];
+}
+
+char Lexer::Lexer::advance() {
+ char c = peek();
+ pos()++;
+ if (c == '\n') {
+ line()++;
+ col() = 1;
+ } else {
+ col()++;
+ }
+ return c;
+}
+
+bool Lexer::Lexer::isAtEnd() const {
+ const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
+ return positions_.at(ns) >= inputs_.at(ns).length();
+}
+
+void Lexer::Lexer::skipWhitespaceAndComments() {
+ while (!isAtEnd()) {
+ char c = peek();
+ if (isspace(c)) {
+ advance();
+ } else if ((c == '/' && peek(1) == '/') || c == '#') {
+ while (!isAtEnd() && peek() != '\n') {
+ advance();
+ }
+ } else {
+ break;
+ }
+ }
+}
+
+Lexer::Tokens::Token Lexer::Lexer::matchIdentifierOrKeyword(size_t start_pos, Tokens::Type type) {
+ while (!isAtEnd() && (isalnum(peek()) || peek() == '_')) {
+ advance();
+ }
+ size_t end = pos();
+ std::string value = input().substr(start_pos, end - start_pos);
+ if (value.empty()) {
+ return createToken(Tokens::Type::UNKNOWN, start_pos, end);
+ }
+
+ if (type == Tokens::Type::IDENTIFIER) {
+ auto it = keywords.find(value);
+ if (it != keywords.end()) {
+ return createToken(it->second, start_pos, end);
+ }
+ }
+ return createToken(type, start_pos, end);
+}
+
+Lexer::Tokens::Token Lexer::Lexer::matchNumber(size_t start_pos) {
+ bool has_dot = false;
+
+ while (!isAtEnd()) {
+ if (isdigit(peek())) {
+ advance();
+ } else if (!has_dot && peek() == '.' && isdigit(peek(1))) {
+ has_dot = true;
+ advance(); // a pont
+ advance(); // az első számjegy a pont után
+ } else {
+ break;
+ }
+ }
+
+ size_t end = pos();
+ return createToken(Tokens::Type::NUMBER, start_pos, end);
+}
+
+Lexer::Tokens::Token Lexer::Lexer::matchStringLiteral(size_t start_pos) {
+ char opening_quote = peek();
+ advance(); // Skip opening quote
+ std::string value;
+ bool unterminated = false;
+
+ while (!isAtEnd()) {
+ char c = peek();
+ if (c == opening_quote) {
+ advance();
+ break;
+ }
+ if (c == '\\') {
+ advance();
+ char e = advance();
+ switch (e) {
+ case 'n':
+ value += '\n';
+ break;
+ case 't':
+ value += '\t';
+ break;
+ case '"':
+ value += opening_quote;
+ break;
+ case '\\':
+ value += '\\';
+ break;
+ default:
+ value += e;
+ break;
+ }
+ } else {
+ value += advance();
+ }
+ }
+
+ size_t end = pos();
+ if (unterminated) {
+ return createToken(Tokens::Type::UNKNOWN, start_pos, end, input().substr(start_pos, end - start_pos));
+ }
+ return createToken(Tokens::Type::STRING_LITERAL, start_pos, end, value);
+}
+
+Lexer::Tokens::Token Lexer::Lexer::matchOperatorOrPunctuation(size_t start_pos) {
+ char first_char = advance(); // Első karakter elfogyasztása
+
+ if (!isAtEnd()) {
+ char second_char = peek(0); // Következő karakter megnézése
+ std::string two_chars_str{ first_char, second_char };
+
+ const std::vector<std::pair<const std::vector<std::string> *, Tokens::Type>> two_char_op_types = {
+ { &OPERATOR_RELATIONAL, Tokens::Type::OPERATOR_RELATIONAL },
+ { &OPERATOR_INCREMENT, Tokens::Type::OPERATOR_INCREMENT },
+ { &OPERATOR_ASSIGNMENT, Tokens::Type::OPERATOR_ASSIGNMENT },
+ { &OPERATOR_LOGICAL, Tokens::Type::OPERATOR_LOGICAL }
+ };
+
+ for (const auto & [vec_ptr, type] : two_char_op_types) {
+ if (matchFromVector(*vec_ptr, two_chars_str)) {
+ advance(); // Második karakter elfogyasztása
+ size_t end_pos = pos();
+ return createToken(type, start_pos, end_pos);
+ }
+ }
+ }
+
+ std::string single_char_str(1, first_char);
+
+ if (single_char_str == "$") {
+ if (isalpha(peek(0)) || peek(0) == '_') {
+ return matchIdentifierOrKeyword(start_pos, Tokens::Type::VARIABLE_IDENTIFIER);
+ }
+ }
+
+ const std::vector<std::pair<const std::vector<std::string> *, Tokens::Type>> one_char_op_types = {
+ { &OPERATOR_ARITHMETIC, Tokens::Type::OPERATOR_ARITHMETIC },
+ { &OPERATOR_ASSIGNMENT, Tokens::Type::OPERATOR_ASSIGNMENT },
+ { &PUNCTUATION, Tokens::Type::PUNCTUATION }
+ };
+
+ for (const auto & [vec_ptr, type] : one_char_op_types) {
+ if (matchFromVector(*vec_ptr, single_char_str)) {
+ size_t end_pos = pos();
+ return createToken(type, start_pos, end_pos);
+ }
+ }
+
+ size_t end_pos = pos();
+ return createToken(Tokens::Type::UNKNOWN, start_pos, end_pos);
+}
+
+bool Lexer::Lexer::matchFromVector(const std::vector<std::string> & vec, const std::string & value) {
+ return std::find(vec.begin(), vec.end(), value) != vec.end();
+}
+
+Lexer::Lexer::Lexer() {
+ for (const auto & vecRef :
+ { std::cref(OPERATOR_ARITHMETIC), std::cref(OPERATOR_RELATIONAL), std::cref(OPERATOR_INCREMENT),
+ std::cref(OPERATOR_ASSIGNMENT), std::cref(OPERATOR_LOGICAL), std::cref(PUNCTUATION) }) {
+ for (const auto & str : vecRef.get()) {
+ operators_ += str;
+ }
+ }
+
+ operators_ += "$";
+}
diff --git a/src/Lexer/Lexer.hpp b/src/Lexer/Lexer.hpp
index 4bd0ecf..d7dac6d 100644
--- a/src/Lexer/Lexer.hpp
+++ b/src/Lexer/Lexer.hpp
@@ -1,91 +1,34 @@
#ifndef LEXER_HPP
#define LEXER_HPP
-#include <algorithm>
#include <cctype>
#include <string>
-#include <string_view>
#include <unordered_map>
#include <vector>
-#include "Symbols/SymbolContainer.hpp"
+#include "BaseException.hpp"
#include "Token.hpp"
namespace Lexer {
class Lexer {
public:
- Lexer() {
- for (const auto & vecRef :
- { std::cref(OPERATOR_ARITHMETIC), std::cref(OPERATOR_RELATIONAL), std::cref(OPERATOR_INCREMENT),
- std::cref(OPERATOR_ASSIGNMENT), std::cref(OPERATOR_LOGICAL), std::cref(PUNCTUATION) }) {
- for (const auto & str : vecRef.get()) {
- operators_ += str;
- }
+ Lexer();
+ void addNamespaceInput(const std::string & ns, const std::string & input);
+ void setKeyWords(const std::unordered_map<std::string, Tokens::Type> & new_keywords);
+ std::vector<Tokens::Token> tokenizeNamespace(const std::string & ns);
+ std::vector<Tokens::Token> getTokens(const std::string & ns) const;
+
+ class Exception : public BaseException {
+ public:
+ using BaseException::BaseException;
+
+ Exception(const std::string & msg) {
+ rawMessage_ = msg;
+ context_ = "";
}
- operators_ += "$";
- }
-
- void addNamespaceInput(const std::string & ns, const std::string & input) {
- inputs_[ns] = input;
- positions_[ns] = 0;
- line_numbers_[ns] = 1;
- column_numbers_[ns] = 1;
- }
-
- std::vector<Tokens::Token> tokenizeNamespace(const std::string & ns) {
- if (inputs_.find(ns) == inputs_.end()) {
- return {};
- }
-
- Symbols::SymbolContainer::instance()->enter(ns);
-
- std::vector<Tokens::Token> tokens;
- Tokens::Token token;
- do {
- token = nextToken();
- tokens.push_back(token);
- } while (token.type != Tokens::Type::END_OF_FILE);
-
- tokens_[ns] = tokens;
- return tokens;
- }
-
- std::vector<Tokens::Token> getTokens(const std::string & ns) const {
- auto it = tokens_.find(ns);
- if (it != tokens_.end()) {
- return it->second;
- }
- return {};
- }
-
- void setKeyWords(const std::unordered_map<std::string, Tokens::Type> & new_keywords) { keywords = new_keywords; }
-
- Tokens::Token nextToken() {
- skipWhitespaceAndComments();
- size_t start = pos();
-
- if (isAtEnd()) {
- return createToken(Tokens::Type::END_OF_FILE, start, start);
- }
-
- char c = peek();
- if (isalpha(c) || c == '_') {
- return matchIdentifierOrKeyword(start);
- }
- if (isdigit(c) || (isdigit(c) && peek(1) == '.') || (c == '.' && isdigit(peek(1)))) {
- return matchNumber(start);
- }
- if (c == '"' || c == '\'') {
- return matchStringLiteral(start);
- }
- if (operators_.find(c) != std::string_view::npos) {
- return matchOperatorOrPunctuation(start);
- }
-
- advance();
- return createToken(Tokens::Type::UNKNOWN, start, pos());
- }
+ std::string formatMessage() const override { return "[LEXER ERROR]: " + rawMessage_; }
+ };
private:
@@ -94,248 +37,24 @@
std::unordered_map<std::string, size_t> positions_;
std::unordered_map<std::string, int> line_numbers_;
std::unordered_map<std::string, int> column_numbers_;
+ std::unordered_map<std::string, Tokens::Type> keywords;
+ std::string operators_;
+ Tokens::Token nextToken();
- std::string operators_;
- std::unordered_map<std::string, Tokens::Type> keywords;
-
- // two chars
- static const std::vector<std::string> OPERATOR_RELATIONAL;
- static const std::vector<std::string> OPERATOR_INCREMENT;
- static const std::vector<std::string> OPERATOR_ASSIGNMENT;
- static const std::vector<std::string> OPERATOR_LOGICAL;
-
- // one char
- static const std::vector<std::string> OPERATOR_ARITHMETIC;
- static const std::vector<std::string> PUNCTUATION;
-
- const std::string & input() const {
- const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
- auto it = inputs_.find(ns);
- if (it != inputs_.end()) {
- return it->second;
- }
- throw std::runtime_error("Input not found in namespace: " + ns);
- }
-
- size_t & pos() {
- const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
- auto it = positions_.find(ns);
- if (it != positions_.end()) {
- return it->second;
- }
- throw std::runtime_error("Unknown position in namespace: " + ns);
- }
-
- int & line() {
- const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
- auto it = line_numbers_.find(ns);
- if (it != line_numbers_.end()) {
- return it->second;
- }
- throw std::runtime_error("Unknown line number in namespace: " + ns);
- }
-
- int & col() {
- const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
- auto it = column_numbers_.find(ns);
- if (it != column_numbers_.end()) {
- return it->second;
- }
- throw std::runtime_error("Unknown column number in namespace: " + ns);
- }
-
- Tokens::Token createToken(Tokens::Type type, size_t start, size_t end, const std::string & value = "") {
- Tokens::Token token;
- token.type = type;
- token.start_pos = start;
- token.end_pos = end;
- token.line_number = line();
- token.column_number = col();
- if (start <= end && end <= input().length()) {
- token.lexeme = std::string_view(input()).substr(start, end - start);
- token.value = value.empty() ? std::string(token.lexeme) : value;
- }
- return token;
- }
-
- // --------------------------------------
-
- char peek(size_t offset = 0) const {
- const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
- const auto & in = inputs_.at(ns);
- size_t cp = positions_.at(ns);
- if (cp + offset >= in.length()) {
- return '\0';
- }
- return in[cp + offset];
- }
-
- char advance() {
- char c = peek();
- pos()++;
- if (c == '\n') {
- line()++;
- col() = 1;
- } else {
- col()++;
- }
- return c;
- }
-
- bool isAtEnd() const {
- const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
- return positions_.at(ns) >= inputs_.at(ns).length();
- }
-
- void skipWhitespaceAndComments() {
- while (!isAtEnd()) {
- char c = peek();
- if (isspace(c)) {
- advance();
- } else if ((c == '/' && peek(1) == '/') || c == '#') {
- while (!isAtEnd() && peek() != '\n') {
- advance();
- }
- } else {
- break;
- }
- }
- }
-
- Tokens::Token matchIdentifierOrKeyword(size_t start_pos, Tokens::Type type = Tokens::Type::IDENTIFIER) {
- while (!isAtEnd() && (isalnum(peek()) || peek() == '_')) {
- advance();
- }
- size_t end = pos();
- std::string value = input().substr(start_pos, end - start_pos);
- if (value.empty()) {
- return createToken(Tokens::Type::UNKNOWN, start_pos, end);
- }
-
- if (type == Tokens::Type::IDENTIFIER) {
- auto it = keywords.find(value);
- if (it != keywords.end()) {
- return createToken(it->second, start_pos, end);
- }
- }
- return createToken(type, start_pos, end);
- }
-
- Tokens::Token matchNumber(size_t start_pos) {
- bool has_dot = false;
-
- while (!isAtEnd()) {
- if (isdigit(peek())) {
- advance();
- } else if (!has_dot && peek() == '.' && isdigit(peek(1))) {
- has_dot = true;
- advance(); // a pont
- advance(); // az első számjegy a pont után
- } else {
- break;
- }
- }
-
- size_t end = pos();
- return createToken(Tokens::Type::NUMBER, start_pos, end);
- }
-
- Tokens::Token matchStringLiteral(size_t start_pos) {
- char opening_quote = peek();
- advance(); // Skip opening quote
- std::string value;
- bool unterminated = false;
-
- while (!isAtEnd()) {
- char c = peek();
- if (c == opening_quote) {
- advance();
- break;
- }
- if (c == '\\') {
- advance();
- char e = advance();
- switch (e) {
- case 'n':
- value += '\n';
- break;
- case 't':
- value += '\t';
- break;
- case '"':
- value += opening_quote;
- break;
- case '\\':
- value += '\\';
- break;
- default:
- value += e;
- break;
- }
- } else {
- value += advance();
- }
- }
-
- size_t end = pos();
- if (unterminated) {
- return createToken(Tokens::Type::UNKNOWN, start_pos, end, input().substr(start_pos, end - start_pos));
- }
- return createToken(Tokens::Type::STRING_LITERAL, start_pos, end, value);
- }
-
- Tokens::Token matchOperatorOrPunctuation(size_t start_pos) {
- char first_char = advance(); // Első karakter elfogyasztása
-
- if (!isAtEnd()) {
- char second_char = peek(0); // Következő karakter megnézése
- std::string two_chars_str{ first_char, second_char };
-
- const std::vector<std::pair<const std::vector<std::string> *, Tokens::Type>> two_char_op_types = {
- { &OPERATOR_RELATIONAL, Tokens::Type::OPERATOR_RELATIONAL },
- { &OPERATOR_INCREMENT, Tokens::Type::OPERATOR_INCREMENT },
- { &OPERATOR_ASSIGNMENT, Tokens::Type::OPERATOR_ASSIGNMENT },
- { &OPERATOR_LOGICAL, Tokens::Type::OPERATOR_LOGICAL }
- };
-
- for (const auto & [vec_ptr, type] : two_char_op_types) {
- if (matchFromVector(*vec_ptr, two_chars_str)) {
- advance(); // Második karakter elfogyasztása
- size_t end_pos = pos();
- return createToken(type, start_pos, end_pos);
- }
- }
- }
-
- // Egykarakteres operátor vagy írásjel
- std::string single_char_str(1, first_char);
-
- if (single_char_str == "$") {
- if (isalpha(peek(0)) || peek(0) == '_') {
- return matchIdentifierOrKeyword(start_pos, Tokens::Type::VARIABLE_IDENTIFIER);
- }
- }
-
- const std::vector<std::pair<const std::vector<std::string> *, Tokens::Type>> one_char_op_types = {
- { &OPERATOR_ARITHMETIC, Tokens::Type::OPERATOR_ARITHMETIC },
- { &OPERATOR_ASSIGNMENT, Tokens::Type::OPERATOR_ASSIGNMENT }, // "=" itt van!
- { &PUNCTUATION, Tokens::Type::PUNCTUATION }
- };
-
- for (const auto & [vec_ptr, type] : one_char_op_types) {
- if (matchFromVector(*vec_ptr, single_char_str)) {
- size_t end_pos = pos();
- return createToken(type, start_pos, end_pos);
- }
- }
-
- size_t end_pos = pos();
- return createToken(Tokens::Type::UNKNOWN, start_pos, end_pos);
- }
-
- static bool matchFromVector(const std::vector<std::string> & vec, const std::string & value) {
- return std::find(vec.begin(), vec.end(), value) != vec.end();
- }
+ const std::string & input() const;
+ size_t & pos();
+ int & line();
+ int & col();
+ char peek(size_t offset = 0) const;
+ char advance();
+ bool isAtEnd() const;
+ void skipWhitespaceAndComments();
+ static bool matchFromVector(const std::vector<std::string> & vec, const std::string & value);
+ Tokens::Token createToken(Tokens::Type type, size_t start, size_t end, const std::string & value = "");
+ Tokens::Token matchIdentifierOrKeyword(size_t start_pos, Tokens::Type type = Tokens::Type::IDENTIFIER);
+ Tokens::Token matchNumber(size_t start_pos);
+ Tokens::Token matchStringLiteral(size_t start_pos);
+ Tokens::Token matchOperatorOrPunctuation(size_t start_pos);
}; // class Lexer
diff --git a/src/Lexer/Operators.cpp b/src/Lexer/Operators.cpp
new file mode 100644
index 0000000..5fd9f81
--- /dev/null
+++ b/src/Lexer/Operators.cpp
@@ -0,0 +1,26 @@
+#include "Lexer/Operators.hpp"
+
+namespace Lexer {
+
+const std::vector<std::string> OPERATOR_RELATIONAL = { "==", "!=", "<", ">", "<=", ">=" };
+const std::vector<std::string> OPERATOR_INCREMENT = { "++", "--" };
+const std::vector<std::string> OPERATOR_ASSIGNMENT = { "=", "+=", "-=", "*=", "/=", "%=" };
+const std::vector<std::string> OPERATOR_LOGICAL = { "&&", "||" };
+
+const std::vector<std::string> OPERATOR_ARITHMETIC = { "+", "-", "*", "/", "%", "!" };
+const std::vector<std::string> PUNCTUATION = { "(", ")", "{", "}", "[", "]", ",", ";" };
+
+bool contains(const std::vector<std::string> & vec, const std::string & value) {
+ return std::find(vec.begin(), vec.end(), value) != vec.end();
+}
+
+bool isUnaryOperator(const std::string & op) {
+ return op == "+" || op == "-" || op == "!";
+}
+
+bool isBinaryOperator(const std::string & op) {
+ return contains(OPERATOR_ARITHMETIC, op) || contains(OPERATOR_LOGICAL, op) ||
+ contains(OPERATOR_RELATIONAL, op);
+}
+
+} // namespace Lexer
diff --git a/src/Lexer/Operators.hpp b/src/Lexer/Operators.hpp
new file mode 100644
index 0000000..690efe5
--- /dev/null
+++ b/src/Lexer/Operators.hpp
@@ -0,0 +1,79 @@
+#ifndef LEXER_OPERATORS_HPP
+#define LEXER_OPERATORS_HPP
+
+#include <string>
+#include <vector>
+
+#include "Lexer/Token.hpp"
+#include "Parser/ParsedExpression.hpp"
+
+namespace Lexer {
+
+// two chars
+extern const std::vector<std::string> OPERATOR_RELATIONAL;
+extern const std::vector<std::string> OPERATOR_INCREMENT;
+extern const std::vector<std::string> OPERATOR_ASSIGNMENT;
+extern const std::vector<std::string> OPERATOR_LOGICAL;
+
+// one char
+extern const std::vector<std::string> OPERATOR_ARITHMETIC;
+extern const std::vector<std::string> PUNCTUATION;
+
+bool contains(const std::vector<std::string> & vec, const std::string & value);
+bool isUnaryOperator(const std::string & op);
+bool isBinaryOperator(const std::string & op);
+
+inline int getPrecedence(const std::string & op) {
+ if (op == "u-" || op == "u+" || op == "u!") {
+ return 4;
+ }
+ if (op == "*" || op == "/" || op == "%") {
+ return 3;
+ }
+ if (op == "+" || op == "-") {
+ return 2;
+ }
+ if (op == "==" || op == "!=" || op == "<" || op == ">" || op == "<=" || op == ">=") {
+ return 1;
+ }
+ if (op == "&&" || op == "||") {
+ return 0;
+ }
+ return -1;
+}
+
+inline bool isLeftAssociative(const std::string & op) {
+ return !(op == "u-" || op == "u+");
+}
+
+inline Parser::ParsedExpressionPtr applyOperator(const std::string & op, Parser::ParsedExpressionPtr rhs,
+ Parser::ParsedExpressionPtr lhs = nullptr) {
+ if (op.starts_with("u")) {
+ std::string real_op = op.substr(1); // "u!" -> "!"
+ return Parser::ParsedExpression::makeUnary(real_op, std::move(rhs));
+ }
+ return Parser::ParsedExpression::makeBinary(op, std::move(lhs), std::move(rhs));
+}
+
+[[nodiscard]] inline bool pushOperand(const Tokens::Token & token, const Symbols::Variables::Type & expected_var_type,
+ std::vector<Parser::ParsedExpressionPtr> & output_queue) {
+ if (token.type == Tokens::Type::NUMBER || token.type == Tokens::Type::STRING_LITERAL ||
+ token.type == Tokens::Type::KEYWORD) {
+ output_queue.push_back(
+ Parser::ParsedExpression::makeLiteral(Symbols::Value::fromString(token.value, expected_var_type)));
+ return true;
+ }
+ if (token.type == Tokens::Type::VARIABLE_IDENTIFIER) {
+ std::string name = token.value;
+ if (!name.empty() && name[0] == '$') {
+ name = name.substr(1);
+ }
+ output_queue.push_back(Parser::ParsedExpression::makeVariable(name));
+ return true;
+ }
+ return false;
+}
+
+}; // namespace Lexer
+
+#endif // LEXER_OPERATORS_HPP
diff --git a/src/Lexer/Token.hpp b/src/Lexer/Token.hpp
index ac2ac9f..2352950 100644
--- a/src/Lexer/Token.hpp
+++ b/src/Lexer/Token.hpp
@@ -2,10 +2,10 @@
#define TOKEN_HPP
#include <iostream>
-#include <string> // <<< Hozzáadva
-#include <string_view> // <<< Hozzáadva
+#include <string>
+#include <string_view>
-#include "Lexer/TokenType.hpp" // Feltételezzük, hogy ez definiálja Type-ot és TypeToString-ot
+#include "Lexer/TokenType.hpp"
namespace Lexer::Tokens {
@@ -27,6 +27,14 @@
<< ", Lexeme: \"" << std::string(lexeme) << "\""
<< " }" << '\n';
}
+
+ std::string dump() const {
+ return + "Token { Type: " + Lexer::Tokens::TypeToString(type) + ", Value: \"" + value + "\""
+ + ", Pos: [" + std::to_string(start_pos) + ", " + std::to_string(end_pos)
+ + ")"
+ + ", Lexeme: \"" + std::string(lexeme) + "\""
+ + " }" + '\n';
+ }
};
inline bool operator==(const Token & lhs, const Token & rhs) {
diff --git a/src/Parser/ParsedExpression.hpp b/src/Parser/ParsedExpression.hpp
index 3f74478..54cce5d 100644
--- a/src/Parser/ParsedExpression.hpp
+++ b/src/Parser/ParsedExpression.hpp
@@ -4,6 +4,7 @@
#include <memory>
#include <string>
+#include "Symbols/SymbolContainer.hpp"
#include "Symbols/Value.hpp"
namespace Parser {
@@ -59,6 +60,46 @@
expr->rhs = std::move(operand);
return expr;
}
+
+ Symbols::Variables::Type getType() const {
+ switch (kind) {
+ case Kind::Literal:
+ return value.getType();
+ break;
+
+ case Kind::Variable:
+ {
+ const auto ns = Symbols::SymbolContainer::instance()->currentScopeName() + ".variables";
+ auto symbol = Symbols::SymbolContainer::instance()->get(ns, name);
+ if (!symbol) {
+ throw std::runtime_error("Unknown variable: " + name + " in namespace: " + ns +
+ " File: " + __FILE__ + ":" + std::to_string(__LINE__));
+ }
+ return symbol->getValue().getType();
+ }
+
+ case Kind::Binary:
+ {
+ auto lhsType = lhs->value.getType();
+ //auto rhsType = rhs->value.getType();
+ return lhsType; // Bináris kifejezésnél a típusok azonosak, tehát a bal oldali típust visszaadhatjuk
+ }
+
+ case Kind::Unary:
+ {
+ //auto operandType = op.
+ if (op == "!") {
+ return Symbols::Variables::Type::BOOLEAN; // Mivel a '!' operátor bool típust vár
+ }
+ break;
+ }
+
+ default:
+ throw std::runtime_error("Unknown expression kind");
+ }
+
+ throw std::runtime_error("Could not determine type for expression");
+ }
};
} // namespace Parser
diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp
index 3c5af2b..37c2081 100644
--- a/src/Parser/Parser.cpp
+++ b/src/Parser/Parser.cpp
@@ -1,27 +1,31 @@
#include "Parser/Parser.hpp"
+#include <stack>
+
+#include "Interpreter/OperationsFactory.hpp"
+#include "Lexer/Operators.hpp"
// Más szükséges include-ok, ha kellenek
namespace Parser {
const std::unordered_map<std::string, Lexer::Tokens::Type> Parser::keywords = {
- { "if", Lexer::Tokens::Type::KEYWORD },
- { "else", Lexer::Tokens::Type::KEYWORD },
- { "while", Lexer::Tokens::Type::KEYWORD },
- { "for", Lexer::Tokens::Type::KEYWORD },
- { "return", Lexer::Tokens::Type::KEYWORD_RETURN },
+ { "if", Lexer::Tokens::Type::KEYWORD },
+ { "else", Lexer::Tokens::Type::KEYWORD },
+ { "while", Lexer::Tokens::Type::KEYWORD },
+ { "for", Lexer::Tokens::Type::KEYWORD },
+ { "return", Lexer::Tokens::Type::KEYWORD_RETURN },
{ "function", Lexer::Tokens::Type::KEYWORD_FUNCTION_DECLARATION },
// Régebbiek:
- { "const", Lexer::Tokens::Type::KEYWORD },
- { "true", Lexer::Tokens::Type::KEYWORD },
- { "false", Lexer::Tokens::Type::KEYWORD },
+ { "const", Lexer::Tokens::Type::KEYWORD },
+ { "true", Lexer::Tokens::Type::KEYWORD },
+ { "false", Lexer::Tokens::Type::KEYWORD },
// változó típusok
- { "null", Lexer::Tokens::Type::KEYWORD_NULL },
- { "int", Lexer::Tokens::Type::KEYWORD_INT },
- { "double", Lexer::Tokens::Type::KEYWORD_DOUBLE },
- { "float", Lexer::Tokens::Type::KEYWORD_FLOAT },
- { "string", Lexer::Tokens::Type::KEYWORD_STRING },
- { "boolean", Lexer::Tokens::Type::KEYWORD_BOOLEAN },
- { "bool", Lexer::Tokens::Type::KEYWORD_BOOLEAN },
+ { "null", Lexer::Tokens::Type::KEYWORD_NULL },
+ { "int", Lexer::Tokens::Type::KEYWORD_INT },
+ { "double", Lexer::Tokens::Type::KEYWORD_DOUBLE },
+ { "float", Lexer::Tokens::Type::KEYWORD_FLOAT },
+ { "string", Lexer::Tokens::Type::KEYWORD_STRING },
+ { "boolean", Lexer::Tokens::Type::KEYWORD_BOOLEAN },
+ { "bool", Lexer::Tokens::Type::KEYWORD_BOOLEAN },
// ... egyéb kulcsszavak ...
};
@@ -34,4 +38,299 @@
{ Lexer::Tokens::Type::KEYWORD_BOOLEAN, Symbols::Variables::Type::BOOLEAN },
};
+void Parser::parseVariableDefinition() {
+ Symbols::Variables::Type var_type = parseType();
+
+ Lexer::Tokens::Token id_token = expect(Lexer::Tokens::Type::VARIABLE_IDENTIFIER);
+ std::string var_name = id_token.value;
+
+ if (!var_name.empty() && var_name[0] == '$') {
+ var_name = var_name.substr(1);
+ }
+ const auto ns = Symbols::SymbolContainer::instance()->currentScopeName();
+
+ expect(Lexer::Tokens::Type::OPERATOR_ASSIGNMENT, "=");
+
+ auto expr = parseParsedExpression(var_type);
+ Interpreter::OperationsFactory::defineVariableWithExpression(
+ var_name, var_type, std::move(expr), ns, current_filename_, id_token.line_number, id_token.column_number);
+ expect(Lexer::Tokens::Type::PUNCTUATION, ";");
+}
+
+void Parser::parseFunctionDefinition() {
+ expect(Lexer::Tokens::Type::KEYWORD_FUNCTION_DECLARATION);
+ Lexer::Tokens::Token id_token = expect(Lexer::Tokens::Type::IDENTIFIER);
+ std::string func_name = id_token.value;
+ Symbols::Variables::Type func_return_type = Symbols::Variables::Type::NULL_TYPE;
+ expect(Lexer::Tokens::Type::OPERATOR_ASSIGNMENT, "=");
+ expect(Lexer::Tokens::Type::PUNCTUATION, "(");
+
+ Symbols::FunctionParameterInfo param_infos;
+
+ if (currentToken().type != Lexer::Tokens::Type::PUNCTUATION || currentToken().value != ")") {
+ while (true) {
+ // Paraméter típusa
+ Symbols::Variables::Type param_type = parseType(); // Ez elfogyasztja a type tokent
+
+ // Paraméter név ($variable)
+ Lexer::Tokens::Token param_id_token = expect(Lexer::Tokens::Type::VARIABLE_IDENTIFIER);
+ std::string param_name = param_id_token.value;
+ if (!param_name.empty() && param_name[0] == '$') { // '$' eltávolítása
+ param_name = param_name.substr(1);
+ }
+
+ param_infos.push_back({ param_name, param_type });
+
+ // Vessző vagy zárójel következik?
+ if (match(Lexer::Tokens::Type::PUNCTUATION, ",")) {
+ continue;
+ }
+ if (currentToken().type == Lexer::Tokens::Type::PUNCTUATION && currentToken().value == ")") {
+ break; // Lista vége
+ }
+ reportError("Expected ',' or ')' in parameter list");
+ }
+ }
+ // Most a ')' következik
+ expect(Lexer::Tokens::Type::PUNCTUATION, ")");
+
+ // check if we have a option return type: function name() type { ... }
+ for (const auto & _type : Parser::variable_types) {
+ if (match(_type.first)) {
+ func_return_type = _type.second;
+ break;
+ }
+ }
+
+ Lexer::Tokens::Token opening_brace = expect(Lexer::Tokens::Type::PUNCTUATION, "{");
+
+ // only parse the body if we checked out if not exists the function and created the symbol
+ parseFunctionBody(opening_brace, func_name, func_return_type, param_infos);
+}
+
+Symbols::Value Parser::parseNumericLiteral(const std::string & value, bool is_negative, Symbols::Variables::Type type) {
+ try {
+ switch (type) {
+ case Symbols::Variables::Type::INTEGER:
+ {
+ if (value.find('.') != std::string::npos) {
+ throw std::invalid_argument("Floating point value in integer context: " + value);
+ }
+ int v = std::stoi(value);
+ return Symbols::Value(is_negative ? -v : v);
+ }
+ case Symbols::Variables::Type::DOUBLE:
+ {
+ double v = std::stod(value);
+ return Symbols::Value(is_negative ? -v : v);
+ }
+ case Symbols::Variables::Type::FLOAT:
+ {
+ float v = std::stof(value);
+ return Symbols::Value(is_negative ? -v : v);
+ }
+ default:
+ throw std::invalid_argument("Unsupported numeric type");
+ }
+ } catch (const std::invalid_argument & e) {
+ reportError("Invalid numeric literal: " + value + " (" + e.what() + ")");
+ } catch (const std::out_of_range & e) {
+ reportError("Numeric literal out of range: " + value + " (" + e.what() + ")");
+ }
+
+ return Symbols::Value(); // unreachable
+}
+
+void Parser::parseFunctionBody(const Lexer::Tokens::Token & opening_brace, const std::string & function_name,
+ Symbols::Variables::Type return_type, const Symbols::FunctionParameterInfo & params) {
+ size_t braceDepth = 0;
+ int peek = 0;
+ int tokenIndex = current_token_index_;
+ Lexer::Tokens::Token currentToken_;
+ Lexer::Tokens::Token closing_brace;
+
+ while (tokenIndex < tokens_.size()) {
+ currentToken_ = peekToken(peek);
+ if (currentToken_.type == Lexer::Tokens::Type::PUNCTUATION) {
+ if (currentToken_.value == "{") {
+ ++braceDepth;
+ } else if (currentToken_.value == "}") {
+ if (braceDepth == 0) {
+ closing_brace = currentToken_;
+ break;
+ }
+ --braceDepth;
+ }
+ }
+ tokenIndex++;
+ peek++;
+ }
+ if (braceDepth != 0) {
+ reportError("Unmatched braces in function body");
+ }
+ std::vector<Lexer::Tokens::Token> filtered_tokens;
+ auto startIt = std::find(tokens_.begin(), tokens_.end(), opening_brace);
+ auto endIt = std::find(tokens_.begin(), tokens_.end(), closing_brace);
+
+ if (startIt != tokens_.end() && endIt != tokens_.end() && startIt < endIt) {
+ filtered_tokens = std::vector<Lexer::Tokens::Token>(startIt + 1, endIt);
+ }
+ std::string_view input_string = input_str_view_.substr(opening_brace.end_pos, closing_brace.end_pos);
+
+ current_token_index_ = tokenIndex;
+ expect(Lexer::Tokens::Type::PUNCTUATION, "}");
+ const std::string newns = Symbols::SymbolContainer::instance()->currentScopeName() + "." + function_name;
+ Symbols::SymbolContainer::instance()->create(newns);
+ std::shared_ptr<Parser> parser = std::make_shared<Parser>();
+ parser->parseScript(filtered_tokens, input_string, this->current_filename_);
+ Symbols::SymbolContainer::instance()->enterPreviousScope();
+ // create function
+ Interpreter::OperationsFactory::defineFunction(
+ function_name, params, return_type, Symbols::SymbolContainer::instance()->currentScopeName(),
+ this->current_filename_, currentToken_.line_number, currentToken_.column_number);
+}
+
+ParsedExpressionPtr Parser::parseParsedExpression(const Symbols::Variables::Type & expected_var_type) {
+ std::stack<std::string> operator_stack;
+ std::vector<ParsedExpressionPtr> output_queue;
+
+ bool expect_unary = true;
+
+ while (true) {
+ auto token = currentToken();
+
+ if (token.type == Lexer::Tokens::Type::PUNCTUATION && token.lexeme == "(") {
+ operator_stack.push("(");
+ consumeToken();
+ expect_unary = true;
+ } else if (token.type == Lexer::Tokens::Type::PUNCTUATION && token.lexeme == ")") {
+ consumeToken();
+ while (!operator_stack.empty() && operator_stack.top() != "(") {
+ std::string op = operator_stack.top();
+ operator_stack.pop();
+
+ if (op == "u-" || op == "u+") {
+ if (output_queue.empty()) {
+ reportError("Missing operand for unary operator");
+ }
+ auto rhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ output_queue.push_back(Lexer::applyOperator(op, std::move(rhs)));
+ } else {
+ if (output_queue.size() < 2) {
+ reportError("Malformed expression");
+ }
+ auto rhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ auto lhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ output_queue.push_back(Lexer::applyOperator(op, std::move(rhs), std::move(lhs)));
+ }
+ }
+
+ if (operator_stack.empty() || operator_stack.top() != "(") {
+ reportError("Mismatched parentheses");
+ }
+ operator_stack.pop(); // remove "("
+ expect_unary = false;
+ } else if (token.type == Lexer::Tokens::Type::OPERATOR_ARITHMETIC) {
+ std::string op = std::string(token.lexeme);
+
+ if (expect_unary && Lexer::isUnaryOperator(op)) {
+ op = "u" + op; // pl. u-, u+ vagy u!
+ }
+
+ while (!operator_stack.empty()) {
+ const std::string & top = operator_stack.top();
+ if ((Lexer::isLeftAssociative(op) && Lexer::getPrecedence(op) <= Lexer::getPrecedence(top)) ||
+ (!Lexer::isLeftAssociative(op) && Lexer::getPrecedence(op) < Lexer::getPrecedence(top))) {
+ operator_stack.pop();
+
+ if (top == "u-" || top == "u+") {
+ if (output_queue.empty()) {
+ reportError("Missing operand for unary operator");
+ }
+ auto rhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ output_queue.push_back(Lexer::applyOperator(top, std::move(rhs)));
+ } else {
+ if (output_queue.size() < 2) {
+ reportError("Malformed expression");
+ }
+ auto rhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ auto lhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ output_queue.push_back(Lexer::applyOperator(top, std::move(rhs), std::move(lhs)));
+ }
+ } else {
+ break;
+ }
+ }
+
+ operator_stack.push(op);
+ consumeToken();
+ expect_unary = true;
+ } else if (token.type == Lexer::Tokens::Type::NUMBER || token.type == Lexer::Tokens::Type::STRING_LITERAL ||
+ token.type == Lexer::Tokens::Type::KEYWORD ||
+ token.type == Lexer::Tokens::Type::VARIABLE_IDENTIFIER) {
+ if (Lexer::pushOperand(token, expected_var_type, output_queue) == false) {
+ reportError("Expected literal or variable");
+ }
+ consumeToken();
+ expect_unary = false;
+ } else {
+ break;
+ }
+ }
+
+ // Kiürítjük az operator stack-et
+ while (!operator_stack.empty()) {
+ std::string op = operator_stack.top();
+ operator_stack.pop();
+
+ if (op == "(" || op == ")") {
+ reportError("Mismatched parentheses");
+ }
+
+ if (op == "u-" || op == "u+") {
+ if (output_queue.empty()) {
+ reportError("Missing operand for unary operator");
+ }
+ auto rhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ output_queue.push_back(Lexer::applyOperator(op, std::move(rhs)));
+ } else {
+ if (output_queue.size() < 2) {
+ reportError("Malformed expression");
+ }
+ auto rhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ auto lhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ output_queue.push_back(Lexer::applyOperator(op, std::move(rhs), std::move(lhs)));
+ }
+ }
+
+ if (output_queue.size() != 1) {
+ reportError("Expression could not be parsed cleanly");
+ }
+
+ return std::move(output_queue.back());
+}
+
+void Parser::parseScript(const std::vector<Lexer::Tokens::Token> & tokens, std::string_view input_string,
+ const std::string & filename) {
+ tokens_ = tokens;
+ input_str_view_ = input_string;
+ current_token_index_ = 0;
+ current_filename_ = filename;
+
+ while (!isAtEnd() && currentToken().type != Lexer::Tokens::Type::END_OF_FILE) {
+ parseStatement();
+ }
+ if (!isAtEnd() && currentToken().type != Lexer::Tokens::Type::END_OF_FILE) {
+ reportError("Unexpected tokens after program end");
+ }
+}
} // namespace Parser
diff --git a/src/Parser/Parser.hpp b/src/Parser/Parser.hpp
index 41a7545..9956e7d 100644
--- a/src/Parser/Parser.hpp
+++ b/src/Parser/Parser.hpp
@@ -1,60 +1,45 @@
#ifndef PARSER_HPP
#define PARSER_HPP
-#include <algorithm>
-#include <memory>
-#include <stack>
#include <stdexcept>
#include <string>
#include <vector>
-#include "Interpreter/ExpressionBuilder.hpp"
-#include "Interpreter/OperationsFactory.hpp"
+#include "BaseException.hpp"
#include "Lexer/Token.hpp"
#include "Lexer/TokenType.hpp"
#include "Parser/ParsedExpression.hpp"
#include "Symbols/ParameterContainer.hpp"
-#include "Symbols/SymbolContainer.hpp"
#include "Symbols/Value.hpp"
namespace Parser {
-
-class SyntaxError : public std::runtime_error {
- public:
- SyntaxError(const std::string & message, const int line, const int col) :
- std::runtime_error(message + " at line " + std::to_string(line) + ", column " + std::to_string(col)) {}
-
- SyntaxError(const std::string & message, const Lexer::Tokens::Token & token) :
- SyntaxError(
- message + " (found token: '" + token.value + "' type: " + Lexer::Tokens::TypeToString(token.type) + ")",
- token.line_number, token.column_number) {}
-};
class Parser {
public:
Parser() {}
- void parseScript(const std::vector<Lexer::Tokens::Token> & tokens, std::string_view input_string,
- const std::string & filename) {
- tokens_ = tokens;
- input_str_view_ = input_string;
- current_token_index_ = 0;
- current_filename_ = filename;
+ class Exception : public BaseException {
+ public:
+ using BaseException::BaseException;
- try {
- while (!isAtEnd() && currentToken().type != Lexer::Tokens::Type::END_OF_FILE) {
- parseStatement();
- }
- if (!isAtEnd() && currentToken().type != Lexer::Tokens::Type::END_OF_FILE) {
- reportError("Unexpected tokens after program end");
- }
- } catch (const SyntaxError & e) {
- std::cerr << "Syntax Error: " << e.what() << '\n';
- } catch (const std::exception & e) {
- std::cerr << "Error during parsing: " << e.what() << '\n';
- throw;
+ Exception(const std::string & msg, const Lexer::Tokens::Token & token) {
+ rawMessage_ = msg + ": " + token.dump();
+ context_ =
+ " at line: " + std::to_string(token.line_number) + ", column: " + std::to_string(token.column_number);
+ formattedMessage_ = formatMessage();
}
- }
+
+ Exception(const std::string & msg, int line, int col) {
+ rawMessage_ = msg;
+ context_ = " at line: " + std::to_string(line) + ", column: " + std::to_string(col);
+ formattedMessage_ = formatMessage();
+ }
+
+ std::string formatMessage() const override { return "[Syntax ERROR] >>" + context_ + " << : " + rawMessage_; }
+ };
+
+ void parseScript(const std::vector<Lexer::Tokens::Token> & tokens, std::string_view input_string,
+ const std::string & filename);
static const std::unordered_map<std::string, Lexer::Tokens::Type> keywords;
static const std::unordered_map<Lexer::Tokens::Type, Symbols::Variables::Type> variable_types;
@@ -161,19 +146,14 @@
(current_token_index_ == tokens_.size() - 1 && tokens_.back().type == Lexer::Tokens::Type::END_OF_FILE);
}
- // --- Hibakezelés ---
- // Hiba jelentése és kivétel dobása
[[noreturn]] void reportError(const std::string & message) {
- // Használjuk az aktuális token pozícióját, ha még nem értünk a végére
if (current_token_index_ < tokens_.size()) {
- throw SyntaxError(message, tokens_[current_token_index_]);
- } // Ha már a végén vagyunk, az utolsó ismert pozíciót használjuk
+ throw Exception(message, tokens_[current_token_index_]);
+ }
int line = tokens_.empty() ? 0 : tokens_.back().line_number;
int col = tokens_.empty() ? 0 : tokens_.back().column_number;
- throw SyntaxError(message, line, col);
+ throw Exception(message, line, col);
}
-
- // --- Elemzési Módszerek (Moduláris részek) ---
// parseStatement (változatlan)
void parseStatement() {
@@ -194,81 +174,8 @@
reportError("Unexpected token at beginning of statement");
}
- void parseVariableDefinition() {
- Symbols::Variables::Type var_type = parseType();
-
- Lexer::Tokens::Token id_token = expect(Lexer::Tokens::Type::VARIABLE_IDENTIFIER);
- std::string var_name = id_token.value;
-
- if (!var_name.empty() && var_name[0] == '$') {
- var_name = var_name.substr(1);
- }
- const auto ns = Symbols::SymbolContainer::instance()->currentScopeName();
-
- expect(Lexer::Tokens::Type::OPERATOR_ASSIGNMENT, "=");
- /*
- Symbols::Value initial_value = parseValue(var_type);
-
- Interpreter::OperationsFactory::defineSimpleVariable(var_name, initial_value, ns, this->current_filename_,
- id_token.line_number, id_token.column_number);
-*/
-
- auto expr = parseParsedExpression(var_type);
- Interpreter::OperationsFactory::defineVariableWithExpression(
- var_name, var_type, std::move(expr), ns, current_filename_, id_token.line_number, id_token.column_number);
- expect(Lexer::Tokens::Type::PUNCTUATION, ";");
- }
-
- void parseFunctionDefinition() {
- expect(Lexer::Tokens::Type::KEYWORD_FUNCTION_DECLARATION);
- Lexer::Tokens::Token id_token = expect(Lexer::Tokens::Type::IDENTIFIER);
- std::string func_name = id_token.value;
- Symbols::Variables::Type func_return_type = Symbols::Variables::Type::NULL_TYPE;
- expect(Lexer::Tokens::Type::OPERATOR_ASSIGNMENT, "=");
- expect(Lexer::Tokens::Type::PUNCTUATION, "(");
-
- Symbols::FunctionParameterInfo param_infos;
-
- if (currentToken().type != Lexer::Tokens::Type::PUNCTUATION || currentToken().value != ")") {
- while (true) {
- // Paraméter típusa
- Symbols::Variables::Type param_type = parseType(); // Ez elfogyasztja a type tokent
-
- // Paraméter név ($variable)
- Lexer::Tokens::Token param_id_token = expect(Lexer::Tokens::Type::VARIABLE_IDENTIFIER);
- std::string param_name = param_id_token.value;
- if (!param_name.empty() && param_name[0] == '$') { // '$' eltávolítása
- param_name = param_name.substr(1);
- }
-
- param_infos.push_back({ param_name, param_type });
-
- // Vessző vagy zárójel következik?
- if (match(Lexer::Tokens::Type::PUNCTUATION, ",")) {
- continue;
- }
- if (currentToken().type == Lexer::Tokens::Type::PUNCTUATION && currentToken().value == ")") {
- break; // Lista vége
- }
- reportError("Expected ',' or ')' in parameter list");
- }
- }
- // Most a ')' következik
- expect(Lexer::Tokens::Type::PUNCTUATION, ")");
-
- // check if we have a option return type: function name() type { ... }
- for (const auto & _type : Parser::variable_types) {
- if (match(_type.first)) {
- func_return_type = _type.second;
- break;
- }
- }
-
- Lexer::Tokens::Token opening_brace = expect(Lexer::Tokens::Type::PUNCTUATION, "{");
-
- // only parse the body if we checked out if not exists the function and created the symbol
- parseFunctionBody(opening_brace, func_name, func_return_type, param_infos);
- }
+ void parseVariableDefinition();
+ void parseFunctionDefinition();
// --- Elemzési Segédfüggvények ---
@@ -333,255 +240,12 @@
return Symbols::Value(); // compiler happy
}
- Symbols::Value parseNumericLiteral(const std::string & value, bool is_negative, Symbols::Variables::Type type) {
- try {
- switch (type) {
- case Symbols::Variables::Type::INTEGER:
- {
- if (value.find('.') != std::string::npos) {
- throw std::invalid_argument("Floating point value in integer context: " + value);
- }
- int v = std::stoi(value);
- return Symbols::Value(is_negative ? -v : v);
- }
- case Symbols::Variables::Type::DOUBLE:
- {
- double v = std::stod(value);
- return Symbols::Value(is_negative ? -v : v);
- }
- case Symbols::Variables::Type::FLOAT:
- {
- float v = std::stof(value);
- return Symbols::Value(is_negative ? -v : v);
- }
- default:
- throw std::invalid_argument("Unsupported numeric type");
- }
- } catch (const std::invalid_argument & e) {
- reportError("Invalid numeric literal: " + value + " (" + e.what() + ")");
- } catch (const std::out_of_range & e) {
- reportError("Numeric literal out of range: " + value + " (" + e.what() + ")");
- }
-
- return Symbols::Value(); // unreachable
- }
+ Symbols::Value parseNumericLiteral(const std::string & value, bool is_negative, Symbols::Variables::Type type);
void parseFunctionBody(const Lexer::Tokens::Token & opening_brace, const std::string & function_name,
- Symbols::Variables::Type return_type, const Symbols::FunctionParameterInfo & params) {
- size_t braceDepth = 0;
- int peek = 0;
- int tokenIndex = current_token_index_;
- Lexer::Tokens::Token currentToken_;
- Lexer::Tokens::Token closing_brace;
+ Symbols::Variables::Type return_type, const Symbols::FunctionParameterInfo & params);
- while (tokenIndex < tokens_.size()) {
- currentToken_ = peekToken(peek);
- if (currentToken_.type == Lexer::Tokens::Type::PUNCTUATION) {
- if (currentToken_.value == "{") {
- ++braceDepth;
- } else if (currentToken_.value == "}") {
- if (braceDepth == 0) {
- closing_brace = currentToken_;
- break;
- }
- --braceDepth;
- }
- }
- tokenIndex++;
- peek++;
- }
- if (braceDepth != 0) {
- reportError("Unmatched braces in function body");
- }
- std::vector<Lexer::Tokens::Token> filtered_tokens;
- auto startIt = std::find(tokens_.begin(), tokens_.end(), opening_brace);
- auto endIt = std::find(tokens_.begin(), tokens_.end(), closing_brace);
-
- if (startIt != tokens_.end() && endIt != tokens_.end() && startIt < endIt) {
- filtered_tokens = std::vector<Lexer::Tokens::Token>(startIt + 1, endIt);
- }
- std::string_view input_string = input_str_view_.substr(opening_brace.end_pos, closing_brace.end_pos);
-
- current_token_index_ = tokenIndex;
- expect(Lexer::Tokens::Type::PUNCTUATION, "}");
- const std::string newns = Symbols::SymbolContainer::instance()->currentScopeName() + "." + function_name;
- Symbols::SymbolContainer::instance()->create(newns);
- std::shared_ptr<Parser> parser = std::make_shared<Parser>();
- parser->parseScript(filtered_tokens, input_string, this->current_filename_);
- Symbols::SymbolContainer::instance()->enterPreviousScope();
- // create function
- Interpreter::OperationsFactory::defineFunction(
- function_name, params, return_type, Symbols::SymbolContainer::instance()->currentScopeName(),
- this->current_filename_, currentToken_.line_number, currentToken_.column_number);
- }
-
- ParsedExpressionPtr parseParsedExpression(const Symbols::Variables::Type & expected_var_type) {
- std::stack<std::string> operator_stack;
- std::vector<ParsedExpressionPtr> output_queue;
-
- auto getPrecedence = [](const std::string & op) -> int {
- if (op == "+" || op == "-") {
- return 1;
- }
- if (op == "*" || op == "/") {
- return 2;
- }
- if (op == "u-" || op == "u+") {
- return 3;
- }
- return 0;
- };
-
- auto isLeftAssociative = [](const std::string & op) -> bool {
- return !(op == "u-" || op == "u+");
- };
-
- auto applyOperator = [](const std::string & op, ParsedExpressionPtr rhs, ParsedExpressionPtr lhs = nullptr) {
- if (op == "u-" || op == "u+") {
- std::string real_op = (op == "u-") ? "-" : "+";
- return ParsedExpression::makeUnary(real_op, std::move(rhs));
- } else {
- return ParsedExpression::makeBinary(op, std::move(lhs), std::move(rhs));
- }
- };
-
- auto pushOperand = [&](const Lexer::Tokens::Token & token) {
- if (token.type == Lexer::Tokens::Type::NUMBER || token.type == Lexer::Tokens::Type::STRING_LITERAL ||
- token.type == Lexer::Tokens::Type::KEYWORD) {
- output_queue.push_back(
- ParsedExpression::makeLiteral(Symbols::Value::fromString(token.value, expected_var_type)));
- } else if (token.type == Lexer::Tokens::Type::VARIABLE_IDENTIFIER) {
- std::string name = token.value;
- if (!name.empty() && name[0] == '$') {
- name = name.substr(1);
- }
- output_queue.push_back(ParsedExpression::makeVariable(name));
- } else {
- reportError("Expected literal or variable");
- }
- };
-
- bool expect_unary = true;
-
- while (true) {
- auto token = currentToken();
-
- if (token.type == Lexer::Tokens::Type::PUNCTUATION && token.lexeme == "(") {
- operator_stack.push("(");
- consumeToken();
- expect_unary = true;
- } else if (token.type == Lexer::Tokens::Type::PUNCTUATION && token.lexeme == ")") {
- consumeToken();
- while (!operator_stack.empty() && operator_stack.top() != "(") {
- std::string op = operator_stack.top();
- operator_stack.pop();
-
- if (op == "u-" || op == "u+") {
- if (output_queue.empty()) {
- reportError("Missing operand for unary operator");
- }
- auto rhs = std::move(output_queue.back());
- output_queue.pop_back();
- output_queue.push_back(applyOperator(op, std::move(rhs)));
- } else {
- if (output_queue.size() < 2) {
- reportError("Malformed expression");
- }
- auto rhs = std::move(output_queue.back());
- output_queue.pop_back();
- auto lhs = std::move(output_queue.back());
- output_queue.pop_back();
- output_queue.push_back(applyOperator(op, std::move(rhs), std::move(lhs)));
- }
- }
-
- if (operator_stack.empty() || operator_stack.top() != "(") {
- reportError("Mismatched parentheses");
- }
- operator_stack.pop(); // remove "("
- expect_unary = false;
- } else if (token.type == Lexer::Tokens::Type::OPERATOR_ARITHMETIC) {
- std::string op = std::string(token.lexeme);
- if (expect_unary && (op == "-" || op == "+")) {
- op = "u" + op; // pl. u-
- }
-
- while (!operator_stack.empty()) {
- const std::string & top = operator_stack.top();
- if ((isLeftAssociative(op) && getPrecedence(op) <= getPrecedence(top)) ||
- (!isLeftAssociative(op) && getPrecedence(op) < getPrecedence(top))) {
- operator_stack.pop();
-
- if (top == "u-" || top == "u+") {
- if (output_queue.empty()) {
- reportError("Missing operand for unary operator");
- }
- auto rhs = std::move(output_queue.back());
- output_queue.pop_back();
- output_queue.push_back(applyOperator(top, std::move(rhs)));
- } else {
- if (output_queue.size() < 2) {
- reportError("Malformed expression");
- }
- auto rhs = std::move(output_queue.back());
- output_queue.pop_back();
- auto lhs = std::move(output_queue.back());
- output_queue.pop_back();
- output_queue.push_back(applyOperator(top, std::move(rhs), std::move(lhs)));
- }
- } else {
- break;
- }
- }
-
- operator_stack.push(op);
- consumeToken();
- expect_unary = true;
- } else if (token.type == Lexer::Tokens::Type::NUMBER || token.type == Lexer::Tokens::Type::STRING_LITERAL ||
- token.type == Lexer::Tokens::Type::KEYWORD ||
- token.type == Lexer::Tokens::Type::VARIABLE_IDENTIFIER) {
- pushOperand(token);
- consumeToken();
- expect_unary = false;
- } else {
- break;
- }
- }
-
- // Kiürítjük az operator stack-et
- while (!operator_stack.empty()) {
- std::string op = operator_stack.top();
- operator_stack.pop();
-
- if (op == "(" || op == ")") {
- reportError("Mismatched parentheses");
- }
-
- if (op == "u-" || op == "u+") {
- if (output_queue.empty()) {
- reportError("Missing operand for unary operator");
- }
- auto rhs = std::move(output_queue.back());
- output_queue.pop_back();
- output_queue.push_back(applyOperator(op, std::move(rhs)));
- } else {
- if (output_queue.size() < 2) {
- reportError("Malformed expression");
- }
- auto rhs = std::move(output_queue.back());
- output_queue.pop_back();
- auto lhs = std::move(output_queue.back());
- output_queue.pop_back();
- output_queue.push_back(applyOperator(op, std::move(rhs), std::move(lhs)));
- }
- }
-
- if (output_queue.size() != 1) {
- reportError("Expression could not be parsed cleanly");
- }
-
- return std::move(output_queue.back());
- }
+ ParsedExpressionPtr parseParsedExpression(const Symbols::Variables::Type & expected_var_type);
}; // class Parser
diff --git a/src/Symbols/BaseSymbol.hpp b/src/Symbols/BaseSymbol.hpp
index 604463c..3d25224 100644
--- a/src/Symbols/BaseSymbol.hpp
+++ b/src/Symbols/BaseSymbol.hpp
@@ -33,7 +33,7 @@
const std::string & context() const { return context_; }
- Symbols::Kind type() const { return kind_; }
+ Symbols::Kind getKind() const { return kind_; }
// Virtuális getter/setter a value-hoz
virtual const Value & getValue() const { return value_; }
diff --git a/src/Symbols/SymbolContainer.hpp b/src/Symbols/SymbolContainer.hpp
index c0bb814..fc3fc5d 100644
--- a/src/Symbols/SymbolContainer.hpp
+++ b/src/Symbols/SymbolContainer.hpp
@@ -123,7 +123,7 @@
std::string getNamespaceForSymbol(const SymbolPtr & symbol) const {
std::string base = symbol->context().empty() ? currentScope_ : symbol->context();
- switch (symbol->type()) {
+ switch (symbol->getKind()) {
case Symbols::Kind::Variable:
return base + ".variables";
case Symbols::Kind::Function:
diff --git a/src/Symbols/SymbolTable.hpp b/src/Symbols/SymbolTable.hpp
index f774f8d..7295bc6 100644
--- a/src/Symbols/SymbolTable.hpp
+++ b/src/Symbols/SymbolTable.hpp
@@ -1,7 +1,6 @@
#ifndef SYMBOL_TABLE_HPP
#define SYMBOL_TABLE_HPP
-#include <memory>
#include <vector>
#include "SymbolTypes.hpp"
diff --git a/src/VoidScript.hpp b/src/VoidScript.hpp
index 4f0aed4..661456c 100644
--- a/src/VoidScript.hpp
+++ b/src/VoidScript.hpp
@@ -1,6 +1,5 @@
#ifndef VOIDSCRIPT_HPP
#define VOIDSCRIPT_HPP
-
#include <filesystem>
#include <fstream>
#include <string>
@@ -42,21 +41,24 @@
int run() {
try {
while (!files.empty()) {
- std::string file = files.back();
+ std::string file = files.back();
const std::string file_content = readFile(file);
files.pop_back();
-
std::string _default_namespace_ = file;
std::replace(_default_namespace_.begin(), _default_namespace_.end(), '.', '_');
Symbols::SymbolContainer::instance()->create(_default_namespace_);
-
const std::string ns = Symbols::SymbolContainer::instance()->currentScopeName();
this->lexer->addNamespaceInput(ns, file_content);
const auto tokens = this->lexer->tokenizeNamespace(ns);
+ // dump tokens
+ std::cout << "--- Tokens ---\n";
+ for (const auto & token : tokens) {
+ token.print();
+ }
std::cout << Operations::Container::dump() << "\n";
@@ -69,11 +71,8 @@
} // while (!files.empty())
return 0;
- } catch (const Parser::SyntaxError & e) {
- std::cerr << "Syntax Error during parsing: " << e.what() << '\n';
- return 1;
} catch (const std::exception & e) {
- std::cerr << "An error occurred: " << e.what() << '\n';
+ std::cerr << e.what() << '\n';
return 1;
}
return 1;
--
Gitblit v1.9.3