From 26c1b7dd0faf4b9d69e70309acf260ab06b71868 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Wed, 29 Oct 2025 17:59:26 +0000 Subject: [PATCH] Basic list support --- src/lexer/lexer.h | 2 +- src/parser/parser.cpp | 65 ++++++++++++++++++-- src/parser/parser.h | 28 ++++++--- src/runner/runner.cpp | 136 ++++++++++++++++++++++-------------------- src/runner/runner.h | 1 + 5 files changed, 152 insertions(+), 80 deletions(-) diff --git a/src/lexer/lexer.h b/src/lexer/lexer.h index 510d4df..bb30013 100644 --- a/src/lexer/lexer.h +++ b/src/lexer/lexer.h @@ -15,7 +15,7 @@ class Lexer { private: std::vector delimiters = { - '(', ')', '{', '}', '.', '\n', ' ' + '(', ')', '{', '}', '[', ']', '.', '\n', ' ', ',' }; std::string file; size_t incrementor = -1; diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index fb8ec70..74628c3 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -13,6 +13,9 @@ ASTValue::ASTValue(std::string in) : type(ValueType::String), value(in) {} ASTValue::ASTValue(bool in) : type(ValueType::Bool), value(in) {} ASTValue::ASTValue(long long in) : type(ValueType::Int), value(in) {} ASTValue::ASTValue(double in) : type(ValueType::Float), value(in) {} +ASTValue::ASTValue(ASTList in) : type(ValueType::List), value(std::move(in)) {} + +ASTList::ASTList(std::vector in) : elements(std::move(in)) {} ValueType ASTValue::getValueType(std::string in) { if (in.size() < 1) { @@ -55,7 +58,7 @@ ASTFunctionCall::ASTFunctionCall(std::string func, std::vector args) : ASTIdentifier::ASTIdentifier(std::string in) : name(std::move(in)) {} -std::optional ASTValue::getString() { +std::optional ASTValue::getString() const { if (type == ValueType::String && std::holds_alternative(value)) { return std::get(value); } else { @@ -63,7 +66,7 @@ std::optional ASTValue::getString() { } } -std::optional ASTValue::getInt() { +std::optional ASTValue::getInt() const { if (type == ValueType::Int && std::holds_alternative(value)) { return std::get(value); } else { @@ -71,7 +74,7 @@ std::optional ASTValue::getInt() { } } -std::optional ASTValue::getFloat() { +std::optional ASTValue::getFloat() const { if (type == ValueType::Float && std::holds_alternative(value)) { return std::get(value); } else { @@ -79,7 +82,7 @@ std::optional ASTValue::getFloat() { } } -std::optional ASTValue::getBool() { +std::optional ASTValue::getBool() const { if (type == ValueType::Bool && std::holds_alternative(value)) { return std::get(value); } else { @@ -87,6 +90,18 @@ std::optional ASTValue::getBool() { } } +std::optional ASTValue::getList() const { + if (type == ValueType::List && std::holds_alternative(value)) { + return std::get(value); + } else { + return {}; + } +} + +std::vector ASTList::getElements() const { + return elements; +} + std::optional ASTCodeBlock::consume() { if (iterator < content.size()) { return content[iterator++]; // Post-increment: returns current, then increments @@ -132,6 +147,12 @@ TokenType ASTCodeBlock::getTokenType() { if (token == ")") { return TokenType::CloseParen; } + if (token == "[") { + return TokenType::ListStart; + } + if (token == "]") { + return TokenType::ListEnd; + } if (token == "\n") { return TokenType::NewLine; } @@ -288,6 +309,40 @@ void ASTCodeBlock::parseBlock() { nodes.emplace_back(std::make_shared(body)); break; } + case TokenType::ListStart: { + std::vector body; + int depth = 1; + while (depth > 0) { + std::optional token = consume(); + if (token.has_value()) { + if (token.value() == "[") { + depth++; + } else if (token.value() == "]") { + depth--; + if (depth == 0) { + break; + } + } + body.push_back(token.value()); + } else { + std::cout << "Reached end of file while parsing list" << std::endl; + exit(1); + } + } + ASTCodeBlock list_elements_block(body); + std::vector final_nodes; + for (const auto& node : list_elements_block.nodes) { + if (std::holds_alternative>(node)) { + auto ident = std::get>(node); + if (ident->name == ",") { + continue; + } + } + final_nodes.push_back(node); + } + nodes.emplace_back(std::make_shared(ASTList(final_nodes))); + break; + } default: break; } @@ -297,7 +352,7 @@ void ASTCodeBlock::parseBlock() { } } -ASTCodeBlock::ASTCodeBlock() {} +ASTCodeBlock::ASTCodeBlock() = default; ASTCodeBlock::ASTCodeBlock(std::vector in) : content(std::move(in)) { parseBlock(); diff --git a/src/parser/parser.h b/src/parser/parser.h index c4801b5..a23653c 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -13,14 +13,24 @@ class ASTCodeBlock; class ASTIdentifier; typedef std::variant, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr> ASTNode; -typedef std::variant RealValue; + +class ASTList { + private: + std::vector elements; + + public: + explicit ASTList(std::vector in); + std::vector getElements() const; +}; + +typedef std::variant RealValue; enum class ValueType { - Int, Float, String, Bool, None + Int, Float, String, Bool, List, None }; enum class TokenType { - Identifier, Value, Function, FunctionCallStart, OpenParen, CloseParen, CodeBlockStart, CodeBlockEnd, NewLine, None + Identifier, Value, Function, FunctionCallStart, OpenParen, CloseParen, CodeBlockStart, CodeBlockEnd, NewLine, ListStart, ListEnd, None }; /** @@ -37,14 +47,16 @@ private: public: ValueType type; ValueType getValueType(std::string in); - std::optional getString(); - std::optional getInt(); - std::optional getFloat(); - std::optional getBool(); + std::optional getString() const; + std::optional getInt() const; + std::optional getFloat() const; + std::optional getBool() const; + std::optional getList() const; explicit ASTValue(std::string in); explicit ASTValue(long long in); explicit ASTValue(double in); explicit ASTValue(bool in); + explicit ASTValue(ASTList in); ASTValue(); }; @@ -95,4 +107,4 @@ class ASTIdentifier { explicit ASTIdentifier(std::string in); }; -ASTNode parser(std::vector in); +ASTNode parser(std::vector in); \ No newline at end of file diff --git a/src/runner/runner.cpp b/src/runner/runner.cpp index 3f8a490..1a74fad 100644 --- a/src/runner/runner.cpp +++ b/src/runner/runner.cpp @@ -17,6 +17,71 @@ std::map Executor::getVariables() { std::map globalVariables; +void Executor::printValue(const ASTValue& arg) { + if (arg.type == ValueType::String) { + std::optional argString = arg.getString(); + if (argString.has_value()) { + std::cout << argString.value(); + } else { + std::cout << "Type mismatch - expecting string but got something else"; + } + } else if (arg.type == ValueType::Int) { + std::optional argInt = arg.getInt(); + if (argInt.has_value()) { + std::cout << argInt.value(); + } else { + std::cout << "Type mismatch - expecting int but got something else"; + } + } else if (arg.type == ValueType::Float) { + std::optional argFloat = arg.getFloat(); + if (argFloat.has_value()) { + std::cout << argFloat.value(); + } else { + std::cout << "Type mismatch - expecting float but got something else"; + } + } else if (arg.type == ValueType::Bool) { + std::optional argBool = arg.getBool(); + if (argBool.has_value()) { + std::cout << (argBool.value() ? "true" : "false"); + } else { + std::cout << "Type mismatch - expecting bool but got something else"; + } + } else if (arg.type == ValueType::List) { + std::optional list = arg.getList(); + if (list.has_value()) { + std::cout << "["; + auto elements = list.value().getElements(); + for (size_t i = 0; i < elements.size(); ++i) { + auto& node = elements[i]; + if (std::holds_alternative>(node)) { + printValue(*std::get>(node)); + } else if (std::holds_alternative>(node)) { + auto name = std::get>(node)->name; + if (variables.count(name)) { + Object obj = variables[name]; + if (!obj.isCustomObject && std::holds_alternative(obj.value)) { + printValue(std::get(obj.value)); + } else { + std::cout << ""; + } + } else { + std::cout << ""; + } + } else { + std::cout << ""; + } + + if (i < elements.size() - 1) { + std::cout << ", "; + } + } + std::cout << "]"; + } + } else { + std::cout << "Type mismatch - expecting string, int, float, bool or list but got something else"; + } +} + std::optional Executor::consume() { if (iterator < code.nodes.size()) { return code.nodes[iterator++]; @@ -184,40 +249,9 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map(object.value)) { arg = std::get(object.value); + printValue(arg); } else { - std::cout << "Type mismatch - expecting string, int, float, or bool but got something else" << std::endl; - exit(1); - } - if (arg.type == ValueType::String) { - std::optional argString = arg.getString(); - if (argString.has_value()) { - std::cout << argString.value(); - } else { - std::cout << "Type mismatch - expecting string but got something else" << std::endl; - } - } else if (arg.type == ValueType::Int) { - std::optional argInt = arg.getInt(); - if (argInt.has_value()) { - std::cout << argInt.value(); - } else { - std::cout << "Type mismatch - expecting int but got something else" << std::endl; - } - } else if (arg.type == ValueType::Float) { - std::optional argFloat = arg.getFloat(); - if (argFloat.has_value()) { - std::cout << argFloat.value(); - } else { - std::cout << "Type mismatch - expecting float but got something else" << std::endl; - } - } else if (arg.type == ValueType::Bool) { - std::optional argBool = arg.getBool(); - if (argBool.has_value()) { - std::cout << argBool.value(); - } else { - std::cout << "Type mismatch - expecting bool but got something else" << std::endl; - } - } else { - std::cout << "Type mismatch - expecting string, int, float, or bool but got something else" << std::endl; + std::cout << "Type mismatch - expecting printable value but got something else"; } } } else if (fnName == "println") { @@ -225,40 +259,10 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map(object.value)) { arg = std::get(object.value); + printValue(arg); + std::cout << std::endl; } else { - std::cout << "Type mismatch - expecting string, int, float, or bool but got something else" << std::endl; - exit(1); - } - if (arg.type == ValueType::String) { - std::optional argString = arg.getString(); - if (argString.has_value()) { - std::cout << argString.value() << std::endl; - } else { - std::cout << "Type mismatch - expecting string but got something else" << std::endl; - } - } else if (arg.type == ValueType::Int) { - std::optional argInt = arg.getInt(); - if (argInt.has_value()) { - std::cout << argInt.value() << std::endl; - } else { - std::cout << "Type mismatch - expecting int but got something else" << std::endl; - } - } else if (arg.type == ValueType::Float) { - std::optional argFloat = arg.getFloat(); - if (argFloat.has_value()) { - std::cout << argFloat.value() << std::endl; - } else { - std::cout << "Type mismatch - expecting float but got something else" << std::endl; - } - } else if (arg.type == ValueType::Bool) { - std::optional argBool = arg.getBool(); - if (argBool.has_value()) { - std::cout << (argBool.value() ? "true" : "false") << std::endl; - } else { - std::cout << "Type mismatch - expecting bool but got something else" << std::endl; - } - } else { - std::cout << "Type mismatch - expecting string, int, float, or bool but got something else" << std::endl; + std::cout << "Type mismatch - expecting printable value but got something else" << std::endl; } } } else if (fnName == "if") { diff --git a/src/runner/runner.h b/src/runner/runner.h index 368ab78..1e1b2fd 100644 --- a/src/runner/runner.h +++ b/src/runner/runner.h @@ -35,6 +35,7 @@ class Executor { size_t iterator = 0; std::optional consume(); std::optional peek(int ahead = 1); + void printValue(const ASTValue& arg); public: explicit Executor(ASTCodeBlock in, bool isInitCall = false, std::map scopeVals = {}, std::vector args = {}); std::map getVariables();