Skip to content

Commit 89ba3ed

Browse files
authored
Merge pull request #30 from sQeeZ-scripting-language/29-callback-functions
29 callback functions
2 parents 67a33eb + 12c16a6 commit 89ba3ed

File tree

3 files changed

+86
-3
lines changed

3 files changed

+86
-3
lines changed

include/parser/ast_nodes.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ enum class NodeType {
2525
// EXPRESSIONS
2626
AssignmentExpr,
2727
CompoundAssignmentExpr,
28+
CallbackFunctionExpr,
2829
TernaryExpr,
2930
BinaryExpr,
3031
UnaryExpr,
@@ -433,6 +434,37 @@ class CompoundAssignmentExpr : public Expr {
433434
}
434435
};
435436

437+
class CallbackFunctionExpr : public Expr {
438+
public:
439+
std::vector<Token> parameters;
440+
std::vector<std::unique_ptr<Stmt>> body;
441+
442+
CallbackFunctionExpr(std::vector<Token> parameters, std::vector<std::unique_ptr<Stmt>> body)
443+
: Expr(NodeType::CallbackFunctionExpr), parameters(std::move(parameters)), body(std::move(body)) {}
444+
445+
CallbackFunctionExpr(const CallbackFunctionExpr&) = delete;
446+
CallbackFunctionExpr& operator=(const CallbackFunctionExpr&) = delete;
447+
CallbackFunctionExpr(CallbackFunctionExpr&&) noexcept = default;
448+
CallbackFunctionExpr& operator=(CallbackFunctionExpr&&) noexcept = default;
449+
450+
std::string toString() const override {
451+
std::ostringstream oss;
452+
oss << "CallbackFunctionExpr: (";
453+
for (size_t i = 0; i < parameters.size(); ++i) {
454+
oss << parameters[i].value;
455+
if (i < parameters.size() - 1) {
456+
oss << ", ";
457+
}
458+
}
459+
oss << ") {\n";
460+
for (const auto& stmt : body) {
461+
oss << " " << stmt->toString() << "\n";
462+
}
463+
oss << "}";
464+
return oss.str();
465+
}
466+
};
467+
436468
class TernaryExpr : public Expr {
437469
public:
438470
std::unique_ptr<Expr> condition;

include/parser/parser.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class Parser {
4040
std::unique_ptr<Expr> parsePipeExpr();
4141
std::unique_ptr<Expr> parseObjectExpr();
4242
std::unique_ptr<Expr> parseArrayExpr();
43+
std::unique_ptr<Expr> parseCallbackFunctionExpr();
4344
std::unique_ptr<Expr> parseShortData();
4445
std::unique_ptr<Expr> parseAdditiveExpr();
4546
std::unique_ptr<Expr> parseMultiplicativeExpr();
@@ -55,6 +56,7 @@ class Parser {
5556
// Utility functions
5657
bool isEOF();
5758
Token peek(int steps = 1);
59+
Token lookAhead(int steps);
5860
Token advance();
5961
Token assertToken(const std::string& expected, const std::string& errorMessage);
6062
void log(const std::unique_ptr<Program>& program, bool devMode);

src/parser/parser.cpp

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,28 @@ std::unique_ptr<Expr> Parser::parseArrayExpr() {
405405
return std::make_unique<ArrayLiteral>(std::move(elements));
406406
}
407407

408+
std::unique_ptr<Expr> Parser::parseCallbackFunctionExpr() {
409+
std::vector<Token> params;
410+
while (!(peek().tag == Token::TypeTag::SYNTAX && peek().type.syntaxToken == SyntaxToken::CLOSE_PARENTHESIS)) {
411+
if (params.size() > 0) {
412+
assertToken("SyntaxToken::COMMA", "Expected comma between callback function parameters.");
413+
}
414+
params.push_back(assertToken("DataToken::IDENTIFIER", "Expected identifier in callback function parameters."));
415+
}
416+
assertToken("SyntaxToken::CLOSE_PARENTHESIS", "Expected closing parenthesis after callback function parameters.");
417+
assertToken("SyntaxToken::CALLBACK", "Expected '=>' to start callback function body.");
418+
std::vector<std::unique_ptr<Stmt>> body = {};
419+
if (peek().tag == Token::TypeTag::SYNTAX && peek().type.syntaxToken == SyntaxToken::OPEN_BRACE) {
420+
assertToken("SyntaxToken::OPEN_BRACE", "Expected '{' to start callback function body.");
421+
body = parseStatementBlock();
422+
} else {
423+
body.push_back(parseStatement());
424+
skipSemicolon();
425+
}
426+
skipSemicolon();
427+
return std::make_unique<CallbackFunctionExpr>(std::move(params), std::move(body));
428+
}
429+
408430
std::unique_ptr<Expr> Parser::parseShortData() {
409431
assertToken("SyntaxToken::AT", "Expected '@' to start short data notation.");
410432
// Short Notation -> Object @ key:value, key:value
@@ -598,12 +620,31 @@ std::unique_ptr<Expr> Parser::parsePrimaryExpr() {
598620
} else if (token.tag == Token::TypeTag::SYNTAX) {
599621
std::unique_ptr<Expr> expression;
600622
std::string value;
623+
int i, scope = 0;
601624
switch (token.type.syntaxToken) {
602625
case SyntaxToken::OPEN_PARENTHESIS:
603626
assertToken("SyntaxToken::OPEN_PARENTHESIS", "Expected '(' to start parenthesised expression.");
604-
expression = parseExpression();
605-
assertToken("SyntaxToken::CLOSE_PARENTHESIS",
606-
"Unexpected token found inside parenthesised expression. Expected closing parenthesis.");
627+
while (true) {
628+
i++;
629+
if (lookAhead(i).tag == Token::TypeTag::SYNTAX &&
630+
lookAhead(i).type.syntaxToken == SyntaxToken::OPEN_PARENTHESIS) {
631+
scope++;
632+
} else if (lookAhead(i).tag == Token::TypeTag::SYNTAX &&
633+
lookAhead(i).type.syntaxToken == SyntaxToken::CLOSE_PARENTHESIS) {
634+
if (scope == 0) {
635+
break;
636+
}
637+
scope--;
638+
}
639+
}
640+
if (lookAhead(i + 1).tag == Token::TypeTag::SYNTAX &&
641+
lookAhead(i + 1).type.syntaxToken == SyntaxToken::CALLBACK) {
642+
expression = parseCallbackFunctionExpr();
643+
} else {
644+
expression = parseExpression();
645+
assertToken("SyntaxToken::CLOSE_PARENTHESIS",
646+
"Unexpected token found inside parenthesised expression. Expected closing parenthesis.");
647+
}
607648
return expression;
608649
case SyntaxToken::DOUBLE_QUOTE:
609650
assertToken("SyntaxToken::DOUBLE_QUOTE", "Expected opening double quote");
@@ -731,6 +772,14 @@ Token Parser::peek(int steps) {
731772
}
732773
}
733774

775+
Token Parser::lookAhead(int steps) {
776+
if (tokens.size() < steps) {
777+
throw std::runtime_error("Unexpected end of file");
778+
} else {
779+
return tokens[steps - 1];
780+
}
781+
}
782+
734783
Token Parser::advance() {
735784
Token token = tokens.front();
736785
tokens.erase(tokens.begin());

0 commit comments

Comments
 (0)