From 1866585af16cd423a8336edd293f10b820ca8ccc Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Sat, 1 Aug 2026 18:01:59 +1000 Subject: [PATCH] precedence stuff yay! --- src/parser/parser.cpp | 53 +++++++++++++++++++++++++++++++++++++------ src/parser/parser.hpp | 12 +++++++--- 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index 49e8725..1fc243c 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -127,12 +127,13 @@ namespace Solstice { Node Parser::parseExpr(TT type) { auto left = getPreviousNode(output); if (!left.has_value()) { - throw std::runtime_error("Expecting expression on left of '+'"); + throw std::runtime_error("Expecting expression on left of expression"); } + Precedence leftPrec = getNodePrecedence(*left); Precedence precedence = getTokenPrecedence(Token(type)); auto right = parseOneNode(precedence); if (!right.has_value()) { - throw std::runtime_error("Expecting expression on right of '+'"); + throw std::runtime_error("Expecting expression on right of expression"); } NodeType nodeType; @@ -142,7 +143,19 @@ namespace Solstice { nodeType = tokToNodeType[type]; } - return Node(nodeType, {*left, *right}); + if (leftPrec >= precedence) { + // enclose the left node inside this node + return Node(nodeType, {*left, *right}); + } else { + // steal the right child of the left node and use it as our left value, + // then enclose ourself inside the left node + auto newLeft = left->children[1]; + Node us{nodeType, {newLeft, *right}}; + + left->children[1] = us; + return *left; + } + } Node Parser::parseLiteral() { @@ -171,10 +184,36 @@ namespace Solstice { return Node(*id); } + Precedence Parser::getNodePrecedence(const Node& node) { + switch (node.type) { + case NodeType::Root: + return Precedence::Root; + case NodeType::Literal: + case NodeType::Identifier: + return Precedence::Identifier; + case NodeType::FunctionBind: + case NodeType::Bind: + case NodeType::Set: + return Precedence::Set; + case NodeType::Lambda: + case NodeType::FunctionCall: + return Precedence::Identifier; + case NodeType::Add: + case NodeType::Subtract: + return Precedence::Add; + case NodeType::Multiply: + case NodeType::Divide: + return Precedence::Multiply; + case NodeType::Equal: + case NodeType::NotEqual: + case NodeType::GreaterThan: + case NodeType::LesserThan: + return Precedence::Compare; + + } + } + Precedence Parser::getTokenPrecedence(const Token& token) { - static size_t braceCount = 0; - static size_t bracketCount = 0; - static size_t spikyBracketCount = 0; switch (token.type) { case TT::OpenCurly: { braceCount++; @@ -244,7 +283,7 @@ namespace Solstice { if (!next.has_value()) { return {}; } - if (getTokenPrecedence(*next) >= precedence) { + if (getTokenPrecedence(*next) <= precedence) { return {}; } consume(); diff --git a/src/parser/parser.hpp b/src/parser/parser.hpp index 55558b9..9782608 100644 --- a/src/parser/parser.hpp +++ b/src/parser/parser.hpp @@ -17,8 +17,8 @@ namespace Solstice { }; enum class Precedence { + Root, NewLine, - Identifier, If, While, Compare, @@ -26,9 +26,10 @@ namespace Solstice { FunctionCall, Add, Multiply, + Identifier, Other, - Root }; + extern std::unordered_map tokToNodeType; @@ -57,6 +58,10 @@ namespace Solstice { size_t current = 0; + size_t braceCount = 0; + size_t bracketCount = 0; + size_t spikyBracketCount = 0; + std::optional peek(int64_t ahead = 0); std::optional consume(); @@ -86,7 +91,8 @@ namespace Solstice { Node parseLiteral(); Node parseIdentifier(); - static Precedence getTokenPrecedence(const Token& token); + Precedence getTokenPrecedence(const Token& token); + Precedence getNodePrecedence(const Node& node); // Returns false when finished std::optional parseOneNode(Precedence precedence = Precedence::Other);