diff --git a/src/lexer/lexer.cpp b/src/lexer/lexer.cpp index eab5ee5..4690f58 100644 --- a/src/lexer/lexer.cpp +++ b/src/lexer/lexer.cpp @@ -24,6 +24,7 @@ namespace Solstice { {")", TT::CloseParen}, {"<", TT::OpenSpiky}, {">", TT::CloseSpiky}, + {",", TT::Comma}, {"+", TT::Math_Add}, {"-", TT::Math_Subtract}, @@ -251,6 +252,7 @@ namespace Solstice { case '+': case '*': case '/': + case ',': { if (!buf.empty()) { output.push_back(processToken(buf)); diff --git a/src/lexer/lexer.hpp b/src/lexer/lexer.hpp index 21bfe70..7b34013 100644 --- a/src/lexer/lexer.hpp +++ b/src/lexer/lexer.hpp @@ -46,6 +46,7 @@ namespace Solstice { CloseParen, OpenSpiky, CloseSpiky, + Comma, NewLine, // other diff --git a/src/main.cpp b/src/main.cpp index 00cb3b9..39df4d4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,20 +1,14 @@ #include "lexer/lexer.hpp" #include "parser/parser.hpp" #include -#include int main() { - try { - Solstice::Lexer lexer{"2 + 2 / 5"}; - auto lexed = lexer.lex(); + Solstice::Lexer lexer{"(2 + 2) / 5"}; + auto lexed = lexer.lex(); - Solstice::Parser parser{lexed}; - auto parsed = parser.parse(); - std::cout << parsed << std::endl; + Solstice::Parser parser{lexed}; + auto parsed = parser.parse(); + std::cout << parsed << std::endl; - } catch (const std::runtime_error& e) { - std::cout << e.what() << std::endl; - return 1; - } return 0; } diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index 1fc243c..6bbfa5f 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -40,6 +40,10 @@ namespace Solstice { return "Literal"; case NodeType::Identifier: return "Identifier"; + case NodeType::Expression: + return "Expression"; + case NodeType::Tuple: + return "Tuple"; case NodeType::FunctionBind: return "FunctionBind"; case NodeType::Bind: @@ -115,17 +119,19 @@ namespace Solstice { return input[current++]; } - std::optional Parser::getPreviousNode(Node& parent) { + std::optional Parser::getPreviousNode(Node& parent, bool popBack) { if (parent.children.empty()) { return {}; } Node node = parent.children[parent.children.size() - 1]; - parent.children.pop_back(); + if (popBack) { + parent.children.pop_back(); + } return node; } Node Parser::parseExpr(TT type) { - auto left = getPreviousNode(output); + auto left = getPreviousNode(*context); if (!left.has_value()) { throw std::runtime_error("Expecting expression on left of expression"); } @@ -158,6 +164,57 @@ namespace Solstice { } + Node Parser::parseOpenParen() { + Node node{NodeType::Expression}; + + for (;;) { + auto next = peek(); + if (!next.has_value()) { + throw std::runtime_error("unclosed parens"); + } + if (next->type == TT::CloseParen) { + consume(); + if (node.children.size() != 1) { + node.type = NodeType::Tuple; + } + break; + } + + Node elem{NodeType::Root}; + Node* prevContext = context; + context = &elem; + + for (;;) { + auto t = peek(); + if (!t.has_value() || t->type == TT::CloseParen || t->type == TT::Comma) { + break; + } + auto n = parseOneNode(Precedence::NewLine); + if (!n.has_value()) break; + elem.children.push_back(*n); + } + + context = prevContext; + + if (elem.children.empty()) { + throw std::runtime_error("expecting expression in parens"); + } + node.children.push_back(elem.children.back()); + + auto sep = peek(); + if (!sep.has_value()) { + throw std::runtime_error("unclosed parens"); + } + if (sep->type == TT::Comma) { + consume(); + } else if (sep->type != TT::CloseParen) { + throw std::runtime_error("expecting comma between expressions in parens"); + } + } + + return node; + } + Node Parser::parseLiteral() { auto current = peek(-1); if (!current.has_value()) { @@ -190,14 +247,15 @@ namespace Solstice { return Precedence::Root; case NodeType::Literal: case NodeType::Identifier: + case NodeType::Lambda: + case NodeType::FunctionCall: + case NodeType::Expression: + case NodeType::Tuple: 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; @@ -214,42 +272,6 @@ namespace Solstice { } Precedence Parser::getTokenPrecedence(const Token& token) { - 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: @@ -298,6 +320,16 @@ namespace Solstice { case TT::Math_Multiply: case TT::Math_Divide: return parseExpr(next->type); + case TT::OpenParen: + return parseOpenParen(); + + // stuff that causes errors + case TT::CloseParen: + throw std::runtime_error("Extra closing paren"); + case TT::CloseSpiky: + throw std::runtime_error("Extra closing angle bracket"); + case TT::CloseCurly: + throw std::runtime_error("Extra closing curly brace"); } throw std::runtime_error("FIXME: unimplemented parsing case"); } diff --git a/src/parser/parser.hpp b/src/parser/parser.hpp index 9782608..d392041 100644 --- a/src/parser/parser.hpp +++ b/src/parser/parser.hpp @@ -9,7 +9,7 @@ namespace Solstice { enum class NodeType { - Root, Literal, Identifier, + Root, Literal, Identifier, Expression, Tuple, FunctionBind, Bind, Set, Lambda, FunctionCall, Add, Subtract, Multiply, Divide, @@ -58,14 +58,12 @@ namespace Solstice { size_t current = 0; - size_t braceCount = 0; - size_t bracketCount = 0; - size_t spikyBracketCount = 0; - std::optional peek(int64_t ahead = 0); std::optional consume(); - std::optional getPreviousNode(Node& parent); + std::optional getPreviousNode(Node& parent, bool popBack = true); + + Node* context = &output; Node parseKwType(); @@ -83,9 +81,6 @@ namespace Solstice { Node parseOpenCurly(); Node parseOpenParen(); Node parseOpenSpiky(); - Node parseCloseCurly(); - Node parseCloseParen(); - Node parseCloseSpiky(); Node parseNewLine(); Node parseLiteral();