Function parsing!
This commit is contained in:
17
src/main.cpp
17
src/main.cpp
@@ -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};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user