From: Thomas Bruce Date: Thu, 20 Feb 2025 05:56:41 +0000 (-0500) Subject: properly parse function calls X-Git-Url: https://git.deglebe.com/non-work/p/w/static/gitweb.css?a=commitdiff_plain;h=a6431d51a8daa891f8e0ee893c32f551025f77b6;p=barec%2Fbarec.git properly parse function calls --- diff --git a/lexer.h b/lexer.h index bfd7d19..4fc77dd 100644 --- a/lexer.h +++ b/lexer.h @@ -28,6 +28,7 @@ typedef enum { TK_LBRACE, // `{` TK_RBRACE, // `}` TK_SEMICOLON, // `;` + TK_COMMA, TK_GT, // `>` TK_EOF, // EOF TK_UNKNOWN // UNKNOWN diff --git a/parser.c b/parser.c index a02250e..0bac1fa 100644 --- a/parser.c +++ b/parser.c @@ -20,7 +20,8 @@ typedef enum { AST_BINARY, // bunary expression AST_NUM, // numeric literal AST_IDENT, // identifier - AST_DECL // variable declaration + AST_DECL, // variable declaration + AST_CALL // function calls } ASTKind; typedef struct ASTNode ASTNode; @@ -35,6 +36,10 @@ struct ASTNode { ASTNode* funcBody; // body block int intValue; // numeric literals char* identName; // identifiers and operator string in binary nodes + ASTNode** args; // array of argument nodes + int argCount; // number of arguments + ASTNode** params; // array of parameter nodes + int paramCount; // number of parameters }; /* utilities for creating new ast nodes */ @@ -136,11 +141,42 @@ static ASTNode* parseFunctionDefinition(void) { char* funcName = strdup(g_currentToken.lexeme); nextToken(); expect(TK_LPAREN); + + /* parse parameter list, if any */ + ASTNode** params = NULL; + int paramCount = 0; + if (g_currentToken.kind != TK_RPAREN) { + while (1) { + expect(TK_INT); + if (g_currentToken.kind != TK_IDENT) { + fprintf(stderr, "Parse err: expected identifier + in parameter list, got '%s'\n", + g_currentToken.lexeme); + exit(1); + } + + ASTNode* param = newASTNode(AST_DECL); + param->identName = strdup(g_currentToken.lexeme); + nextToken(); + + paramCount++; + params = realloc(params, sizeof(ASTNode*) * paramCount); + params[paramCount - 1] = param; + + if (g_currentToken.kind == TK_COMMA) + nextToken(); + else + break; + } + } expect(TK_RPAREN); + ASTNode* body = parseCompoundStatement(); ASTNode* funcNode = newASTNode(AST_FUNCDEF); funcNode->funcName = funcName; funcNode->funcBody = body; + funcNode->params = params; + funcNode->paramCount = paramCount; return funcNode; } @@ -271,6 +307,37 @@ static ASTNode* parseFactor(void) { if (g_currentToken.kind == TK_IDENT) { ASTNode* node = newIdentNode(g_currentToken.lexeme); nextToken(); + + /* check if function call */ + if (g_currentToken.kind == TK_LPAREN) { + nextToken(); + ASTNode** args = NULL; + int argCount = 0; + + if (g_currentToken.kind != TK_RPAREN) { + while (true) { + ASTNode* arg = parseExpression(); + argCount++; + args = realloc(args, sizeof(ASTNode*) + * argCount); + args[argCount - 1] = arg; + if (g_currentToken.kind == TK_COMMA) { + nextToken(); + } else { + break; + } + } + } + expect(TK_RPAREN); + + /* create func call astnode */ + ASTNode* callNode = newASTNode(AST_CALL); + callNode->left = node; + callNode->args = args; + callNode->argCount = argCount; + return callNode; + } + return node; } if (g_currentToken.kind == TK_NUMBER) { @@ -391,6 +458,29 @@ static void printAST(ASTNode* node, int indent) { printIndent(indent); printf("Identifier (%s)\n", node->identName); break; + case AST_DECL: + printIndent(indent); + printf("Decl: %s\n", node->identName); + if (node->left) { + printIndent(indent + 1); + printf("Initializer:\n"); + printAST(node->left, indent + 2); + } + break; + case AST_CALL: + printIndent(indent); + printf("FunctionCall\n"); + printIndent(indent + 1); + printf("Callee:\n"); + printAST(node->left, indent + 2); + if (node->left, indent + 2) { + printIndent(indent + 1); + printf("Arguments:\n"); + for (int i = 0; i < node->argCount; i++) { + printAST(node->args[i], indent + 2); + } + } + break; default: printIndent(indent); printf("Unknown AST node kind\n");