From 67eb3fc5521ead7076ca5f2238b99fec2a3ed631 Mon Sep 17 00:00:00 2001 From: Blendi Date: Thu, 30 Apr 2026 15:22:04 +0200 Subject: [PATCH] parser: things --- src/parser.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++----- src/parser.h | 10 ++ 2 files changed, 268 insertions(+), 23 deletions(-) diff --git a/src/parser.c b/src/parser.c index ed276fb..25a1ff8 100644 --- a/src/parser.c +++ b/src/parser.c @@ -21,6 +21,8 @@ const char *noomP_formatNodeType(noomP_NodeType node_type) { return "repeat loop"; case NOOMP_NODE_BLOCK: return "block"; + case NOOMP_NODE_DOBLOCK: + return "do block"; case NOOMP_NODE_ATTRIBUTE: return "attribute"; case NOOMP_NODE_BREAK: @@ -35,6 +37,10 @@ const char *noomP_formatNodeType(noomP_NodeType node_type) { return "nil literal"; case NOOMP_NODE_STRINGLITERAL: return "string literal"; + case NOOMP_NODE_TABLELITERAL: + return "table literal"; + case NOOMP_NODE_TABLEENTRY: + return "table entry"; case NOOMP_NODE_UNARYOPERATOR: return "unary operator"; case NOOMP_NODE_BINARYOPERATOR: @@ -47,6 +53,14 @@ const char *noomP_formatNodeType(noomP_NodeType node_type) { return "call"; case NOOMP_NODE_METHODCALL: return "method call"; + case NOOMP_NODE_STRINGCALL: + return "string call"; + case NOOMP_NODE_TABLECALL: + return "table call"; + case NOOMP_NODE_STRINGMETHODCALL: + return "string method call"; + case NOOMP_NODE_TABLEMETHODCALL: + return "table method call"; case NOOMP_NODE_LAMBDAFUNCTIONLITERAL: return "lambda function literal"; case NOOMP_NODE_FUNCTIONDECLARATION: @@ -133,6 +147,128 @@ int noomP_addSubnode(noomP_Node* node, noomP_Node* subnode) { return 0; } +noomP_Node* noomP_parseTableLiteral(noomP_Parser* parser) { + noomL_Token token; + + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "{", 1)) { + return 0; + } + noomP_skip(parser, &token); + + noomP_Node* table = noomP_allocNode(parser); + if (table == 0) return 0; + + table->type = NOOMP_NODE_TABLELITERAL; + table->source_offset = token.offset; + + // oh boy, oh boy! + while (1) { + noomP_peek(parser, &token); + + if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, "}", 1)) { + // noomP_skip(parser, &token); + break; + } + + noomP_peek(parser, &token); + + if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, "[", 1)) { + noomP_skip(parser, &token); + noom_uint_t bloc = token.offset; + + noomP_Node* idx = noomP_parseExpression(parser); + if (idx == 0) return 0; + + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "]", 1)) { + return 0; + } + noomP_skip(parser, &token); + + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "=", 1)) { + return 0; + } + noomP_skip(parser, &token); + + noomP_Node* val = noomP_parseExpression(parser); + if (val == 0) return 0; + + noomP_Node* entry = noomP_allocNode(parser); + if (entry == 0) return 0; + + entry->type = NOOMP_NODE_TABLEENTRY; + entry->source_offset = bloc; + + noomP_addSubnode(entry, idx); + noomP_addSubnode(entry, val); + + noomP_addSubnode(table, entry); + } else { + int exprcheck = 1; + if (token.type == NOOML_TOKEN_IDENTIFIER) { // maybe `Name = ...` + noom_uint_t opos = parser->lex_offset; + noomP_skip(parser, &token); + + noomP_peek(parser, &token); + if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, "=", 1)) { + noomP_skip(parser, &token); + + // conveniently opos is also the thingamajig + noomP_Node* val = noomP_parseExpression(parser); + if (val == 0) return 0; + + noomP_Node* idx = noomP_allocNode(parser); + if (idx == 0) return 0; + + idx->type = NOOMP_NODE_FIELDNAME; + idx->source_offset = opos; + + noomP_Node* entry = noomP_allocNode(parser); + if (entry == 0) return 0; + + entry->type = NOOMP_NODE_TABLEENTRY; + entry->source_offset = opos; + + noomP_addSubnode(entry, idx); + noomP_addSubnode(entry, val); + + noomP_addSubnode(table, entry); + exprcheck = 0; + } else { + /// fuuuuuuuu + parser->lex_offset = opos; // evil hack!!1!! + } + } + if (exprcheck) { + noomP_Node* val = noomP_parseExpression(parser); + if (val == 0) return 0; + + // ehhhh this doesn't need an entry; it's not my problem anyway. + // to lex: sorry, not sorry + noomP_addSubnode(table, val); + } + } + + // check for , + 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; + } + } + + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "}", 1)) { + return 0; + } + noomP_skip(parser, &token); + + return table; +} + noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode) { noomP_Node* node = snode; noomL_Token token; @@ -226,6 +362,20 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode noomP_skip(parser, &token); + node = new; + } else if (noom_streql(parser->code + token.offset, token.length, "{", 1)) { // table call + noomP_Node* new = noomP_allocNode(parser); + if (new == 0) return 0; + + new->type = NOOMP_NODE_TABLECALL; + new->source_offset = token.offset; + + noomP_Node* table = noomP_parseTableLiteral(parser); + if (table == 0) return 0; + + noomP_addSubnode(new, node); + noomP_addSubnode(new, table); + node = new; } else if (noom_streql(parser->code + token.offset, token.length, ":", 1)) { // method call noomP_skip(parser, &token); @@ -238,6 +388,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode noomP_Node* new = noomP_allocNode(parser); if (new == 0) return 0; + new->type = 0; new->type = NOOMP_NODE_METHODCALL; new->source_offset = sym_loc; @@ -251,39 +402,71 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode noomP_addSubnode(new, method_node); noomP_peek(parser, &token); - if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, "(", 1))) { - return 0; - } - noomP_skip(parser, &token); - noomP_peek(parser, &token); - if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ")", 1))) { - while (1) { - noomP_Node* expr = noomP_parseExpression(parser); - if (expr == 0) return 0; + if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, "(", 1)) { + noomP_skip(parser, &token); + // new->type = NOOMP_NODE_METHODCALL; - noomP_addSubnode(new, expr); + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ")", 1))) { + while (1) { + noomP_Node* expr = noomP_parseExpression(parser); + if (expr == 0) return 0; - noomP_peek(parser, &token); - if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ",", 1))) { - break; + noomP_addSubnode(new, expr); + + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ",", 1))) { + break; + } + noomP_skip(parser, &token); } - noomP_skip(parser, &token); } + + // check for ) + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ")", 1))) { + return 0; + } + noomP_skip(parser, &token); + } else if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, "{", 1)) { + noomP_Node* table = noomP_parseTableLiteral(parser); + if (table == 0) return 0; + + // new->type = NOOMP_NODE_TABLEMETHODCALL; + + noomP_addSubnode(new, table); + } else if (token.type == NOOML_TOKEN_STRING) { + noomP_skip(parser, &token); + new->type = NOOMP_NODE_STRINGMETHODCALL; + + noomP_Node* str = noomP_allocNode(parser); + if (str == 0) return 0; + str->type = NOOMP_NODE_STRINGLITERAL; + str->source_offset = token.offset; + + noomP_addSubnode(new, str); + } else { + return 0; // unexpected :( } - // check for ) - noomP_peek(parser, &token); - if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ")", 1))) { - return 0; - } - - noomP_skip(parser, &token); node = new; } else { return node; // done } + } else if (token.type == NOOML_TOKEN_STRING) { + noomP_skip(parser, &token); + // string call + noomP_Node* new = noomP_allocNode(parser); + if (new == 0) return 0; + + new->type = NOOMP_NODE_STRINGCALL; + new->source_offset = token.offset; + + noomP_addSubnode(new, node); + + node = new; } else { return node; // done } @@ -409,6 +592,11 @@ noomP_Node* noomP_parseRawExpression(noomP_Parser* parser) { // buttt we're not done YET! it could still go :dsg().dsdh():dsh() return noomP_parseComplexExpression(parser, paren); // thank you for being a function :heart: + } else if (noom_streql(parser->code + token.offset, token.length, "{", 1)) { + noomP_Node* table = noomP_parseTableLiteral(parser); + if (table == 0) return 0; + + return table; } } @@ -434,6 +622,10 @@ int noomP_infixOperatorBP(noomP_Parser* parser, noomL_Token* token, noom_uint_t* *a = 110; *b = 120; return 1; + } else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, "//", 2)) { + *a = 110; + *b = 120; + return 1; } else if (noom_streql(parser->code + token->offset, token->length, "%", 1)) { *a = 110; *b = 120; @@ -449,6 +641,28 @@ int noomP_infixOperatorBP(noomP_Parser* parser, noomL_Token* token, noom_uint_t* *b = 70; // right ass. return 1; + } else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, ">>", 2)) { + *a = 68; + *b = 69; + return 1; + } else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, "<<", 2)) { + *a = 68; + *b = 69; + return 1; + + } else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, "&", 1)) { + *a = 66; + *b = 67; + return 1; + } else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, "~", 1)) { + *a = 64; + *b = 65; + return 1; + } else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, "|", 1)) { + *a = 62; + *b = 63; + return 1; + // oh boy. } else if (noom_streql(parser->code + token->offset, token->length, "<", 1)) { @@ -497,7 +711,7 @@ noom_uint_t noomP_prefixOperatorBP(noomP_Parser* parser, noomL_Token* token) { / return 125; } else if (noom_streql(parser->code + token->offset, token->length, "#", 1)) { return 125; - } else if (noom_streql(parser->code + token->offset, token->length, "~", 1)) { + } else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, "~", 1)) { return 125; } } else if (token->type == NOOML_TOKEN_KEYWORD) { @@ -1285,6 +1499,27 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { noomP_addSubnode(repeat, condition); return repeat; + } else if (noom_streql(parser->code + token.offset, token.length, "do", 2)) { + noomP_skip(parser, &token); + + noomP_Node* doblock = noomP_allocNode(parser); + if (doblock == 0) return 0; + + doblock->type = NOOMP_NODE_DOBLOCK; + doblock->source_offset = token.offset; + + noomP_Node* block = noomP_parseBlock(parser); + if (block == 0) return 0; + + noomP_addSubnode(doblock, 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 doblock; } } else if (token.type == NOOML_TOKEN_SYMBOL) { if (noom_streql(parser->code + token.offset, token.length, "::", 2)) { // symbol doesn't exist on wrong versions @@ -1402,7 +1637,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { } return assignment; - } else if (base->type == NOOMP_NODE_CALL || base->type == NOOMP_NODE_METHODCALL) { + } else if (base->type == NOOMP_NODE_CALL || base->type == NOOMP_NODE_METHODCALL || base->type == NOOMP_NODE_STRINGCALL || base->type == NOOMP_NODE_STRINGMETHODCALL || base->type == NOOMP_NODE_TABLECALL || base->type == NOOMP_NODE_TABLEMETHODCALL) { // this expression is now a statement. return base; // no need to eat any more. } else { diff --git a/src/parser.h b/src/parser.h index d2ead2c..60e04c2 100644 --- a/src/parser.h +++ b/src/parser.h @@ -13,6 +13,7 @@ typedef enum noomP_NodeType { NOOMP_NODE_FORLOOPIN, NOOMP_NODE_REPEAT, NOOMP_NODE_BLOCK, + NOOMP_NODE_DOBLOCK, // maybe just use BLOCK for this? NOOMP_NODE_ATTRIBUTE, @@ -24,6 +25,9 @@ typedef enum noomP_NodeType { NOOMP_NODE_NILLITERAL, NOOMP_NODE_STRINGLITERAL, + NOOMP_NODE_TABLELITERAL, + NOOMP_NODE_TABLEENTRY, + NOOMP_NODE_UNARYOPERATOR, NOOMP_NODE_BINARYOPERATOR, @@ -32,6 +36,12 @@ typedef enum noomP_NodeType { NOOMP_NODE_CALL, NOOMP_NODE_METHODCALL, + NOOMP_NODE_STRINGCALL, + NOOMP_NODE_TABLECALL, + + NOOMP_NODE_STRINGMETHODCALL, + NOOMP_NODE_TABLEMETHODCALL, + NOOMP_NODE_LAMBDAFUNCTIONLITERAL, NOOMP_NODE_FUNCTIONDECLARATION, NOOMP_NODE_LOCALFUNCTIONDECLARATION,