precedence stuff yay!
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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<TokenType, NodeType> 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<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);
|
||||
|
||||
Reference in New Issue
Block a user