parsing functions and inline functions

and return too
This commit is contained in:
2026-04-28 10:03:06 +10:00
parent bf0f00c2b2
commit 94c8541cb2
7 changed files with 225 additions and 12 deletions

View File

@@ -20,6 +20,8 @@ typedef enum {
AST_IDENTIFIER,
AST_TYPE_NAME,
AST_ARG_DEF,
AST_PROGRAM,
// statements
@@ -31,6 +33,8 @@ typedef enum {
AST_IF_STATEMENT,
AST_BREAK_STATEMENT,
AST_CONTINUE_STATEMENT,
AST_FUNC_DEF_STATEMENT,
AST_RETURN_STATEMENT,
// expressions
AST_INFIX_EXPRESSION
@@ -38,6 +42,10 @@ typedef enum {
// Main ASTNode struct, this can hold the different types of nodes.
typedef struct CometASTNode CometASTNode;
typedef CometASTNode* astNodePtr;
UseList(astNodePtr);
struct CometASTNode {
CometASTNodeType nodeType;
union {
@@ -46,6 +54,8 @@ struct CometASTNode {
struct AST_IDENTIFIER { char* ident; } AST_IDENTIFIER;
struct AST_TYPE_NAME { char* name; } AST_TYPE_NAME;
struct AST_ARG_DEF { CometASTNode* type; CometASTNode* ident; } AST_ARG_DEF;
struct AST_PROGRAM { CometASTNode** statements; size_t numStatements; size_t statementsArraySize; } AST_PROGRAM;
struct AST_INFIX_EXPRESSION { CometASTNode* left; CometASTNode* right; char* op; } AST_INFIX_EXPRESSION;
@@ -54,10 +64,26 @@ struct CometASTNode {
struct AST_ASSIGN_STATEMENT { CometASTNode* ident; CometASTNode* expression; CometASTNode* type; } AST_ASSIGN_STATEMENT;
struct AST_REASSIGN_STATEMENT { CometASTNode* ident; CometASTNode* expression; } AST_REASSIGN_STATEMENT;
struct AST_WHILE_STATEMENT { CometASTNode* expression; CometASTNode* program; } AST_WHILE_STATEMENT;
struct AST_FOR_STATEMENT { CometASTNode* ident; CometASTNode* start; CometASTNode* end; CometASTNode* step; CometASTNode* program; } AST_FOR_STATEMENT;
struct AST_FOR_STATEMENT {
CometASTNode* ident;
CometASTNode* start;
CometASTNode* end;
CometASTNode* step;
CometASTNode* program;
} AST_FOR_STATEMENT;
struct AST_IF_STATEMENT { CometASTNode* expression; CometASTNode* program; } AST_IF_STATEMENT;
struct AST_BREAK_STATEMENT { } AST_BREAK_STATEMENT;
struct AST_CONTINUE_STATEMENT { } AST_CONTINUE_STATEMENT;
struct AST_FUNC_DEF_STATEMENT {
CometASTNode* ident;
CometASTNode* program;
List(astNodePtr) args;
CometASTNode* returnType;
bool isInline;
CometASTNode* inlineExpr;
} AST_FUNC_DEF_STATEMENT;
struct AST_RETURN_STATEMENT { CometASTNode* expression; } AST_RETURN_STATEMENT;
} data;
};

View File

@@ -121,7 +121,13 @@ ResultType(CometToken, charptr) lexerParseWord(CometLexer* lexer) {
buffer = newPtr;
}
lexerConsume(lexer);
char peek = lexer->source[lexer->pos+1];
if (isspace(peek) || !(isalnum(peek) || peek == '_')) {
break;
} else {
lexerConsume(lexer);
}
}
buffer[bufferPos] = 0;
@@ -262,13 +268,21 @@ ResultType(tokenList, charptr) lex(CometLexer* lexer) {
case '\r':
break;
case '=':
ResultType(char, charptr) nextEq = lexerPeek(lexer);
ResultType(char, charptr) next = lexerPeek(lexer);
if (!nextEq.error && nextEq.as.success == '=') {
lexerConsume(lexer);
append(tokens, TOKEN_LITERAL(CT_EQ_EQ, "=="));
} else {
if (next.error) {
append(tokens, TOKEN_LITERAL(CT_EQ, "="));
break;
}
lexerConsume(lexer);
if (next.as.success == '=') {
append(tokens, TOKEN_LITERAL(CT_EQ_EQ, "=="));
} else if (next.as.success == '>') {
append(tokens, TOKEN_LITERAL(CT_INLINE_FUNC_ARROW, "=>"))
} else {
return Error(tokenList, charptr, "Expected '=' or '>' after '='.");
}
break;
@@ -324,12 +338,24 @@ ResultType(tokenList, charptr) lex(CometLexer* lexer) {
case '+': append(tokens, TOKEN_LITERAL(CT_PLUS, "+")); break;
case '-': append(tokens, TOKEN_LITERAL(CT_MINUS, "-")); break;
case '-':
ResultType(char, charptr) arrow = lexerPeek(lexer);
if (!arrow.error && arrow.as.success == '>') {
lexerConsume(lexer);
append(tokens, TOKEN_LITERAL(CT_ARROW, "->"));
} else {
append(tokens, TOKEN_LITERAL(CT_MINUS, "-"));
}
break;
case '*': append(tokens, TOKEN_LITERAL(CT_TIMES, "*")); break;
case '/': append(tokens, TOKEN_LITERAL(CT_DIVIDE, "/")); break;
case '%': append(tokens, TOKEN_LITERAL(CT_MOD, "%")); break;
case '^': append(tokens, TOKEN_LITERAL(CT_POW, "^")); break;
case ',': append(tokens, TOKEN_LITERAL(CT_COMMA, ",")) break;
case '<':
ResultType(char, charptr) ltEq = lexerPeek(lexer);

View File

@@ -1,5 +1,6 @@
#include "lexer.h"
#include "parser.h"
#include "token.h"
#include "util.h"
#include <stdio.h>
@@ -13,7 +14,7 @@ int main() {
printf("lexer error: %s\n", tokens.as.error);
exit(1);
}
ResultType(parserPtr, charptr) parser = newParser(tokens.as.success);
if (parser.error) {
printf("error while creating parser: %s\n", parser.as.error);

View File

@@ -2,6 +2,7 @@
#include "ast.h"
#include "lexer.h"
#include "token.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -255,6 +256,42 @@ void printNode(CometASTNode* node) {
case AST_CONTINUE_STATEMENT:
printf("continue");
break;
case AST_ARG_DEF:
printNode(node->data.AST_ARG_DEF.type);
printf(" ");
printNode(node->data.AST_ARG_DEF.ident);
break;
case AST_FUNC_DEF_STATEMENT:
printf("func ");
printNode(node->data.AST_FUNC_DEF_STATEMENT.ident);
printf("(");
for (size_t i = 0; i < node->data.AST_FUNC_DEF_STATEMENT.args.count; i++) {
CometASTNode* arg = *get(node->data.AST_FUNC_DEF_STATEMENT.args, i);
printNode(arg);
if (i < node->data.AST_FUNC_DEF_STATEMENT.args.count-1)
printf(", ");
}
printf(") -> ");
printNode(node->data.AST_FUNC_DEF_STATEMENT.returnType);
printf(" ");
if (node->data.AST_FUNC_DEF_STATEMENT.isInline) {
printf("=> ");
printNode(node->data.AST_FUNC_DEF_STATEMENT.inlineExpr);
} else {
printf("{\n");
printNode(node->data.AST_FUNC_DEF_STATEMENT.program);
printf(" }");
}
break;
case AST_RETURN_STATEMENT:
printf("return ");
printNode(node->data.AST_RETURN_STATEMENT.expression);
break;
case AST_IF_STATEMENT:
printf("if ");
printNode(node->data.AST_IF_STATEMENT.expression);
@@ -576,6 +613,122 @@ ResultType(astNodePtr, charptr) parseReassignStatement(CometParser* parser) {
return Success(astNodePtr, charptr, stmt);
}
ResultType(astNodePtr, charptr) parseFunctionDefStatement(CometParser* parser) {
// basic format
// func func_name(type arg_name, type2 arg_name2) -> return_type {
// return arg_name + arg_name2
// }
//
// inline body func
// func func_name(type arg_name, type2 arg_name2) => arg_name + arg_name2
ResultType(int, charptr) expectName = expectPeek(parser, CT_IDENT);
if (expectName.error) {
return Error(astNodePtr, charptr, expectName.as.error);
}
CometASTNode* ident = AST_NODE(AST_IDENTIFIER, parser->currentToken->value.literal);
bool isInline = false;
ResultType(int, charptr) expectOpenParen = expectPeek(parser, CT_OPEN_PAREN);
if (expectOpenParen.error) {
return Error(astNodePtr, charptr, expectOpenParen.as.error);
}
// parse args
List(astNodePtr) args = newList(astNodePtr);
while (parser->currentToken->type != CT_CLOSE_PAREN) {
if (parser->peekToken->type == CT_EOF) {
return Error(astNodePtr, charptr, "Function args were not closed!");
} else if (parser->peekToken->type == CT_CLOSE_PAREN) {
parserNextToken(parser);
break;
}
ResultType(int, charptr) expectType = expectPeek(parser, CT_TYPE_NAME);
if (expectType.error) {
return Error(astNodePtr, charptr, expectType.as.error);
}
CometASTNode* type = AST_NODE(AST_TYPE_NAME, parser->currentToken->value.literal);
ResultType(int, charptr) expectArgName = expectPeek(parser, CT_IDENT);
if (expectArgName.error) {
return Error(astNodePtr, charptr, expectArgName.as.error);
}
CometASTNode* argName = AST_NODE(AST_IDENTIFIER, parser->currentToken->value.literal);
append(args, AST_NODE(AST_ARG_DEF, type, argName));
ResultType(int, charptr) expectComma = expectPeek(parser, CT_COMMA);
if (expectComma.error && !peekTokenIs(parser, CT_CLOSE_PAREN)) {
return Error(astNodePtr, charptr, expectComma.as.error);
}
}
ResultType(int, charptr) expectArrow = expectPeek(parser, CT_ARROW);
if (expectArrow.error) {
return Error(astNodePtr, charptr, expectArrow.as.error);
}
ResultType(int, charptr) expectReturnType = expectPeek(parser, CT_TYPE_NAME);
if (expectReturnType.error) {
return Error(astNodePtr, charptr, expectReturnType.as.error);
}
CometASTNode* returnType = AST_NODE(AST_TYPE_NAME, parser->currentToken->value.literal);
isInline = peekTokenIs(parser, CT_INLINE_FUNC_ARROW);
if (!(isInline || peekTokenIs(parser, CT_OPEN_CURLY))) {
return Error(astNodePtr, charptr, "Expected next token to be '{' '=>'.");
}
CometASTNode* block = NULL;
CometASTNode* inlineExpr = NULL;
if (!isInline) {
ResultType(astNodePtr, charptr) blockResult = parseBlockStatement(parser);
if (blockResult.error) {
return blockResult;
}
block = blockResult.as.success;
} else {
parserNextToken(parser); // skip return type
parserNextToken(parser); // skip the arrow
ResultType(astNodePtr, charptr) exprResult = parseExpression(parser, PRECEDENCE_LOWEST);
if (exprResult.error) {
return exprResult;
}
inlineExpr = exprResult.as.success;
}
CometASTNode* stmt = AST_NODE(
AST_FUNC_DEF_STATEMENT,
ident,
block,
args,
returnType,
isInline,
inlineExpr
);
return Success(astNodePtr, charptr, stmt);
}
ResultType(astNodePtr, charptr) parseReturnStatement(CometParser* parser) {
parserNextToken(parser);
ResultType(astNodePtr, charptr) expr = parseExpression(parser, PRECEDENCE_LOWEST);
if (expr.error) {
return expr;
}
return Success(astNodePtr, charptr, AST_NODE(AST_RETURN_STATEMENT, expr.as.success));
}
ResultType(astNodePtr, charptr) parseKeyword(CometParser* parser) {
char* keyword = parser->currentToken->value.literal;
@@ -589,6 +742,10 @@ ResultType(astNodePtr, charptr) parseKeyword(CometParser* parser) {
return parseBreakStatement(parser);
} else if (strcmp(keyword, "continue") == 0) {
return parseContinueStatement(parser);
} else if (strcmp(keyword, "func") == 0) {
return parseFunctionDefStatement(parser);
} else if (strcmp(keyword, "return") == 0) {
return parseReturnStatement(parser);
} else {
char* buffer = malloc(256);
sprintf(buffer, "No parse method for keyword \"%s\"", keyword);

View File

@@ -21,7 +21,6 @@ typedef struct {
} CometParser;
typedef CometParser* parserPtr;
typedef CometASTNode* astNodePtr;
Result(astNodePtr, charptr);

View File

@@ -58,6 +58,10 @@ char* tokenTypeToCStr(CometTokenType tokType) {
return "CT_POW";
case CT_EOF:
return "CT_EOF";
case CT_ARROW:
return "CT_ARROW";
case CT_INLINE_FUNC_ARROW:
return "CT_INLINE_FUNC_ARROW";
default:
return "FIXME";

View File

@@ -18,8 +18,8 @@ typedef enum {
CT_COLON,
CT_EQ,
CT_PLUS, CT_MINUS, CT_DIVIDE, CT_TIMES, CT_MOD, CT_POW,
CT_DOT, CT_DOT_DOT, CT_ARROW,
CT_OPEN_CURLY, CT_CLOSE_CURLY, CT_OPEN_PAREN, CT_CLOSE_PAREN,
CT_DOT, CT_DOT_DOT, CT_ARROW, CT_INLINE_FUNC_ARROW,
CT_OPEN_CURLY, CT_CLOSE_CURLY, CT_OPEN_PAREN, CT_CLOSE_PAREN, CT_COMMA,
// other
CT_COMMENT, CT_END_LABEL, CT_EOF