From bba1be30d7544a27ca8c1b0106d143661a362fac Mon Sep 17 00:00:00 2001 From: Blendi Date: Wed, 29 Apr 2026 13:10:57 +0200 Subject: [PATCH] parser: for loops --- src/main.c | 2 +- src/parser.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/parser.h | 2 + 3 files changed, 126 insertions(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 2a8558a..d00d4a8 100644 --- a/src/main.c +++ b/src/main.c @@ -33,7 +33,7 @@ void print_node(noomP_Node* node, noom_uint_t depth) { int main(int argc, char** argv) { // uhh uhhh uhhhhh - const char* code = "function fact(n) if n == 0 then return 1 end return n*fact(n-1) end"; + const char* code = "for k,v,a,b,c in 8,5,6,3,2,5 do end"; noom_uint_t pos = 0; printf("LEX OUTPUT:\n"); diff --git a/src/parser.c b/src/parser.c index 0c1963d..f14a1ae 100644 --- a/src/parser.c +++ b/src/parser.c @@ -13,6 +13,10 @@ const char *noomP_formatNodeType(noomP_NodeType node_type) { return "if statement"; case NOOMP_NODE_WHILELOOP: return "while loop"; + case NOOMP_NODE_FORLOOP: + return "for loop"; + case NOOMP_NODE_FORLOOPIN: + return "for loop (in)"; case NOOMP_NODE_BLOCK: return "block"; case NOOMP_NODE_ATTRIBUTE: @@ -1107,6 +1111,125 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (!is_done) return 0; //darn it return ret; + } else if (noom_streql(parser->code + token.offset, token.length, "for", 3)) { + // yay... + noomP_skip(parser, &token); + + noomP_Node* forl = noomP_allocNode(parser); + if (forl == 0) return 0; + + forl->type = NOOMP_NODE_FORLOOP; // might be changed to FORLOOPIN later. + forl->source_offset = token.offset; + + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_IDENTIFIER) return 0; + noom_uint_t vname = token.offset; + noomP_skip(parser, &token); + + noomP_Node* name_node = noomP_allocNode(parser); + if (name_node == 0) return 0; + + name_node->type = NOOMP_NODE_VARNAME; + name_node->source_offset = vname; + + noomP_addSubnode(forl, name_node); + + noomP_peek(parser, &token); + + if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, "=", 1)) { + noomP_skip(parser, &token); + + // ehhh i'll do a stupid + noom_uint_t numc = 0; + while (1) { + noomP_Node* expr = noomP_parseExpression(parser); + if (expr == 0) return 0; + + noomP_addSubnode(forl, expr); + numc++; + + noomP_peek(parser, &token); + + if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, ",", 1)) { + noomP_skip(parser, &token); + } else { + break; + } + } + + if (numc < 2 || numc > 3) return 0; // damn :( + } else { + forl->type = NOOMP_NODE_FORLOOPIN; + + if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, ",", 1)) { + noomP_skip(parser, &token); + + while (1) { + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_IDENTIFIER) return 0; + noomP_skip(parser, &token); + + noomP_Node* namemoment = noomP_allocNode(parser); + if (namemoment == 0) return 0; + + namemoment->type = NOOMP_NODE_VARNAME; + namemoment->source_offset = token.offset; + + noomP_addSubnode(forl, namemoment); + + noomP_peek(parser, &token); + + if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, ",", 1)) { + noomP_skip(parser, &token); + } else { + break; + } + } + } + + // okay. that took a while. now for the in and the expressions + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "in", 2)) { + return 0; + } + noomP_skip(parser, &token); + + // exprlist time + while (1) { + noomP_Node* expr = noomP_parseExpression(parser); + if (expr == 0) return 0; + + noomP_addSubnode(forl, expr); + + noomP_peek(parser, &token); + + if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, ",", 1)) { + noomP_skip(parser, &token); + } else { + break; + } + } + } + + // making this the same for all of them: do [block] end + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "do", 2)) { + return 0; + } + noomP_skip(parser, &token); + + noomP_Node* block = noomP_parseBlock(parser); + if (block == 0) return 0; + + noomP_addSubnode(forl, block); + + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { + return 0; + } + noomP_skip(parser, &token); + + return forl; } } diff --git a/src/parser.h b/src/parser.h index f0e0b74..e0a95e7 100644 --- a/src/parser.h +++ b/src/parser.h @@ -9,6 +9,8 @@ typedef enum noomP_NodeType { NOOMP_NODE_LOCALDECLARATION, NOOMP_NODE_IFSTATEMENT, NOOMP_NODE_WHILELOOP, + NOOMP_NODE_FORLOOP, + NOOMP_NODE_FORLOOPIN, NOOMP_NODE_BLOCK, NOOMP_NODE_ATTRIBUTE,