#include "parser.hpp" #include #include using TT = Solstice::TokenType; namespace Solstice { std::unordered_map tokToNodeType = { {TT::Math_Add, NodeType::Add}, {TT::Math_Subtract, NodeType::Subtract}, {TT::Math_Multiply, NodeType::Multiply}, {TT::Math_Divide, NodeType::Divide}, {TT::Comparison_Equal, NodeType::Equal}, {TT::Comparison_NotEqual, NodeType::NotEqual}, {TT::Comparison_GreaterThan, NodeType::GreaterThan}, {TT::Comparison_LesserThan, NodeType::LesserThan}, }; std::optional Parser::peek(int64_t ahead) { if (current + ahead >= input.size() || current + ahead < 0) { return {}; } return input[current + ahead]; } std::optional Parser::consume() { if (current >= input.size()) { return {}; } return input[current++]; } std::optional Parser::getPreviousNode(Node& parent) { if (parent.children.empty()) { return {}; } Node node = parent.children[parent.children.size() - 1]; parent.children.pop_back(); return node; } Node Parser::parseExpr(TT type) { auto left = getPreviousNode(output); if (!left.has_value()) { throw std::runtime_error("Expecting expression on left of '+'"); } consume(); // be rid of the + Precedence precedence = getTokenPrecedence(Token(type)); auto right = parseOneNode(precedence); if (!right.has_value()) { throw std::runtime_error("Expecting expression on right of '+'"); } NodeType nodeType; if (tokToNodeType.find(type) == tokToNodeType.end()) { throw std::runtime_error("FIXME couldn't map token type to node type"); } else { nodeType = tokToNodeType[type]; } return Node(nodeType, {*left, *right}); } Node Parser::parseLiteral() { auto current = peek(-1); if (!current.has_value()) { throw std::runtime_error("FIXME couldn't get current token"); } auto literal = current->getLiteral(); if (!literal.has_value()) { throw std::runtime_error("FIXME token with type literal does not hold a literal"); } return Node(*literal); } Node Parser::parseIdentifier() { auto current = peek(-1); if (!current.has_value()) { throw std::runtime_error("FIXME couldn't get current token"); } auto id = current->getIdentifier(); if (!id.has_value()) { throw std::runtime_error("FIXME token with type identifier does not hold an identifier"); } return Node(*id); } 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++; return Precedence::Other; } case TT::CloseCurly: { braceCount--; return Precedence::Other; } case TT::OpenSpiky: { spikyBracketCount++; return Precedence::Other; } case TT::CloseSpiky: { spikyBracketCount--; return Precedence::Other; } case TT::OpenParen: { bracketCount++; return Precedence::Other; } case TT::CloseParen: { bracketCount--; return Precedence::Other; } default: break; } if (braceCount > 0) { return Precedence::Other; } if (bracketCount > 0) { return Precedence::Other; } if (spikyBracketCount > 0) { return Precedence::Other; } switch (token.type) { case TT::None: case TT::Kw_Type: case TT::Hash_CImport: case TT::Hash_Effect: case TT::Action_Function: return Precedence::Other; case TT::Math_Add: case TT::Math_Subtract: return Precedence::Add; case TT::Math_Multiply: case TT::Math_Divide: return Precedence::Multiply; case TT::Assign_Bind: case TT::Assign_Set: case TT::Assign_Type: return Precedence::Set; case TT::NewLine: return Precedence::NewLine; case TT::Identifier: return Precedence::Identifier; case TT::Literal: return Precedence::Identifier; default: return Precedence::Other; } } std::optional Parser::parseOneNode(Precedence precedence) { auto next = peek(); if (!next.has_value()) { return {}; } if (getTokenPrecedence(*next) >= precedence) { return {}; } consume(); switch (next->type) { case TT::None: break; case TT::Identifier: return parseIdentifier(); case TT::Literal: return parseLiteral(); case TT::Math_Add: case TT::Math_Subtract: case TT::Math_Multiply: case TT::Math_Divide: return parseExpr(next->type); } throw std::runtime_error("FIXME: unimplemented parsing case"); } const Node& Parser::parse() { while (auto node = parseOneNode(Precedence::Root)) { output.children.push_back(*node); } return output; } }