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;
|
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() {
|
SolNode Parser::parse() {
|
||||||
current = 0;
|
current = 0;
|
||||||
size = tokensToParse.size();
|
size = tokensToParse.size();
|
||||||
@@ -790,17 +878,19 @@ namespace Solstice {
|
|||||||
case SolNodeType::Multiply:
|
case SolNodeType::Multiply:
|
||||||
case SolNodeType::Divide:
|
case SolNodeType::Divide:
|
||||||
{
|
{
|
||||||
SolNode addNode(getNodeType(token));
|
SolNode opNode(getNodeType(token));
|
||||||
addNode.addNode(rootNode.children.back());
|
if (rootNode.children.empty()) {
|
||||||
rootNode.children.pop_back();
|
std::cout << "Expected operand before operator\n";
|
||||||
auto tokenopt = consume();
|
|
||||||
if (tokenopt) {
|
|
||||||
addNode.addNode(parseOneToken(tokenopt));
|
|
||||||
} else {
|
|
||||||
std::cout << "FEED ME MORE TOKENS\n";
|
|
||||||
exit(1);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Equal:
|
case SolNodeType::Equal:
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ namespace Solstice {
|
|||||||
size_t current;
|
size_t current;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
std::optional<std::string> peek(int ahead = 1);
|
std::optional<std::string> peek(int ahead = 0);
|
||||||
std::optional<std::string> consume();
|
std::optional<std::string> consume();
|
||||||
bool isInt(std::string in);
|
bool isInt(std::string in);
|
||||||
bool isDouble(std::string in);
|
bool isDouble(std::string in);
|
||||||
@@ -119,6 +119,10 @@ namespace Solstice {
|
|||||||
SolDataType getDataType(std::string in);
|
SolDataType getDataType(std::string in);
|
||||||
SolNodeType getNodeType(std::string in);
|
SolNodeType getNodeType(std::string in);
|
||||||
|
|
||||||
|
SolNode parsePrimary();
|
||||||
|
SolNode parseExpression(int minPrec);
|
||||||
|
int getPrecedence(std::string token);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Parser(std::vector<std::string> in);
|
Parser(std::vector<std::string> in);
|
||||||
SolNode parse();
|
SolNode parse();
|
||||||
|
|||||||
Reference in New Issue
Block a user