Expressions in brackets

This commit is contained in:
2026-08-01 19:26:41 +10:00
parent 1866585af1
commit ad9254b975
5 changed files with 86 additions and 62 deletions

View File

@@ -24,6 +24,7 @@ namespace Solstice {
{")", TT::CloseParen}, {")", TT::CloseParen},
{"<", TT::OpenSpiky}, {"<", TT::OpenSpiky},
{">", TT::CloseSpiky}, {">", TT::CloseSpiky},
{",", TT::Comma},
{"+", TT::Math_Add}, {"+", TT::Math_Add},
{"-", TT::Math_Subtract}, {"-", TT::Math_Subtract},
@@ -251,6 +252,7 @@ namespace Solstice {
case '+': case '+':
case '*': case '*':
case '/': case '/':
case ',':
{ {
if (!buf.empty()) { if (!buf.empty()) {
output.push_back(processToken(buf)); output.push_back(processToken(buf));

View File

@@ -46,6 +46,7 @@ namespace Solstice {
CloseParen, CloseParen,
OpenSpiky, OpenSpiky,
CloseSpiky, CloseSpiky,
Comma,
NewLine, NewLine,
// other // other

View File

@@ -1,20 +1,14 @@
#include "lexer/lexer.hpp" #include "lexer/lexer.hpp"
#include "parser/parser.hpp" #include "parser/parser.hpp"
#include <iostream> #include <iostream>
#include <stdexcept>
int main() { int main() {
try { Solstice::Lexer lexer{"(2 + 2) / 5"};
Solstice::Lexer lexer{"2 + 2 / 5"}; auto lexed = lexer.lex();
auto lexed = lexer.lex();
Solstice::Parser parser{lexed}; Solstice::Parser parser{lexed};
auto parsed = parser.parse(); auto parsed = parser.parse();
std::cout << parsed << std::endl; std::cout << parsed << std::endl;
} catch (const std::runtime_error& e) {
std::cout << e.what() << std::endl;
return 1;
}
return 0; return 0;
} }

View File

@@ -40,6 +40,10 @@ namespace Solstice {
return "Literal"; return "Literal";
case NodeType::Identifier: case NodeType::Identifier:
return "Identifier"; return "Identifier";
case NodeType::Expression:
return "Expression";
case NodeType::Tuple:
return "Tuple";
case NodeType::FunctionBind: case NodeType::FunctionBind:
return "FunctionBind"; return "FunctionBind";
case NodeType::Bind: case NodeType::Bind:
@@ -115,17 +119,19 @@ namespace Solstice {
return input[current++]; return input[current++];
} }
std::optional<Node> Parser::getPreviousNode(Node& parent) { std::optional<Node> Parser::getPreviousNode(Node& parent, bool popBack) {
if (parent.children.empty()) { if (parent.children.empty()) {
return {}; return {};
} }
Node node = parent.children[parent.children.size() - 1]; Node node = parent.children[parent.children.size() - 1];
parent.children.pop_back(); if (popBack) {
parent.children.pop_back();
}
return node; return node;
} }
Node Parser::parseExpr(TT type) { Node Parser::parseExpr(TT type) {
auto left = getPreviousNode(output); auto left = getPreviousNode(*context);
if (!left.has_value()) { if (!left.has_value()) {
throw std::runtime_error("Expecting expression on left of expression"); 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() { Node Parser::parseLiteral() {
auto current = peek(-1); auto current = peek(-1);
if (!current.has_value()) { if (!current.has_value()) {
@@ -190,14 +247,15 @@ namespace Solstice {
return Precedence::Root; return Precedence::Root;
case NodeType::Literal: case NodeType::Literal:
case NodeType::Identifier: case NodeType::Identifier:
case NodeType::Lambda:
case NodeType::FunctionCall:
case NodeType::Expression:
case NodeType::Tuple:
return Precedence::Identifier; return Precedence::Identifier;
case NodeType::FunctionBind: case NodeType::FunctionBind:
case NodeType::Bind: case NodeType::Bind:
case NodeType::Set: case NodeType::Set:
return Precedence::Set; return Precedence::Set;
case NodeType::Lambda:
case NodeType::FunctionCall:
return Precedence::Identifier;
case NodeType::Add: case NodeType::Add:
case NodeType::Subtract: case NodeType::Subtract:
return Precedence::Add; return Precedence::Add;
@@ -214,42 +272,6 @@ namespace Solstice {
} }
Precedence Parser::getTokenPrecedence(const Token& token) { 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) { switch (token.type) {
case TT::None: case TT::None:
case TT::Kw_Type: case TT::Kw_Type:
@@ -298,6 +320,16 @@ namespace Solstice {
case TT::Math_Multiply: case TT::Math_Multiply:
case TT::Math_Divide: case TT::Math_Divide:
return parseExpr(next->type); 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"); throw std::runtime_error("FIXME: unimplemented parsing case");
} }

View File

@@ -9,7 +9,7 @@
namespace Solstice { namespace Solstice {
enum class NodeType { enum class NodeType {
Root, Literal, Identifier, Root, Literal, Identifier, Expression, Tuple,
FunctionBind, Bind, Set, FunctionBind, Bind, Set,
Lambda, FunctionCall, Lambda, FunctionCall,
Add, Subtract, Multiply, Divide, Add, Subtract, Multiply, Divide,
@@ -58,14 +58,12 @@ namespace Solstice {
size_t current = 0; 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> peek(int64_t ahead = 0);
std::optional<Token> consume(); std::optional<Token> consume();
std::optional<Node> getPreviousNode(Node& parent); std::optional<Node> getPreviousNode(Node& parent, bool popBack = true);
Node* context = &output;
Node parseKwType(); Node parseKwType();
@@ -83,9 +81,6 @@ namespace Solstice {
Node parseOpenCurly(); Node parseOpenCurly();
Node parseOpenParen(); Node parseOpenParen();
Node parseOpenSpiky(); Node parseOpenSpiky();
Node parseCloseCurly();
Node parseCloseParen();
Node parseCloseSpiky();
Node parseNewLine(); Node parseNewLine();
Node parseLiteral(); Node parseLiteral();