precedence stuff yay!

This commit is contained in:
2026-08-01 18:01:59 +10:00
parent 7df9f25119
commit 1866585af1
2 changed files with 55 additions and 10 deletions

View File

@@ -127,12 +127,13 @@ namespace Solstice {
Node Parser::parseExpr(TT type) { Node Parser::parseExpr(TT type) {
auto left = getPreviousNode(output); auto left = getPreviousNode(output);
if (!left.has_value()) { 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)); Precedence precedence = getTokenPrecedence(Token(type));
auto right = parseOneNode(precedence); auto right = parseOneNode(precedence);
if (!right.has_value()) { 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; NodeType nodeType;
@@ -142,7 +143,19 @@ namespace Solstice {
nodeType = tokToNodeType[type]; 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() { Node Parser::parseLiteral() {
@@ -171,10 +184,36 @@ namespace Solstice {
return Node(*id); 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) { Precedence Parser::getTokenPrecedence(const Token& token) {
static size_t braceCount = 0;
static size_t bracketCount = 0;
static size_t spikyBracketCount = 0;
switch (token.type) { switch (token.type) {
case TT::OpenCurly: { case TT::OpenCurly: {
braceCount++; braceCount++;
@@ -244,7 +283,7 @@ namespace Solstice {
if (!next.has_value()) { if (!next.has_value()) {
return {}; return {};
} }
if (getTokenPrecedence(*next) >= precedence) { if (getTokenPrecedence(*next) <= precedence) {
return {}; return {};
} }
consume(); consume();

View File

@@ -17,8 +17,8 @@ namespace Solstice {
}; };
enum class Precedence { enum class Precedence {
Root,
NewLine, NewLine,
Identifier,
If, If,
While, While,
Compare, Compare,
@@ -26,10 +26,11 @@ namespace Solstice {
FunctionCall, FunctionCall,
Add, Add,
Multiply, Multiply,
Identifier,
Other, Other,
Root
}; };
extern std::unordered_map<TokenType, NodeType> tokToNodeType; extern std::unordered_map<TokenType, NodeType> tokToNodeType;
class Node { class Node {
@@ -57,6 +58,10 @@ namespace Solstice {
size_t current = 0; size_t current = 0;
size_t braceCount = 0;
size_t bracketCount = 0;
size_t spikyBracketCount = 0;
std::optional<Token> peek(int64_t ahead = 0); std::optional<Token> peek(int64_t ahead = 0);
std::optional<Token> consume(); std::optional<Token> consume();
@@ -86,7 +91,8 @@ namespace Solstice {
Node parseLiteral(); Node parseLiteral();
Node parseIdentifier(); Node parseIdentifier();
static Precedence getTokenPrecedence(const Token& token); Precedence getTokenPrecedence(const Token& token);
Precedence getNodePrecedence(const Node& node);
// Returns false when finished // Returns false when finished
std::optional<Node> parseOneNode(Precedence precedence = Precedence::Other); std::optional<Node> parseOneNode(Precedence precedence = Precedence::Other);