forked from solstice/solstice
Operator precedence I think
This commit is contained in:
108
src/parser.cpp
108
src/parser.cpp
@@ -743,6 +743,94 @@ namespace Solstice {
|
||||
return SolNodeType::Identifier;
|
||||
}
|
||||
|
||||
int Parser::getPrecedence(std::string token) {
|
||||
if (token == "*" || token == "/") return 2;
|
||||
if (token == "+" || token == "-") return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SolNode Parser::parsePrimary() {
|
||||
auto tokenopt = consume();
|
||||
if (!tokenopt) {
|
||||
std::cout << "Unexpected end of input\n";
|
||||
exit(1);
|
||||
}
|
||||
std::string token = tokenopt.value();
|
||||
SolNodeType type = getNodeType(token);
|
||||
|
||||
if (type == SolNodeType::Value) {
|
||||
SolNode node(SolNodeType::Value);
|
||||
switch (getDataType(token)) {
|
||||
case SolDataType::Int: node.setValue((int64_t) std::stoll(token)); break;
|
||||
case SolDataType::Double: node.setValue(std::stod(token)); break;
|
||||
case SolDataType::String: node.setValue(token.substr(1, token.size() - 2)); break;
|
||||
case SolDataType::Char: node.setValue(token[1]); break;
|
||||
case SolDataType::Bool: node.setValue(token == "true"); break;
|
||||
default: break;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
if (type == SolNodeType::Identifier) {
|
||||
SolNode idNode(SolNodeType::Identifier);
|
||||
idNode.outputId = token;
|
||||
if (peek().value_or("") == "(") {
|
||||
consume(); // (
|
||||
SolNode fnCallNode(SolNodeType::FunctionCall);
|
||||
fnCallNode.addNode(idNode);
|
||||
|
||||
std::vector<std::string> tokens;
|
||||
size_t brackets = 1;
|
||||
while (auto t = consume()) {
|
||||
if (t.value() == "(") brackets++;
|
||||
if (t.value() == ")") brackets--;
|
||||
if (brackets == 0) break;
|
||||
tokens.push_back(t.value());
|
||||
}
|
||||
auto args = Parser(tokens).parse();
|
||||
for(auto& child : args.children) fnCallNode.addNode(child);
|
||||
return fnCallNode;
|
||||
}
|
||||
return idNode;
|
||||
}
|
||||
|
||||
if (type == SolNodeType::BracketStart) {
|
||||
std::vector<std::string> tokens;
|
||||
size_t brackets = 1;
|
||||
while (auto t = consume()) {
|
||||
if (t.value() == "(") brackets++;
|
||||
if (t.value() == ")") brackets--;
|
||||
if (brackets == 0) break;
|
||||
tokens.push_back(t.value());
|
||||
}
|
||||
auto inner = Parser(tokens).parse();
|
||||
if (inner.children.size() > 0) return inner.children[0];
|
||||
return SolNode(SolNodeType::None);
|
||||
}
|
||||
|
||||
std::cout << "Unexpected token in expression: " << token << "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SolNode Parser::parseExpression(int minPrec) {
|
||||
SolNode lhs = parsePrimary();
|
||||
while(true) {
|
||||
auto opOpt = peek();
|
||||
if (!opOpt) break;
|
||||
std::string op = opOpt.value();
|
||||
int prec = getPrecedence(op);
|
||||
if (prec < minPrec) break;
|
||||
|
||||
consume();
|
||||
SolNode rhs = parseExpression(prec + 1);
|
||||
SolNode newNode(getNodeType(op));
|
||||
newNode.addNode(lhs);
|
||||
newNode.addNode(rhs);
|
||||
lhs = newNode;
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
SolNode Parser::parse() {
|
||||
current = 0;
|
||||
size = tokensToParse.size();
|
||||
@@ -790,17 +878,19 @@ namespace Solstice {
|
||||
case SolNodeType::Multiply:
|
||||
case SolNodeType::Divide:
|
||||
{
|
||||
SolNode addNode(getNodeType(token));
|
||||
addNode.addNode(rootNode.children.back());
|
||||
rootNode.children.pop_back();
|
||||
auto tokenopt = consume();
|
||||
if (tokenopt) {
|
||||
addNode.addNode(parseOneToken(tokenopt));
|
||||
} else {
|
||||
std::cout << "FEED ME MORE TOKENS\n";
|
||||
SolNode opNode(getNodeType(token));
|
||||
if (rootNode.children.empty()) {
|
||||
std::cout << "Expected operand before operator\n";
|
||||
exit(1);
|
||||
}
|
||||
rootNode.addNode(addNode);
|
||||
opNode.addNode(rootNode.children.back());
|
||||
rootNode.children.pop_back();
|
||||
|
||||
// Parse RHS with higher precedence
|
||||
SolNode rhs = parseExpression(getPrecedence(token) + 1);
|
||||
opNode.addNode(rhs);
|
||||
|
||||
rootNode.addNode(opNode);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Equal:
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Solstice {
|
||||
size_t current;
|
||||
size_t size;
|
||||
|
||||
std::optional<std::string> peek(int ahead = 1);
|
||||
std::optional<std::string> peek(int ahead = 0);
|
||||
std::optional<std::string> consume();
|
||||
bool isInt(std::string in);
|
||||
bool isDouble(std::string in);
|
||||
@@ -119,6 +119,10 @@ namespace Solstice {
|
||||
SolDataType getDataType(std::string in);
|
||||
SolNodeType getNodeType(std::string in);
|
||||
|
||||
SolNode parsePrimary();
|
||||
SolNode parseExpression(int minPrec);
|
||||
int getPrecedence(std::string token);
|
||||
|
||||
public:
|
||||
Parser(std::vector<std::string> in);
|
||||
SolNode parse();
|
||||
|
||||
Reference in New Issue
Block a user