Function parsing!

This commit is contained in:
2026-08-01 20:43:16 +10:00
parent 476b401e55
commit 34afdd9642
3 changed files with 112 additions and 3 deletions

View File

@@ -1,9 +1,22 @@
#include "lexer/lexer.hpp" #include "lexer/lexer.hpp"
#include "parser/parser.hpp" #include "parser/parser.hpp"
#include <iostream> #include <iostream>
#include <fstream>
#include <ostream>
#include <sstream>
int main() { int main(int argc, char** argv) {
Solstice::Lexer lexer{"(2 + 2) / 5\n(1, 2, 3)"};
if (argc <= 1) {
std::cout << "Usage: " << argv[0] << " <file.sols>" << std::endl;
return 1;
}
std::ifstream file{argv[1]};
std::stringstream ss;
ss << file.rdbuf();
Solstice::Lexer lexer{ss.str()};
auto lexed = lexer.lex(); auto lexed = lexer.lex();
Solstice::Parser parser{lexed}; Solstice::Parser parser{lexed};

View File

@@ -44,6 +44,8 @@ namespace Solstice {
return "Expression"; return "Expression";
case NodeType::Tuple: case NodeType::Tuple:
return "Tuple"; return "Tuple";
case NodeType::CodeBlock:
return "CodeBlock";
case NodeType::FunctionBind: case NodeType::FunctionBind:
return "FunctionBind"; return "FunctionBind";
case NodeType::Bind: case NodeType::Bind:
@@ -70,8 +72,8 @@ namespace Solstice {
return "GreaterThan"; return "GreaterThan";
case NodeType::LesserThan: case NodeType::LesserThan:
return "LesserThan"; return "LesserThan";
} }
throw std::runtime_error("FIXME Unhandled case in nodeTypeToString");
} }
std::ostream& operator<<(std::ostream& stream, const Node& node) { std::ostream& operator<<(std::ostream& stream, const Node& node) {
@@ -130,6 +132,37 @@ namespace Solstice {
return node; return node;
} }
Node Parser::parseActionFunction() {
Node node{NodeType::FunctionBind};
auto previous = getPreviousNode(*context);
if (!previous.has_value()) {
throw std::runtime_error("expecting function arguments before '->'");
}
// the previous node is either a tuple or expression (for lambda) or a function call (for named function)
if (previous->type == NodeType::FunctionCall) {
node.type = NodeType::FunctionBind;
node.children.push_back(previous->children[0]); // name
node.children.push_back(previous->children[1]); // args
} else if (previous->type == NodeType::Tuple || previous->type == NodeType::Expression) {
node.type = NodeType::Lambda;
previous->type = NodeType::Tuple; // for consistency's sake
node.children.push_back(*previous);
} else {
throw std::runtime_error("expecting function arguments before '->'");
}
// process the body for the function
auto body = parseOneNode(Precedence::Root);
if (!body.has_value()) {
throw std::runtime_error("expecting function body after '->'");
}
node.children.push_back(*body);
return node;
}
Node Parser::parseExpr(TT type) { Node Parser::parseExpr(TT type) {
auto left = getPreviousNode(*context); auto left = getPreviousNode(*context);
if (!left.has_value()) { if (!left.has_value()) {
@@ -215,6 +248,52 @@ namespace Solstice {
return node; return node;
} }
Node Parser::parseOpenCurly() {
Node node{NodeType::CodeBlock};
for (;;) {
while (peek().has_value() && peek()->type == TT::NewLine) {
consume();
}
auto next = peek();
if (!next.has_value()) {
throw std::runtime_error("unclosed curly bracket");
}
if (next->type == TT::CloseCurly) {
consume();
break;
}
Node elem{NodeType::Root};
Node* prevContext = context;
context = &elem;
for (;;) {
auto t = peek();
if (!t.has_value() || t->type == TT::CloseCurly) {
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 code block");
}
node.children.push_back(elem.children.back());
auto sep = peek();
if (!sep.has_value()) {
throw std::runtime_error("unclosed 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()) {
@@ -238,6 +317,17 @@ namespace Solstice {
throw std::runtime_error("FIXME token with type identifier does not hold an identifier"); throw std::runtime_error("FIXME token with type identifier does not hold an identifier");
} }
// Check if it's a function call
auto next = peek();
if (next.has_value() && next->type == TT::OpenParen) {
consume();
Node argsNode = parseOpenParen();
argsNode.type = NodeType::Tuple;
Node callNode = {NodeType::FunctionCall, {*id, argsNode}};
return callNode;
}
return Node(*id); return Node(*id);
} }
@@ -269,6 +359,7 @@ namespace Solstice {
return Precedence::Compare; return Precedence::Compare;
} }
throw std::runtime_error("FIXME unhandled node precedence case");
} }
Precedence Parser::getTokenPrecedence(const Token& token) { Precedence Parser::getTokenPrecedence(const Token& token) {
@@ -322,6 +413,10 @@ namespace Solstice {
return parseExpr(next->type); return parseExpr(next->type);
case TT::OpenParen: case TT::OpenParen:
return parseOpenParen(); return parseOpenParen();
case TT::Action_Function:
return parseActionFunction();
case TT::OpenCurly:
return parseOpenCurly();
case TT::NewLine: case TT::NewLine:
// ignore new line // ignore new line

View File

@@ -10,6 +10,7 @@ namespace Solstice {
enum class NodeType { enum class NodeType {
Root, Literal, Identifier, Expression, Tuple, Root, Literal, Identifier, Expression, Tuple,
CodeBlock,
FunctionBind, Bind, Set, FunctionBind, Bind, Set,
Lambda, FunctionCall, Lambda, FunctionCall,
Add, Subtract, Multiply, Divide, Add, Subtract, Multiply, Divide,