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) {
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];
}
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();

View File

@@ -17,8 +17,8 @@ namespace Solstice {
};
enum class Precedence {
Root,
NewLine,
Identifier,
If,
While,
Compare,
@@ -26,10 +26,11 @@ namespace Solstice {
FunctionCall,
Add,
Multiply,
Identifier,
Other,
Root
};
extern std::unordered_map<TokenType, NodeType> tokToNodeType;
class Node {
@@ -57,6 +58,10 @@ namespace Solstice {
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> 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<Node> parseOneNode(Precedence precedence = Precedence::Other);