From 59e273b26e68dd5a319719d8b18626a3edeaea2f Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Tue, 27 Jan 2026 21:12:09 +1100 Subject: [PATCH] Member access (no writing yet) --- src/lexer.cpp | 3 +- src/parser.cpp | 115 +++++++++++++++++++++++++++++++++++++++++++--- src/parser.h | 2 +- tests/struct.sols | 3 ++ 4 files changed, 115 insertions(+), 8 deletions(-) diff --git a/src/lexer.cpp b/src/lexer.cpp index f7f01f8..3177889 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -100,7 +100,6 @@ namespace Solstice { } // tokens which are not followed by anything case '\n': - case ':': { if (!buf.empty()) { addToken(buf); @@ -114,6 +113,8 @@ namespace Solstice { case ')': case '}': case ',': + case ':': + case '.': { if (!buf.empty()) { addToken(buf); diff --git a/src/parser.cpp b/src/parser.cpp index 4a958d4..f1fe51c 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #define parseOneToken(token) Parser({token}).parse().children[0] @@ -267,6 +268,81 @@ namespace Solstice { code = parsedStdlib.generateCode(); } } + + // Process object member access + for (size_t i = 0; i < children.size(); i++) { + SolNode& child = children[i]; + if (child.nodeType == SolNodeType::In) { + if (variables.find(child.outputId) == variables.end()) { + Error::syntaxError(child.outputId + " could not be found", child.line, child.lineContent); + } + std::string type = variables[child.outputId]; + if (type.substr(0, 7) != "object(") { + Error::typingError(child.outputId + " is not an object", child.line, child.lineContent); + } + std::regex pattern("([a-zA-Z0-9_:<>*&]+)\\s+\\b" + child.children[0].outputId + "\\b"); + std::smatch match; + + if (std::regex_search(type, match, pattern)) { + if (i + 1 < children.size() && children[i + 1].nodeType == SolNodeType::Set) { + // handle stuff in the equals + } else { + SolGroundCodeBlock codeBlock; + GroundInstruction gi = groundCreateInstruction(GETFIELD); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(child.outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(child.children[0].outputId))); + child.outputId = "obj_access_" + std::to_string(tmpIdIterator++); + variables[child.outputId] = match[1]; + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(child.outputId))); + codeBlock.code.push_back(gi); + code.push_back(codeBlock); + } + } else { + Error::typingError("Couldn't find field " + child.children[0].outputId + " in " + child.outputId, child.line, child.lineContent); + } + } + } + + /* + // Process object member access + for (size_t i = 0; i < children.size(); i++) { + SolNode& child = children[i]; + if (child.nodeType == SolNodeType::In) { + if (variables.find(outputId) == variables.end()) { + Error::syntaxError(child.outputId + " could not be found", child.line, child.lineContent); + break; + } + std::string type = variables[outputId]; + if (type.substr(0, 7) != "object(") { + Error::typingError(child.outputId + " is not an object", child.line, child.lineContent); + break; + } + std::regex pattern("([a-zA-Z0-9_:<>*&]+)\\s+\\b" + child.children[0].outputId + "\\b"); + std::smatch match; + + if (std::regex_search(type, match, pattern)) { + if (i + 1 < children.size() && children[i + 1].nodeType == SolNodeType::Set) { + // handle stuff in the equals + } else { + SolGroundCodeBlock codeBlock; + GroundInstruction gi = groundCreateInstruction(GETFIELD); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(children[0].outputId))); + outputId = "obj_access_" + std::to_string(tmpIdIterator++); + variables[outputId] = match[1]; + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); + codeBlock.code.push_back(gi); + code.push_back(codeBlock); + } + } else { + Error::typingError("Couldn't find field " + child.children[0].outputId + " in " + outputId, child.line, child.lineContent); + break; + } + } + } + */ + + // Process other stuff if (nodeType != SolNodeType::If && nodeType != SolNodeType::While && nodeType != SolNodeType::Struct) for (auto& child : children) { auto childCode = child.generateCode(); code.insert(code.end(), childCode.begin(), childCode.end()); @@ -897,17 +973,22 @@ namespace Solstice { return true; } bool Parser::isDouble(std::string in) { + if (in.empty()) return false; + bool foundDot = false; + bool foundDigit = false; + for (const char& c : in) { - if (!std::isdigit(c)) { - if (!foundDot && c == '.') { - foundDot = true; - continue; - } + if (std::isdigit(c)) { + foundDigit = true; + } else if (c == '.' && !foundDot) { + foundDot = true; + } else { return false; } } - return true; + + return foundDot && foundDigit; } bool Parser::isString(std::string in) { if (in.size() > 1 && in[0] == '"' && in.back() == '"') { @@ -1020,6 +1101,9 @@ namespace Solstice { if (in == ")") { return SolNodeType::BracketEnd; } + if (in == ".") { + return SolNodeType::In; + } return SolNodeType::Identifier; } @@ -1690,6 +1774,25 @@ namespace Solstice { rootNode.addNode(newNode); break; } + case SolNodeType::In: { + SolNode inNode(SolNodeType::In); + inNode.line = tokenObj.line; + inNode.lineContent = tokenObj.lineContent; + inNode.outputId = rootNode.children.back().outputId; + rootNode.children.pop_back(); + auto accessopt = consume(); + if (accessopt) { + SolNode accessNode(SolNodeType::Identifier); + accessNode.outputId = accessopt.value().value; + accessNode.line = accessopt.value().line; + accessNode.lineContent = accessopt.value().lineContent; + inNode.addNode(accessNode); + } else { + Error::syntaxError("Expected identifier after '.'", tokenObj.line, tokenObj.lineContent); + } + rootNode.addNode(inNode); + break; + } } } return rootNode; diff --git a/src/parser.h b/src/parser.h index 56259eb..793813a 100644 --- a/src/parser.h +++ b/src/parser.h @@ -57,7 +57,7 @@ namespace Solstice { enum class SolNodeType { - Add, Subtract, Multiply, Divide, Equal, Inequal, Greater, Lesser, EqGreater, EqLesser, Set, While, If, Value, Identifier, None, Root, CodeBlock, CodeBlockStart, CodeBlockEnd, FunctionDef, FunctionCall, Expression, BracketStart, BracketEnd, Puts, Return, InlineGround, Struct, New + Add, Subtract, Multiply, Divide, Equal, Inequal, Greater, Lesser, EqGreater, EqLesser, Set, While, If, Value, Identifier, None, Root, CodeBlock, CodeBlockStart, CodeBlockEnd, FunctionDef, FunctionCall, Expression, BracketStart, BracketEnd, Puts, Return, InlineGround, Struct, New, In }; enum class SolDataType { diff --git a/tests/struct.sols b/tests/struct.sols index 87874a0..bed033a 100644 --- a/tests/struct.sols +++ b/tests/struct.sols @@ -6,3 +6,6 @@ struct dingus { e = new dingus puts e puts dingus + +puts e.x +puts e.y