From b260b49b62d0dae38312d4a91b886618d8046e22 Mon Sep 17 00:00:00 2001 From: Blendi Date: Thu, 16 Apr 2026 11:53:26 +0200 Subject: [PATCH] elseif, else --- src/main.c | 2 +- src/parser.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/main.c b/src/main.c index a3e2126..1cffbb6 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 = "if false or true then local a = 5 end"; + const char* code = "if false or true then elseif true or false then else end"; noom_uint_t pos = 0; printf("LEX OUTPUT:\n"); diff --git a/src/parser.c b/src/parser.c index d8a8cc8..39c447f 100644 --- a/src/parser.c +++ b/src/parser.c @@ -284,8 +284,8 @@ noomP_Node* noomP_parseExpression(noomP_Parser* parser) { return noomP_parseOperatorExpression(parser, 0, 0); } -noomP_Node* noomP_parseBlock(noomP_Parser* parser) { // todo: maybe specify the ending keyword? how do we end on elseif, else? - // block starter has been eaten already; we just go until end +noomP_Node* noomP_parseBlock(noomP_Parser* parser) { // stops on end, else or elseif. + // block starter has been eaten already; we just go until ending keyword noomP_Node* node = noomP_allocNode(parser); if (node == 0) return 0; // OOM :( @@ -300,8 +300,10 @@ noomP_Node* noomP_parseBlock(noomP_Parser* parser) { // todo: maybe specify the if (token.type == NOOML_TOKEN_KEYWORD) { if (noom_streql(parser->code + token.offset, token.length, "end", 3)) { - // it's so joever - noomP_skip(parser, &token); + break; + } else if (noom_streql(parser->code + token.offset, token.length, "elseif", 6)) { + break; + } else if (noom_streql(parser->code + token.offset, token.length, "else", 4)) { break; } } @@ -402,11 +404,60 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { noomP_skip(parser, &token); - noomP_Node* block = noomP_parseBlock(parser); // TODO: elseif, else + noomP_Node* block = noomP_parseBlock(parser); if (block == 0) return 0; noomP_addSubnode(ifStatement, block); + while (1) { // else, elseif + noomP_peek(parser, &token); + + if (token.type != NOOML_TOKEN_KEYWORD) return 0; // unexpected + + if (noom_streql(parser->code + token.offset, token.length, "elseif", 6)) { + noomP_skip(parser, &token); + noomP_Node* elseIfCondition = noomP_parseExpression(parser); + if (elseIfCondition == 0) return 0; + + noomP_addSubnode(ifStatement, elseIfCondition); + + // now we need to check for "then" + noomP_peek(parser, &token); + + if (token.type != NOOML_TOKEN_KEYWORD) return 0; // unexpected + if (!noom_streql(parser->code + token.offset, token.length, "then", 4)) return 0; // unexpected + noomP_skip(parser, &token); + + // now the block + noomP_Node* elseIfBlock = noomP_parseBlock(parser); + if (elseIfBlock == 0) return 0; + + noomP_addSubnode(ifStatement, elseIfBlock); + + // could be even more + } else if (noom_streql(parser->code + token.offset, token.length, "else", 4)) { + noomP_skip(parser, &token); + + noomP_Node* elseBlock = noomP_parseBlock(parser); + if (elseBlock == 0) return 0; + + // we know it's an else if it's an odd number. no need to do anything special. + noomP_addSubnode(ifStatement, elseBlock); + + break; // this must be the last one; end is handled after the loop + } else if (noom_streql(parser->code + token.offset, token.length, "end", 3)) { + break; // will check for end outside the loop because else and things + } else { + // unexpected + return 0; + } + } + + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_KEYWORD) return 0; // unexpected + if (!noom_streql(parser->code + token.offset, token.length, "end", 3)) return 0; // unexpected + noomP_skip(parser, &token); + return ifStatement; } }