From cdb90d236de55961c773c3e18fbfaaa545ebf627 Mon Sep 17 00:00:00 2001 From: tema5002 Date: Sat, 23 May 2026 21:47:49 +0300 Subject: [PATCH 1/5] update build.lua again --- .gitignore | 1 + build.lua | 39 ++++++++++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 5 deletions(-) mode change 100644 => 100755 build.lua diff --git a/.gitignore b/.gitignore index 89df9c7..bccf78e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /build /.zig-cache /zig-out +.idea noom noom.* \ No newline at end of file diff --git a/build.lua b/build.lua old mode 100644 new mode 100755 index 46fb84a..db22649 --- a/build.lua +++ b/build.lua @@ -1,4 +1,6 @@ +#!/usr/bin/env lua -- i love build scripts i love build scripts i love build scripts scripts build love i script build love me i love script build i script love build +local args = {...} local isBlendi = os.getenv("USER") == "blendi" local separator = package.config:sub(1,1) @@ -28,10 +30,33 @@ local function fixPath(path) return new end +if args[1] == "clean" then + if separator == '\\' then + runCommand("rmdir /s /q build 2>nul") + else + runCommand("rm -r build") + end + return +end + +local needsDir = false + if separator == '\\' then - runCommand('mkdir build 2>nul') + needsDir = true else - runCommand('mkdir -p build') + -- My favorite coreutil is /usr/bin/[ + local handle = io.popen('[ -d "build" ] && echo 1') + local result = handle:read("*a") + handle:close() + needsDir = result:match("1") ~= nil +end + +if not needsDir then + if separator == '\\' then + runCommand('mkdir build 2>nul') + else + runCommand('mkdir -p build') + end end local files = { @@ -73,14 +98,18 @@ for i = 1,#files do if needsRebuild(fname, out) then needsLinking = true - runCommand('clang -c -g -o ' .. out .. ' ' .. fname .. ' ' .. table.concat(coolArgs, ' ')) + runCommand('clang -c -o ' .. out .. ' ' .. fname .. ' ' .. table.concat(coolArgs, ' ')) end objects[#objects+1] = out; end -local exe = separator == '\\' and "noom.exe" or "noom" +local exe = separator == '\\' and ".\\noom.exe" or "./noom" if needsLinking then - runCommand('clang -g -o ' .. exe .. ' ' .. table.concat(objects, ' ') .. ' ' .. table.concat(coolArgs, ' ')) + runCommand('clang -o ' .. exe .. ' ' .. table.concat(objects, ' ') .. ' ' .. table.concat(coolArgs, ' ')) +end + +if args[1] == "run" then + runCommand(exe) end -- 2.49.1 From 19e8e1356b33b2f371dea34f5562b6607d1fab8d Mon Sep 17 00:00:00 2001 From: tema5002 Date: Sat, 23 May 2026 21:58:22 +0300 Subject: [PATCH 2/5] I made a great mistake --- build.lua | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/build.lua b/build.lua index db22649..d1aff88 100755 --- a/build.lua +++ b/build.lua @@ -1,7 +1,5 @@ #!/usr/bin/env lua -- i love build scripts i love build scripts i love build scripts scripts build love i script build love me i love script build i script love build -local args = {...} - local isBlendi = os.getenv("USER") == "blendi" local separator = package.config:sub(1,1) @@ -30,7 +28,7 @@ local function fixPath(path) return new end -if args[1] == "clean" then +if arg[1] == "clean" then if separator == '\\' then runCommand("rmdir /s /q build 2>nul") else @@ -98,7 +96,7 @@ for i = 1,#files do if needsRebuild(fname, out) then needsLinking = true - runCommand('clang -c -o ' .. out .. ' ' .. fname .. ' ' .. table.concat(coolArgs, ' ')) + runCommand('clang -g -c -o ' .. out .. ' ' .. fname .. ' ' .. table.concat(coolArgs, ' ')) end objects[#objects+1] = out; @@ -107,9 +105,9 @@ end local exe = separator == '\\' and ".\\noom.exe" or "./noom" if needsLinking then - runCommand('clang -o ' .. exe .. ' ' .. table.concat(objects, ' ') .. ' ' .. table.concat(coolArgs, ' ')) + runCommand('clang -g -o ' .. exe .. ' ' .. table.concat(objects, ' ') .. ' ' .. table.concat(coolArgs, ' ')) end -if args[1] == "run" then +if arg[1] == "run" then runCommand(exe) end -- 2.49.1 From a3c2ddbf9e729dc2b7faceabc30ffb5b83da19ea Mon Sep 17 00:00:00 2001 From: tema5002 Date: Sun, 24 May 2026 12:46:01 +0300 Subject: [PATCH 3/5] implement proper error handling --- .gitignore | 3 +- build.lua | 6 ++- src/error.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/error.h | 5 ++ src/helper.c | 29 ++++++++++ src/helper.h | 2 + src/main.c | 66 ++++++++++++++++++----- src/parser.c | 90 ++++++++++++++++--------------- src/parser.h | 55 +++++++++++++++++-- 9 files changed, 345 insertions(+), 61 deletions(-) create mode 100644 src/error.c create mode 100644 src/error.h diff --git a/.gitignore b/.gitignore index bccf78e..9ea7baa 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ /.zig-cache /zig-out .idea +Makefile noom -noom.* \ No newline at end of file +noom.* diff --git a/build.lua b/build.lua index d1aff88..0c5012b 100755 --- a/build.lua +++ b/build.lua @@ -15,7 +15,10 @@ end local function runCommand(cmd) print("> " .. cmd) - return os.execute(cmd) + local result = os.execute(cmd) + if result ~= true then + os.exit(1) + end end local function fixPath(path) @@ -58,6 +61,7 @@ if not needsDir then end local files = { + 'src/error.c', 'src/helper.c', 'src/lexer.c', 'src/parser.c', diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..d64c938 --- /dev/null +++ b/src/error.c @@ -0,0 +1,150 @@ +#include "error.h" +#include "helper.h" + +noom_uint_t noom_format_error(const noomP_Parser* parser, char* buffer, noom_uint_t buffer_size) { + struct noom_error { + const char* s; + int near; // 0:none 1: near '%s'\n 2: '%s'\n + }; + + static const struct noom_error parser_errors[] = { + [NOOMP_ERROR_NONE] = {0, 0 }, + + [NOOMP_ERROR_OOM] = {"Whoops! Out of memory :(\n", 0}, + [NOOMP_ERROR_EXPECTED_LCURLY] = {"expected '{'", 1}, + [NOOMP_ERROR_EXPECTED_RCURLY] = {"expected '}' to close table literal", 1}, + [NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_KEY] = {"expected ']' to close computed key", 1}, + [NOOMP_ERROR_EXPECTED_EQUALS_AFTER_KEY] = {"expected '=' after table key", 1}, + [NOOMP_ERROR_EXPECTED_FIELD_IDENTIFIER] = {"expected identifier after '.' for field access", 1}, + [NOOMP_ERROR_EXPECTED_METHOD_CALL] = {"expected identifier after ':' for method call", 1}, + [NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_INDEX] = {"expected ']' after index expression", 1}, + [NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION] = {"expected ')' after expression", 1}, + [NOOMP_ERROR_EXPECTED_LPAREN_FOR_PARAMETERS] = {"expected '(' for function parameters", 1}, + [NOOMP_ERROR_EXPECTED_RPAREN_FOR_PARAMETERS] = {"expected ')' for function parameters", 1}, + [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL_FUNCTION] = {"expected identifier after 'local function'\n", 0}, + [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FUNCTION] = {"expected identifier after 'function'\n", 0}, + [NOOMP_ERROR_EXPECTED_END_AFTER_LOCAL_FUNCTION] = {"expected 'end' to close local function declaration", 1}, + [NOOMP_ERROR_EXPECTED_END_AFTER_FUNCTION] = {"expected 'end' to close function declaration", 1}, + [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL] = {"expected identifier after 'local'\n", 0}, + [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LANGLE] = {"expected identifier after '<' for attribute\n", 0}, + [NOOMP_ERROR_EXPECTED_RANGLE_TO_CLOSE_ATTRIBUTE] = {"expected '>' to close attribute after identifier", 1}, + [NOOMP_ERROR_EXPECTED_THEN_AFTER_EXPRESSION] = {"expected 'then' after expression", 1}, + [NOOMP_ERROR_EXPECTED_ELSE_ELSEIF_OR_END] = {"expected 'else', 'elseif', or 'end'", 1}, + [NOOMP_ERROR_EXPECTED_END_AFTER_IF] = {"expected 'end' to close if statement", 1}, + [NOOMP_ERROR_EXPECTED_DO_AFTER_EXPRESSION] = {"expected 'do' after expression", 1}, + [NOOMP_ERROR_EXPECTED_END_AFTER_WHILE] = {"expected 'end' to close while statement", 1}, + [NOOMP_ERROR_EXPECTED_END_AFTER_FOR] = {"expected 'end' to close for statement", 1}, + [NOOMP_ERROR_EXPECTED_END_AFTER_DO] = {"expected 'end' to close do statement", 1}, + [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FOR] = {"expected identifier after 'for'\n", 1}, + [NOOMP_ERROR_EXPECTED_VARIABLE_AFTER_COMMA_IN_FOR] = {"expected variable name after ',' in for loop\n", 0}, + [NOOMP_ERROR_EXPECTED_IN] = {"expected 'in'", 1}, + [NOOMP_ERROR_EXPECTED_UNTIL] = {"expected 'until' to close repeat expression", 1}, + [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_GOTO] = {"expected identifier after goto\n", 0}, + [NOOMP_ERROR_EXPECTED_COLONCOLON] = {"expected :: to end label identifier", 1}, + [NOOMP_ERROR_UNEXPECTED_VALUE] = {"unexpected value", 1}, + // I want someone smarter than me [tema5002] to give these a proper description + [NOOMP_ERROR_UNEXPECTED_SOMETHING1] = {"", 1}, + [NOOMP_ERROR_UNEXPECTED_SOMETHING2] = {"", 1}, + [NOOMP_ERROR_UNEXPECTED_SOMETHING3] = {"", 1}, + [NOOMP_ERROR_UNEXPECTED_SOMETHING4] = {"", 1}, + [NOOMP_ERROR_FAKEATTRIBUTE] = {"invalid attribute", 2}, + [NOOMP_ERROR_RETURN_NOT_END] = {"'return' must be the last statement in a block\n", 0}, + [NOOMP_ERROR_FOR_WRONG_AMOUNT] = {"'for' initializer must have 2 or 3 expressions\n", 0} + }; + + static const struct noom_error lexer_errors[] = { + [NOOML_ERROR_NONE] = {0, 0}, + + [NOOML_ERROR_UNKNOWN] = {"unknown token", 1}, + [NOOML_ERROR_MALFORMED_NUM] = {"malformed number", 1}, + [NOOML_ERROR_UNFINISHED_COMMENT] = {"unfinished comment", 1}, + [NOOML_ERROR_UNFINISHED_STRING] = {"unfinished string", 1}, + [NOOML_ERROR_UNFINISHED_LONG_STRING] = {"unfinished long string", 1}, + [NOOML_ERROR_DECIMAL_ESCAPE_TOO_BIG] = {"decimal escape sequence too big (max 255)", 1}, + [NOOML_ERROR_HEX_ESCAPE_INVALID] = {"invalid hexadecimal escape sequence", 1}, + [NOOML_ERROR_UNICODE_ESCAPE_UNOPENED] = {"expected '{' after '\\u' for Unicode escape", 1}, + [NOOML_ERROR_UNICODE_ESCAPE_UNCLOSED] = {"expected '}' to close Unicode escape sequence", 1}, + [NOOML_ERROR_UNICODE_ESCAPE_TOO_BIG] = {"Unicode escape sequence exceeds maximum (0x10FFFF)", 1}, + }; + + noomP_Error base_err = parser->error_state; + noom_uint_t lexer_code = 0; + noom_uint_t pos = 0; + + if (parser->error_state & NOOMP_ERROR_LEXER) { + base_err = NOOMP_ERROR_LEXER; + lexer_code = parser->error_state & ~NOOMP_ERROR_LEXER; + } + + struct noom_error err = (base_err == NOOMP_ERROR_LEXER) ? lexer_errors[lexer_code] : parser_errors[base_err]; + + noom_uint_t row = 1, column = 1; + for (noom_uint_t i = 0; i < parser->lex_offset; i++) { + if (parser->code[i] == '\n') { + row++; + column = 1; + } + else { + column++; + } + } + + if (buffer == 0) { + noom_uint_t linedig = 0; + for (noom_uint_t eh = row; eh; eh /= 10, linedig++); + + return + sizeof("noom: ") - 1 + + noom_strlen(parser->filename) + + sizeof(":") - 1 + + linedig + + sizeof(":") - 1 + + noom_strlen(err.s) + + + 1 + // \0 + (err.near ? ( + (err.near == 1 ? sizeof(" near") - 1 : 0) + + sizeof(" '") - 1 + + parser->last_token_length + + sizeof("'\n") - 1 + ) : 0); + } + + noom_safe_strcpy(buffer, &pos, buffer_size, "noom: "); + noom_safe_strcpy(buffer, &pos, buffer_size, parser->filename); + noom_safe_strcpy(buffer, &pos, buffer_size, ":"); + + char num_buf[20]; + noom_uint_t num_len = 0; + if (row == 0) { + num_buf[num_len++] = '0'; + } + else { + noom_uint_t temp = row; + noom_uint_t divisor = 1; + while (temp / divisor >= 10) divisor *= 10; + while (divisor > 0) { + num_buf[num_len++] = '0' + (temp / divisor); + temp %= divisor; + divisor /= 10; + } + } + + for (noom_uint_t i = 0; i < num_len && pos < buffer_size - 1; i++) { + buffer[pos++] = num_buf[i]; + } + + noom_safe_strcpy(buffer, &pos, buffer_size, ":"); + noom_safe_strcpy(buffer, &pos, buffer_size, err.s); + if (err.near) { + if (err.near == 1) { + noom_safe_strcpy(buffer, &pos, buffer_size, " near"); + } + noom_safe_strcpy(buffer, &pos, buffer_size, " '"); + for (noom_uint_t i = 0; i < parser->last_token_length && pos < buffer_size - 1; i++) { + buffer[pos++] = parser->code[parser->last_token_offset + i]; + } + noom_safe_strcpy(buffer, &pos, buffer_size, "'\n"); + } + if (pos < buffer_size) buffer[pos] = '\0'; + return pos; +} diff --git a/src/error.h b/src/error.h new file mode 100644 index 0000000..81eef5e --- /dev/null +++ b/src/error.h @@ -0,0 +1,5 @@ +// js let me use include guards 🥀🥀🥀🥀🥀🥀🥀 +#include "types.h" +#include "parser.h" + +noom_uint_t noom_format_error(const noomP_Parser* parser, char* buffer, noom_uint_t buffer_size); diff --git a/src/helper.c b/src/helper.c index 84f6c92..276ced1 100644 --- a/src/helper.c +++ b/src/helper.c @@ -21,6 +21,35 @@ int noom_streql(const char* stra, noom_uint_t lena, const char* strb, noom_uint_ return 1; } +noom_uint_t noom_strlen(const char *s) +{ + const char *a = s; +#ifdef noouuuuu // __GNUC__ + // align + while ((noom_uint_t)s % sizeof(noom_uint_t)) { + if (!*s) return s - a; + s++; + } + + // word at a time scan + typedef noom_uint_t __attribute__((__may_alias__)) word; + const word *w = (const word *)s; + while (!((*w)-(0x101010101010101) & ~(*w) & (0x8080808080808080))) + w++; + + // find exact null byte + s = (const char *)w; +#endif + while (*s) s++; + return s - a; +} + +void noom_safe_strcpy(char* buffer, noom_uint_t* pos, noom_uint_t buffer_size, const char* src) { + while (*src && *pos < buffer_size - 1) { + buffer[(*pos)++] = *src++; + } +} + #include // TODO: remove void* noom_alloc(noom_uint_t size) { diff --git a/src/helper.h b/src/helper.h index b39b5ab..1e2ce55 100644 --- a/src/helper.h +++ b/src/helper.h @@ -2,6 +2,8 @@ int noom_startswith(const char* str, const char* compare); int noom_streql(const char* stra, noom_uint_t lena, const char* strb, noom_uint_t lenb); // rename to something better? +noom_uint_t noom_strlen(const char *s); +void noom_safe_strcpy(char* buffer, noom_uint_t* pos, noom_uint_t buffer_size, const char* src); void* noom_alloc(noom_uint_t size); void noom_free(void* ptr); diff --git a/src/main.c b/src/main.c index fac9a64..8f0fb45 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ #include // for now // #include "lexer.h" -#include "parser.h" #include "helper.h" +#include "error.h" void tab(noom_uint_t amount) { amount *= 2; @@ -10,17 +10,17 @@ void tab(noom_uint_t amount) { } } -void print_node(noomP_Node* node, noom_uint_t depth) { +void print_node(noomP_Node *node, noom_uint_t depth) { tab(depth); printf("{\n"); - tab(depth+1); + tab(depth + 1); printf("type: %s\n", noomP_formatNodeType(node->type)); - tab(depth+1); + tab(depth + 1); printf("location: %lld\n", node->source_offset); - tab(depth+1); + tab(depth + 1); printf("subnodes:\n"); for (noom_uint_t i = 0; i < node->subnodec; i++) { @@ -31,25 +31,56 @@ void print_node(noomP_Node* node, noom_uint_t depth) { printf("}\n"); } -int main(int argc, char** argv) { +int main(int argc, char **argv) { // uhh uhhh uhhhhh - const char* code = "local t = {'a'; 2; 6}}"; + const char *code = "local t = {'a'; 2; 6 \"\\xgg\""; noom_uint_t pos = 0; printf("LEX OUTPUT:\n"); - noomL_Token token; + fputs("\x1b[48;2;10;10;10m", stdout); while (1) { - noomL_lex(code, pos, &token, NOOM_VERSION_54); + noomL_Token token; + //noomL_lex(code, pos, &token, NOOM_VERSION_54); + noomL_ErrorType err = noomL_lex(code, pos, &token, NOOM_VERSION_54); + if (err) break; - printf("%s ", noomL_formatTokenType(token.type)); - for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); - putchar('\n'); + if (token.type == NOOML_TOKEN_KEYWORD) { + fputs("\x1b[38;2;207;142;109m", stdout); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + fflush(stdout); + } else if (token.type == NOOML_TOKEN_WHITESPACE) { + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + } else if (token.type == NOOML_TOKEN_IDENTIFIER) { + fputs("\x1b[38;2;255;255;255m", stdout); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + fflush(stdout); + } else if (token.type == NOOML_TOKEN_SYMBOL) { + fputs("\x1b[38;2;0;255;255m", stdout); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + fflush(stdout); + } else if (token.type == NOOML_TOKEN_STRING) { + fputs("\x1b[38;2;255;0;0m", stdout); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + fflush(stdout); + } else if (token.type == NOOML_TOKEN_NUMBER) { + fputs("\x1b[38;2;0;255;0m", stdout); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + fflush(stdout); + } else { + fputs("\x1b[0m\n", stdout); + printf("%s ", noomL_formatTokenType(token.type)); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + fputs("\x1b[48;2;10;10;10m", stdout); + putchar('\n'); + fflush(stdout); + } pos += token.length; if (token.type == NOOML_TOKEN_EOF) break; } + fputs("\x1b[0m\n", stdout); // time for parser testing printf("\nPARSE OUTPUT:\n"); @@ -60,16 +91,23 @@ int main(int argc, char** argv) { int success = noomP_parse(code, "shitass", NOOM_VERSION_54, &program, &parser); if (success == 0) print_node(program, 0); + else { + noom_uint_t bleh = noom_format_error(&parser, NULL, 0); + char* buf = noom_alloc(bleh); + noom_format_error(&parser, buf, bleh); + fputs(buf, stdout); + noom_free(buf); + } // freeing time noomP_Node *last_node = parser.last_node; while (last_node) { - noomP_Node* next = last_node->previous_node; + noomP_Node *next = last_node->previous_node; // subnodes could be null if we OOM'd during a realloc of it if (last_node->subnodes) noom_free(last_node->subnodes); noom_free(last_node); last_node = next; } - + return 0; } diff --git a/src/parser.c b/src/parser.c index be6f2ea..a83f041 100644 --- a/src/parser.c +++ b/src/parser.c @@ -109,6 +109,11 @@ int noomP_peek(noomP_Parser* parser, noomL_Token* token) { parser->lex_offset += token->length; continue; } + + if (token->type != NOOML_TOKEN_EOF) { + parser->last_token_offset = token->offset; + parser->last_token_length = token->length; + } return 0; } @@ -135,7 +140,7 @@ noomP_Node* noomP_allocNode(noomP_Parser* parser) { noom_free(node); return 0; } - + node->previous_node = parser->last_node; parser->last_node = node; @@ -163,7 +168,7 @@ noomP_Node* noomP_parseTableLiteral(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "{", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_LCURLY; return 0; } noomP_skip(parser, &token); @@ -194,14 +199,14 @@ noomP_Node* noomP_parseTableLiteral(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "]", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_KEY; return 0; } noomP_skip(parser, &token); if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "=", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_EQUALS_AFTER_KEY; return 0; } noomP_skip(parser, &token); @@ -278,7 +283,7 @@ noomP_Node* noomP_parseTableLiteral(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "}", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RCURLY; return 0; } noomP_skip(parser, &token); @@ -300,7 +305,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_FIELD_IDENTIFIER; return 0; } noomP_skip(parser, &token); // skip the field name @@ -331,7 +336,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode if (noomP_peek(parser, &token)) return 0; // look for ] if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, "]", 1))) { // damn it :( - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_INDEX; return 0; } noomP_skip(parser, &token); // skip ] @@ -378,7 +383,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode // check for ) if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ")", 1))) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION; return 0; } @@ -448,7 +453,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode // check for ) if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ")", 1))) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION; return 0; } noomP_skip(parser, &token); @@ -601,7 +606,7 @@ noomP_Node* noomP_parseRawExpression(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, ")", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION; return 0; // unexpected } noomP_skip(parser, &token); @@ -837,7 +842,7 @@ noomP_Node* noomP_parseFunctionParameters(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "(", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_LPAREN_FOR_PARAMETERS; return 0; } noomP_skip(parser, &token); @@ -889,7 +894,7 @@ noomP_Node* noomP_parseFunctionParameters(noomP_Parser* parser) { // closing paren if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, ")", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RPAREN_FOR_PARAMETERS; return 0; } noomP_skip(parser, &token); @@ -953,7 +958,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL_FUNCTION; return 0; } noomP_skip(parser, &token); @@ -976,7 +981,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_LOCAL_FUNCTION; return 0; } noomP_skip(parser, &token); @@ -994,7 +999,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL; return 0; } noomP_skip(parser, &token); @@ -1015,7 +1020,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // the attribute is an identifier. if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LANGLE; return 0; // unexpected } noom_uint_t attr = token.offset; @@ -1028,7 +1033,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, ">", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RANGLE_TO_CLOSE_ATTRIBUTE; return 0; } noomP_skip(parser, &token); @@ -1104,7 +1109,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "then", 4)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_THEN_AFTER_EXPRESSION; return 0; // unexpected } @@ -1119,7 +1124,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_ELSE_ELSEIF_OR_END; return 0; // unexpected } @@ -1134,7 +1139,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "then", 4)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_THEN_AFTER_EXPRESSION; return 0; // unexpected } noomP_skip(parser, &token); @@ -1160,14 +1165,14 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { break; // will check for end outside the loop because else and things } else { // unexpected - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_ELSE_ELSEIF_OR_END; return 0; } } if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_IF; return 0; // unexpected } noomP_skip(parser, &token); @@ -1190,7 +1195,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "do", 2)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_DO_AFTER_EXPRESSION; return 0; // unexpected } noomP_skip(parser, &token); // skip `do` @@ -1202,7 +1207,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_WHILE; return 0; // unexpected } noomP_skip(parser, &token); // skip `end` @@ -1240,7 +1245,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { fname->source_offset = token.offset; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FUNCTION; return 0; // unex. } noomP_skip(parser, &token); @@ -1265,7 +1270,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_FIELD_IDENTIFIER; return 0; } noomP_skip(parser, &token); @@ -1282,7 +1287,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_METHOD_CALL; return 0; } noomP_skip(parser, &token); @@ -1316,7 +1321,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // remove `end` if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_FUNCTION; return 0; } noomP_skip(parser, &token); @@ -1418,7 +1423,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FOR; return 0; } noom_uint_t vname = token.offset; @@ -1468,7 +1473,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { while (1) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_VARIABLE_AFTER_COMMA_IN_FOR; return 0; } noomP_skip(parser, &token); @@ -1494,7 +1499,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // okay. that took a while. now for the in and the expressions if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "in", 2)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IN; return 0; } noomP_skip(parser, &token); @@ -1519,7 +1524,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // making this the same for all of them: do [block] end if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "do", 2)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_DO_AFTER_EXPRESSION; return 0; } noomP_skip(parser, &token); @@ -1531,7 +1536,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_FOR; return 0; } noomP_skip(parser, &token); @@ -1548,7 +1553,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_GOTO; return 0; } noomP_skip(parser, &token); @@ -1578,7 +1583,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "until", 5)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_UNTIL; return 0; } noomP_skip(parser, &token); @@ -1606,7 +1611,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_DO; return 0; } noomP_skip(parser, &token); @@ -1637,7 +1642,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "::", 2)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_COLONCOLON; return 0; } noomP_skip(parser, &token); @@ -1680,7 +1685,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (token.type != NOOML_TOKEN_IDENTIFIER && (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "(", 1))) { // unexpected - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_UNEXPECTED_SOMETHING1; return 0; } @@ -1689,7 +1694,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (item == 0) return 0; if (item->type != NOOMP_NODE_INDEX && item->type != NOOMP_NODE_GETFIELD && item->type != NOOMP_NODE_VARIABLE) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_UNEXPECTED_SOMETHING2; return 0; // unexpected } @@ -1708,7 +1713,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { break; } } else { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_UNEXPECTED_SOMETHING3; return 0; // unexpected } } @@ -1737,12 +1742,12 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // this expression is now a statement. return base; // no need to eat any more. } else { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_UNEXPECTED_SOMETHING4; return 0; // unexpected. e.g. random string or whatever } } - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_UNEXPECTED_VALUE; return 0; } @@ -1795,6 +1800,7 @@ int noomP_initParser(noomP_Parser* parser, const char* code, const char* filenam parser->code = code; parser->filename = filename; parser->lex_offset = 0; + parser->last_token_length = 0; parser->last_node = (void *)0; parser->version = version; diff --git a/src/parser.h b/src/parser.h index 2622fa9..0d6f2a7 100644 --- a/src/parser.h +++ b/src/parser.h @@ -71,13 +71,59 @@ typedef enum noomP_NodeType { typedef enum noomP_Error { NOOMP_ERROR_NONE = 0, NOOMP_ERROR_OOM, - - NOOMP_ERROR_UNEXPECTED, // TODO: maybe split into multiple for better errors? + + NOOMP_ERROR_EXPECTED_LCURLY, // table start + NOOMP_ERROR_EXPECTED_RCURLY, // table end + NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_KEY, + NOOMP_ERROR_EXPECTED_EQUALS_AFTER_KEY, + + NOOMP_ERROR_EXPECTED_FIELD_IDENTIFIER, + NOOMP_ERROR_EXPECTED_METHOD_CALL, + NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_INDEX, + + NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION, + + NOOMP_ERROR_EXPECTED_LPAREN_FOR_PARAMETERS, + NOOMP_ERROR_EXPECTED_RPAREN_FOR_PARAMETERS, + + NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL_FUNCTION, + NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FUNCTION, + NOOMP_ERROR_EXPECTED_END_AFTER_LOCAL_FUNCTION, + NOOMP_ERROR_EXPECTED_END_AFTER_FUNCTION, + + NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL, + + NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LANGLE, + NOOMP_ERROR_EXPECTED_RANGLE_TO_CLOSE_ATTRIBUTE, + + NOOMP_ERROR_EXPECTED_THEN_AFTER_EXPRESSION, + NOOMP_ERROR_EXPECTED_ELSE_ELSEIF_OR_END, + NOOMP_ERROR_EXPECTED_END_AFTER_IF, + NOOMP_ERROR_EXPECTED_DO_AFTER_EXPRESSION, + NOOMP_ERROR_EXPECTED_END_AFTER_WHILE, + NOOMP_ERROR_EXPECTED_END_AFTER_FOR, + NOOMP_ERROR_EXPECTED_END_AFTER_DO, + NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FOR, + NOOMP_ERROR_EXPECTED_VARIABLE_AFTER_COMMA_IN_FOR, + NOOMP_ERROR_EXPECTED_IN, + NOOMP_ERROR_EXPECTED_UNTIL, + + NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_GOTO, + NOOMP_ERROR_EXPECTED_COLONCOLON, + + NOOMP_ERROR_UNEXPECTED_VALUE, + + // i am sorry + NOOMP_ERROR_UNEXPECTED_SOMETHING1, + NOOMP_ERROR_UNEXPECTED_SOMETHING2, + NOOMP_ERROR_UNEXPECTED_SOMETHING3, + NOOMP_ERROR_UNEXPECTED_SOMETHING4, + NOOMP_ERROR_FAKEATTRIBUTE, NOOMP_ERROR_RETURN_NOT_END, NOOMP_ERROR_FOR_WRONG_AMOUNT, - NOOMP_ERROR_LEXER = 1 << 31, // bitwise or'd with the lexer error number + NOOMP_ERROR_LEXER = 1 << 31, // bitwise or's with the lexer error number } noomP_Error; typedef struct noomP_Node { @@ -97,6 +143,9 @@ typedef struct noomP_Parser { // todo: track location in code with line/column? const char* code; const char* filename; + noom_uint_t last_token_offset; + noom_uint_t last_token_length; + noom_uint_t lex_offset; noom_uint_t error_state; -- 2.49.1 From f6b9f8c921e2889a76a388b062bbf0c6fab1803f Mon Sep 17 00:00:00 2001 From: tema5002 Date: Sun, 24 May 2026 11:53:58 +0200 Subject: [PATCH 4/5] revert a3c2ddbf9e729dc2b7faceabc30ffb5b83da19ea revert implement proper error handling --- .gitignore | 3 +- build.lua | 6 +-- src/error.c | 150 --------------------------------------------------- src/error.h | 5 -- src/helper.c | 29 ---------- src/helper.h | 2 - src/main.c | 66 +++++------------------ src/parser.c | 90 +++++++++++++++---------------- src/parser.h | 55 ++----------------- 9 files changed, 61 insertions(+), 345 deletions(-) delete mode 100644 src/error.c delete mode 100644 src/error.h diff --git a/.gitignore b/.gitignore index 9ea7baa..bccf78e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,5 @@ /.zig-cache /zig-out .idea -Makefile noom -noom.* +noom.* \ No newline at end of file diff --git a/build.lua b/build.lua index 0c5012b..d1aff88 100755 --- a/build.lua +++ b/build.lua @@ -15,10 +15,7 @@ end local function runCommand(cmd) print("> " .. cmd) - local result = os.execute(cmd) - if result ~= true then - os.exit(1) - end + return os.execute(cmd) end local function fixPath(path) @@ -61,7 +58,6 @@ if not needsDir then end local files = { - 'src/error.c', 'src/helper.c', 'src/lexer.c', 'src/parser.c', diff --git a/src/error.c b/src/error.c deleted file mode 100644 index d64c938..0000000 --- a/src/error.c +++ /dev/null @@ -1,150 +0,0 @@ -#include "error.h" -#include "helper.h" - -noom_uint_t noom_format_error(const noomP_Parser* parser, char* buffer, noom_uint_t buffer_size) { - struct noom_error { - const char* s; - int near; // 0:none 1: near '%s'\n 2: '%s'\n - }; - - static const struct noom_error parser_errors[] = { - [NOOMP_ERROR_NONE] = {0, 0 }, - - [NOOMP_ERROR_OOM] = {"Whoops! Out of memory :(\n", 0}, - [NOOMP_ERROR_EXPECTED_LCURLY] = {"expected '{'", 1}, - [NOOMP_ERROR_EXPECTED_RCURLY] = {"expected '}' to close table literal", 1}, - [NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_KEY] = {"expected ']' to close computed key", 1}, - [NOOMP_ERROR_EXPECTED_EQUALS_AFTER_KEY] = {"expected '=' after table key", 1}, - [NOOMP_ERROR_EXPECTED_FIELD_IDENTIFIER] = {"expected identifier after '.' for field access", 1}, - [NOOMP_ERROR_EXPECTED_METHOD_CALL] = {"expected identifier after ':' for method call", 1}, - [NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_INDEX] = {"expected ']' after index expression", 1}, - [NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION] = {"expected ')' after expression", 1}, - [NOOMP_ERROR_EXPECTED_LPAREN_FOR_PARAMETERS] = {"expected '(' for function parameters", 1}, - [NOOMP_ERROR_EXPECTED_RPAREN_FOR_PARAMETERS] = {"expected ')' for function parameters", 1}, - [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL_FUNCTION] = {"expected identifier after 'local function'\n", 0}, - [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FUNCTION] = {"expected identifier after 'function'\n", 0}, - [NOOMP_ERROR_EXPECTED_END_AFTER_LOCAL_FUNCTION] = {"expected 'end' to close local function declaration", 1}, - [NOOMP_ERROR_EXPECTED_END_AFTER_FUNCTION] = {"expected 'end' to close function declaration", 1}, - [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL] = {"expected identifier after 'local'\n", 0}, - [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LANGLE] = {"expected identifier after '<' for attribute\n", 0}, - [NOOMP_ERROR_EXPECTED_RANGLE_TO_CLOSE_ATTRIBUTE] = {"expected '>' to close attribute after identifier", 1}, - [NOOMP_ERROR_EXPECTED_THEN_AFTER_EXPRESSION] = {"expected 'then' after expression", 1}, - [NOOMP_ERROR_EXPECTED_ELSE_ELSEIF_OR_END] = {"expected 'else', 'elseif', or 'end'", 1}, - [NOOMP_ERROR_EXPECTED_END_AFTER_IF] = {"expected 'end' to close if statement", 1}, - [NOOMP_ERROR_EXPECTED_DO_AFTER_EXPRESSION] = {"expected 'do' after expression", 1}, - [NOOMP_ERROR_EXPECTED_END_AFTER_WHILE] = {"expected 'end' to close while statement", 1}, - [NOOMP_ERROR_EXPECTED_END_AFTER_FOR] = {"expected 'end' to close for statement", 1}, - [NOOMP_ERROR_EXPECTED_END_AFTER_DO] = {"expected 'end' to close do statement", 1}, - [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FOR] = {"expected identifier after 'for'\n", 1}, - [NOOMP_ERROR_EXPECTED_VARIABLE_AFTER_COMMA_IN_FOR] = {"expected variable name after ',' in for loop\n", 0}, - [NOOMP_ERROR_EXPECTED_IN] = {"expected 'in'", 1}, - [NOOMP_ERROR_EXPECTED_UNTIL] = {"expected 'until' to close repeat expression", 1}, - [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_GOTO] = {"expected identifier after goto\n", 0}, - [NOOMP_ERROR_EXPECTED_COLONCOLON] = {"expected :: to end label identifier", 1}, - [NOOMP_ERROR_UNEXPECTED_VALUE] = {"unexpected value", 1}, - // I want someone smarter than me [tema5002] to give these a proper description - [NOOMP_ERROR_UNEXPECTED_SOMETHING1] = {"", 1}, - [NOOMP_ERROR_UNEXPECTED_SOMETHING2] = {"", 1}, - [NOOMP_ERROR_UNEXPECTED_SOMETHING3] = {"", 1}, - [NOOMP_ERROR_UNEXPECTED_SOMETHING4] = {"", 1}, - [NOOMP_ERROR_FAKEATTRIBUTE] = {"invalid attribute", 2}, - [NOOMP_ERROR_RETURN_NOT_END] = {"'return' must be the last statement in a block\n", 0}, - [NOOMP_ERROR_FOR_WRONG_AMOUNT] = {"'for' initializer must have 2 or 3 expressions\n", 0} - }; - - static const struct noom_error lexer_errors[] = { - [NOOML_ERROR_NONE] = {0, 0}, - - [NOOML_ERROR_UNKNOWN] = {"unknown token", 1}, - [NOOML_ERROR_MALFORMED_NUM] = {"malformed number", 1}, - [NOOML_ERROR_UNFINISHED_COMMENT] = {"unfinished comment", 1}, - [NOOML_ERROR_UNFINISHED_STRING] = {"unfinished string", 1}, - [NOOML_ERROR_UNFINISHED_LONG_STRING] = {"unfinished long string", 1}, - [NOOML_ERROR_DECIMAL_ESCAPE_TOO_BIG] = {"decimal escape sequence too big (max 255)", 1}, - [NOOML_ERROR_HEX_ESCAPE_INVALID] = {"invalid hexadecimal escape sequence", 1}, - [NOOML_ERROR_UNICODE_ESCAPE_UNOPENED] = {"expected '{' after '\\u' for Unicode escape", 1}, - [NOOML_ERROR_UNICODE_ESCAPE_UNCLOSED] = {"expected '}' to close Unicode escape sequence", 1}, - [NOOML_ERROR_UNICODE_ESCAPE_TOO_BIG] = {"Unicode escape sequence exceeds maximum (0x10FFFF)", 1}, - }; - - noomP_Error base_err = parser->error_state; - noom_uint_t lexer_code = 0; - noom_uint_t pos = 0; - - if (parser->error_state & NOOMP_ERROR_LEXER) { - base_err = NOOMP_ERROR_LEXER; - lexer_code = parser->error_state & ~NOOMP_ERROR_LEXER; - } - - struct noom_error err = (base_err == NOOMP_ERROR_LEXER) ? lexer_errors[lexer_code] : parser_errors[base_err]; - - noom_uint_t row = 1, column = 1; - for (noom_uint_t i = 0; i < parser->lex_offset; i++) { - if (parser->code[i] == '\n') { - row++; - column = 1; - } - else { - column++; - } - } - - if (buffer == 0) { - noom_uint_t linedig = 0; - for (noom_uint_t eh = row; eh; eh /= 10, linedig++); - - return - sizeof("noom: ") - 1 + - noom_strlen(parser->filename) + - sizeof(":") - 1 + - linedig + - sizeof(":") - 1 + - noom_strlen(err.s) + - + 1 + // \0 - (err.near ? ( - (err.near == 1 ? sizeof(" near") - 1 : 0) + - sizeof(" '") - 1 + - parser->last_token_length + - sizeof("'\n") - 1 - ) : 0); - } - - noom_safe_strcpy(buffer, &pos, buffer_size, "noom: "); - noom_safe_strcpy(buffer, &pos, buffer_size, parser->filename); - noom_safe_strcpy(buffer, &pos, buffer_size, ":"); - - char num_buf[20]; - noom_uint_t num_len = 0; - if (row == 0) { - num_buf[num_len++] = '0'; - } - else { - noom_uint_t temp = row; - noom_uint_t divisor = 1; - while (temp / divisor >= 10) divisor *= 10; - while (divisor > 0) { - num_buf[num_len++] = '0' + (temp / divisor); - temp %= divisor; - divisor /= 10; - } - } - - for (noom_uint_t i = 0; i < num_len && pos < buffer_size - 1; i++) { - buffer[pos++] = num_buf[i]; - } - - noom_safe_strcpy(buffer, &pos, buffer_size, ":"); - noom_safe_strcpy(buffer, &pos, buffer_size, err.s); - if (err.near) { - if (err.near == 1) { - noom_safe_strcpy(buffer, &pos, buffer_size, " near"); - } - noom_safe_strcpy(buffer, &pos, buffer_size, " '"); - for (noom_uint_t i = 0; i < parser->last_token_length && pos < buffer_size - 1; i++) { - buffer[pos++] = parser->code[parser->last_token_offset + i]; - } - noom_safe_strcpy(buffer, &pos, buffer_size, "'\n"); - } - if (pos < buffer_size) buffer[pos] = '\0'; - return pos; -} diff --git a/src/error.h b/src/error.h deleted file mode 100644 index 81eef5e..0000000 --- a/src/error.h +++ /dev/null @@ -1,5 +0,0 @@ -// js let me use include guards 🥀🥀🥀🥀🥀🥀🥀 -#include "types.h" -#include "parser.h" - -noom_uint_t noom_format_error(const noomP_Parser* parser, char* buffer, noom_uint_t buffer_size); diff --git a/src/helper.c b/src/helper.c index 276ced1..84f6c92 100644 --- a/src/helper.c +++ b/src/helper.c @@ -21,35 +21,6 @@ int noom_streql(const char* stra, noom_uint_t lena, const char* strb, noom_uint_ return 1; } -noom_uint_t noom_strlen(const char *s) -{ - const char *a = s; -#ifdef noouuuuu // __GNUC__ - // align - while ((noom_uint_t)s % sizeof(noom_uint_t)) { - if (!*s) return s - a; - s++; - } - - // word at a time scan - typedef noom_uint_t __attribute__((__may_alias__)) word; - const word *w = (const word *)s; - while (!((*w)-(0x101010101010101) & ~(*w) & (0x8080808080808080))) - w++; - - // find exact null byte - s = (const char *)w; -#endif - while (*s) s++; - return s - a; -} - -void noom_safe_strcpy(char* buffer, noom_uint_t* pos, noom_uint_t buffer_size, const char* src) { - while (*src && *pos < buffer_size - 1) { - buffer[(*pos)++] = *src++; - } -} - #include // TODO: remove void* noom_alloc(noom_uint_t size) { diff --git a/src/helper.h b/src/helper.h index 1e2ce55..b39b5ab 100644 --- a/src/helper.h +++ b/src/helper.h @@ -2,8 +2,6 @@ int noom_startswith(const char* str, const char* compare); int noom_streql(const char* stra, noom_uint_t lena, const char* strb, noom_uint_t lenb); // rename to something better? -noom_uint_t noom_strlen(const char *s); -void noom_safe_strcpy(char* buffer, noom_uint_t* pos, noom_uint_t buffer_size, const char* src); void* noom_alloc(noom_uint_t size); void noom_free(void* ptr); diff --git a/src/main.c b/src/main.c index 8f0fb45..fac9a64 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ #include // for now // #include "lexer.h" +#include "parser.h" #include "helper.h" -#include "error.h" void tab(noom_uint_t amount) { amount *= 2; @@ -10,17 +10,17 @@ void tab(noom_uint_t amount) { } } -void print_node(noomP_Node *node, noom_uint_t depth) { +void print_node(noomP_Node* node, noom_uint_t depth) { tab(depth); printf("{\n"); - tab(depth + 1); + tab(depth+1); printf("type: %s\n", noomP_formatNodeType(node->type)); - tab(depth + 1); + tab(depth+1); printf("location: %lld\n", node->source_offset); - tab(depth + 1); + tab(depth+1); printf("subnodes:\n"); for (noom_uint_t i = 0; i < node->subnodec; i++) { @@ -31,56 +31,25 @@ void print_node(noomP_Node *node, noom_uint_t depth) { printf("}\n"); } -int main(int argc, char **argv) { +int main(int argc, char** argv) { // uhh uhhh uhhhhh - const char *code = "local t = {'a'; 2; 6 \"\\xgg\""; + const char* code = "local t = {'a'; 2; 6}}"; noom_uint_t pos = 0; printf("LEX OUTPUT:\n"); - fputs("\x1b[48;2;10;10;10m", stdout); + noomL_Token token; while (1) { - noomL_Token token; - //noomL_lex(code, pos, &token, NOOM_VERSION_54); - noomL_ErrorType err = noomL_lex(code, pos, &token, NOOM_VERSION_54); - if (err) break; + noomL_lex(code, pos, &token, NOOM_VERSION_54); - if (token.type == NOOML_TOKEN_KEYWORD) { - fputs("\x1b[38;2;207;142;109m", stdout); - for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); - fflush(stdout); - } else if (token.type == NOOML_TOKEN_WHITESPACE) { - for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); - } else if (token.type == NOOML_TOKEN_IDENTIFIER) { - fputs("\x1b[38;2;255;255;255m", stdout); - for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); - fflush(stdout); - } else if (token.type == NOOML_TOKEN_SYMBOL) { - fputs("\x1b[38;2;0;255;255m", stdout); - for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); - fflush(stdout); - } else if (token.type == NOOML_TOKEN_STRING) { - fputs("\x1b[38;2;255;0;0m", stdout); - for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); - fflush(stdout); - } else if (token.type == NOOML_TOKEN_NUMBER) { - fputs("\x1b[38;2;0;255;0m", stdout); - for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); - fflush(stdout); - } else { - fputs("\x1b[0m\n", stdout); - printf("%s ", noomL_formatTokenType(token.type)); - for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); - fputs("\x1b[48;2;10;10;10m", stdout); - putchar('\n'); - fflush(stdout); - } + printf("%s ", noomL_formatTokenType(token.type)); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + putchar('\n'); pos += token.length; if (token.type == NOOML_TOKEN_EOF) break; } - fputs("\x1b[0m\n", stdout); // time for parser testing printf("\nPARSE OUTPUT:\n"); @@ -91,23 +60,16 @@ int main(int argc, char **argv) { int success = noomP_parse(code, "shitass", NOOM_VERSION_54, &program, &parser); if (success == 0) print_node(program, 0); - else { - noom_uint_t bleh = noom_format_error(&parser, NULL, 0); - char* buf = noom_alloc(bleh); - noom_format_error(&parser, buf, bleh); - fputs(buf, stdout); - noom_free(buf); - } // freeing time noomP_Node *last_node = parser.last_node; while (last_node) { - noomP_Node *next = last_node->previous_node; + noomP_Node* next = last_node->previous_node; // subnodes could be null if we OOM'd during a realloc of it if (last_node->subnodes) noom_free(last_node->subnodes); noom_free(last_node); last_node = next; } - + return 0; } diff --git a/src/parser.c b/src/parser.c index a83f041..be6f2ea 100644 --- a/src/parser.c +++ b/src/parser.c @@ -109,11 +109,6 @@ int noomP_peek(noomP_Parser* parser, noomL_Token* token) { parser->lex_offset += token->length; continue; } - - if (token->type != NOOML_TOKEN_EOF) { - parser->last_token_offset = token->offset; - parser->last_token_length = token->length; - } return 0; } @@ -140,7 +135,7 @@ noomP_Node* noomP_allocNode(noomP_Parser* parser) { noom_free(node); return 0; } - + node->previous_node = parser->last_node; parser->last_node = node; @@ -168,7 +163,7 @@ noomP_Node* noomP_parseTableLiteral(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "{", 1)) { - parser->error_state = NOOMP_ERROR_EXPECTED_LCURLY; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -199,14 +194,14 @@ noomP_Node* noomP_parseTableLiteral(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "]", 1)) { - parser->error_state = NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_KEY; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "=", 1)) { - parser->error_state = NOOMP_ERROR_EXPECTED_EQUALS_AFTER_KEY; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -283,7 +278,7 @@ noomP_Node* noomP_parseTableLiteral(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "}", 1)) { - parser->error_state = NOOMP_ERROR_EXPECTED_RCURLY; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -305,7 +300,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_EXPECTED_FIELD_IDENTIFIER; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); // skip the field name @@ -336,7 +331,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode if (noomP_peek(parser, &token)) return 0; // look for ] if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, "]", 1))) { // damn it :( - parser->error_state = NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_INDEX; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); // skip ] @@ -383,7 +378,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode // check for ) if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ")", 1))) { - parser->error_state = NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } @@ -453,7 +448,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode // check for ) if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ")", 1))) { - parser->error_state = NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -606,7 +601,7 @@ noomP_Node* noomP_parseRawExpression(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, ")", 1)) { - parser->error_state = NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; // unexpected } noomP_skip(parser, &token); @@ -842,7 +837,7 @@ noomP_Node* noomP_parseFunctionParameters(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "(", 1)) { - parser->error_state = NOOMP_ERROR_EXPECTED_LPAREN_FOR_PARAMETERS; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -894,7 +889,7 @@ noomP_Node* noomP_parseFunctionParameters(noomP_Parser* parser) { // closing paren if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, ")", 1)) { - parser->error_state = NOOMP_ERROR_EXPECTED_RPAREN_FOR_PARAMETERS; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -958,7 +953,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL_FUNCTION; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -981,7 +976,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_LOCAL_FUNCTION; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -999,7 +994,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1020,7 +1015,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // the attribute is an identifier. if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LANGLE; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; // unexpected } noom_uint_t attr = token.offset; @@ -1033,7 +1028,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, ">", 1)) { - parser->error_state = NOOMP_ERROR_EXPECTED_RANGLE_TO_CLOSE_ATTRIBUTE; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1109,7 +1104,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "then", 4)) { - parser->error_state = NOOMP_ERROR_EXPECTED_THEN_AFTER_EXPRESSION; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; // unexpected } @@ -1124,7 +1119,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD) { - parser->error_state = NOOMP_ERROR_EXPECTED_ELSE_ELSEIF_OR_END; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; // unexpected } @@ -1139,7 +1134,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "then", 4)) { - parser->error_state = NOOMP_ERROR_EXPECTED_THEN_AFTER_EXPRESSION; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; // unexpected } noomP_skip(parser, &token); @@ -1165,14 +1160,14 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { break; // will check for end outside the loop because else and things } else { // unexpected - parser->error_state = NOOMP_ERROR_EXPECTED_ELSE_ELSEIF_OR_END; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } } if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_IF; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; // unexpected } noomP_skip(parser, &token); @@ -1195,7 +1190,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "do", 2)) { - parser->error_state = NOOMP_ERROR_EXPECTED_DO_AFTER_EXPRESSION; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; // unexpected } noomP_skip(parser, &token); // skip `do` @@ -1207,7 +1202,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_WHILE; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; // unexpected } noomP_skip(parser, &token); // skip `end` @@ -1245,7 +1240,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { fname->source_offset = token.offset; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FUNCTION; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; // unex. } noomP_skip(parser, &token); @@ -1270,7 +1265,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_EXPECTED_FIELD_IDENTIFIER; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1287,7 +1282,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_EXPECTED_METHOD_CALL; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1321,7 +1316,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // remove `end` if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_FUNCTION; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1423,7 +1418,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FOR; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noom_uint_t vname = token.offset; @@ -1473,7 +1468,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { while (1) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_EXPECTED_VARIABLE_AFTER_COMMA_IN_FOR; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1499,7 +1494,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // okay. that took a while. now for the in and the expressions if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "in", 2)) { - parser->error_state = NOOMP_ERROR_EXPECTED_IN; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1524,7 +1519,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // making this the same for all of them: do [block] end if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "do", 2)) { - parser->error_state = NOOMP_ERROR_EXPECTED_DO_AFTER_EXPRESSION; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1536,7 +1531,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_FOR; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1553,7 +1548,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_GOTO; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1583,7 +1578,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "until", 5)) { - parser->error_state = NOOMP_ERROR_EXPECTED_UNTIL; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1611,7 +1606,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_DO; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1642,7 +1637,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "::", 2)) { - parser->error_state = NOOMP_ERROR_EXPECTED_COLONCOLON; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } noomP_skip(parser, &token); @@ -1685,7 +1680,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (token.type != NOOML_TOKEN_IDENTIFIER && (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "(", 1))) { // unexpected - parser->error_state = NOOMP_ERROR_UNEXPECTED_SOMETHING1; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } @@ -1694,7 +1689,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (item == 0) return 0; if (item->type != NOOMP_NODE_INDEX && item->type != NOOMP_NODE_GETFIELD && item->type != NOOMP_NODE_VARIABLE) { - parser->error_state = NOOMP_ERROR_UNEXPECTED_SOMETHING2; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; // unexpected } @@ -1713,7 +1708,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { break; } } else { - parser->error_state = NOOMP_ERROR_UNEXPECTED_SOMETHING3; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; // unexpected } } @@ -1742,12 +1737,12 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // this expression is now a statement. return base; // no need to eat any more. } else { - parser->error_state = NOOMP_ERROR_UNEXPECTED_SOMETHING4; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; // unexpected. e.g. random string or whatever } } - parser->error_state = NOOMP_ERROR_UNEXPECTED_VALUE; + parser->error_state = NOOMP_ERROR_UNEXPECTED; return 0; } @@ -1800,7 +1795,6 @@ int noomP_initParser(noomP_Parser* parser, const char* code, const char* filenam parser->code = code; parser->filename = filename; parser->lex_offset = 0; - parser->last_token_length = 0; parser->last_node = (void *)0; parser->version = version; diff --git a/src/parser.h b/src/parser.h index 0d6f2a7..2622fa9 100644 --- a/src/parser.h +++ b/src/parser.h @@ -71,59 +71,13 @@ typedef enum noomP_NodeType { typedef enum noomP_Error { NOOMP_ERROR_NONE = 0, NOOMP_ERROR_OOM, - - NOOMP_ERROR_EXPECTED_LCURLY, // table start - NOOMP_ERROR_EXPECTED_RCURLY, // table end - NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_KEY, - NOOMP_ERROR_EXPECTED_EQUALS_AFTER_KEY, - - NOOMP_ERROR_EXPECTED_FIELD_IDENTIFIER, - NOOMP_ERROR_EXPECTED_METHOD_CALL, - NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_INDEX, - - NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION, - - NOOMP_ERROR_EXPECTED_LPAREN_FOR_PARAMETERS, - NOOMP_ERROR_EXPECTED_RPAREN_FOR_PARAMETERS, - - NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL_FUNCTION, - NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FUNCTION, - NOOMP_ERROR_EXPECTED_END_AFTER_LOCAL_FUNCTION, - NOOMP_ERROR_EXPECTED_END_AFTER_FUNCTION, - - NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL, - - NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LANGLE, - NOOMP_ERROR_EXPECTED_RANGLE_TO_CLOSE_ATTRIBUTE, - - NOOMP_ERROR_EXPECTED_THEN_AFTER_EXPRESSION, - NOOMP_ERROR_EXPECTED_ELSE_ELSEIF_OR_END, - NOOMP_ERROR_EXPECTED_END_AFTER_IF, - NOOMP_ERROR_EXPECTED_DO_AFTER_EXPRESSION, - NOOMP_ERROR_EXPECTED_END_AFTER_WHILE, - NOOMP_ERROR_EXPECTED_END_AFTER_FOR, - NOOMP_ERROR_EXPECTED_END_AFTER_DO, - NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FOR, - NOOMP_ERROR_EXPECTED_VARIABLE_AFTER_COMMA_IN_FOR, - NOOMP_ERROR_EXPECTED_IN, - NOOMP_ERROR_EXPECTED_UNTIL, - - NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_GOTO, - NOOMP_ERROR_EXPECTED_COLONCOLON, - - NOOMP_ERROR_UNEXPECTED_VALUE, - - // i am sorry - NOOMP_ERROR_UNEXPECTED_SOMETHING1, - NOOMP_ERROR_UNEXPECTED_SOMETHING2, - NOOMP_ERROR_UNEXPECTED_SOMETHING3, - NOOMP_ERROR_UNEXPECTED_SOMETHING4, - + + NOOMP_ERROR_UNEXPECTED, // TODO: maybe split into multiple for better errors? NOOMP_ERROR_FAKEATTRIBUTE, NOOMP_ERROR_RETURN_NOT_END, NOOMP_ERROR_FOR_WRONG_AMOUNT, - NOOMP_ERROR_LEXER = 1 << 31, // bitwise or's with the lexer error number + NOOMP_ERROR_LEXER = 1 << 31, // bitwise or'd with the lexer error number } noomP_Error; typedef struct noomP_Node { @@ -143,9 +97,6 @@ typedef struct noomP_Parser { // todo: track location in code with line/column? const char* code; const char* filename; - noom_uint_t last_token_offset; - noom_uint_t last_token_length; - noom_uint_t lex_offset; noom_uint_t error_state; -- 2.49.1 From 511841f1cc3a8c635da1daf12809494d1c43c84a Mon Sep 17 00:00:00 2001 From: tema5002 Date: Sun, 24 May 2026 12:55:45 +0300 Subject: [PATCH 5/5] dammit --- .gitignore | 3 +- build.lua | 6 ++- src/error.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/error.h | 5 ++ src/helper.c | 13 +++++ src/helper.h | 2 + src/main.c | 66 ++++++++++++++++++----- src/parser.c | 90 ++++++++++++++++--------------- src/parser.h | 55 +++++++++++++++++-- 9 files changed, 329 insertions(+), 61 deletions(-) create mode 100644 src/error.c create mode 100644 src/error.h diff --git a/.gitignore b/.gitignore index bccf78e..f136d34 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ /zig-out .idea noom -noom.* \ No newline at end of file +noom.* +Makefile diff --git a/build.lua b/build.lua index d1aff88..0c5012b 100755 --- a/build.lua +++ b/build.lua @@ -15,7 +15,10 @@ end local function runCommand(cmd) print("> " .. cmd) - return os.execute(cmd) + local result = os.execute(cmd) + if result ~= true then + os.exit(1) + end end local function fixPath(path) @@ -58,6 +61,7 @@ if not needsDir then end local files = { + 'src/error.c', 'src/helper.c', 'src/lexer.c', 'src/parser.c', diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..d64c938 --- /dev/null +++ b/src/error.c @@ -0,0 +1,150 @@ +#include "error.h" +#include "helper.h" + +noom_uint_t noom_format_error(const noomP_Parser* parser, char* buffer, noom_uint_t buffer_size) { + struct noom_error { + const char* s; + int near; // 0:none 1: near '%s'\n 2: '%s'\n + }; + + static const struct noom_error parser_errors[] = { + [NOOMP_ERROR_NONE] = {0, 0 }, + + [NOOMP_ERROR_OOM] = {"Whoops! Out of memory :(\n", 0}, + [NOOMP_ERROR_EXPECTED_LCURLY] = {"expected '{'", 1}, + [NOOMP_ERROR_EXPECTED_RCURLY] = {"expected '}' to close table literal", 1}, + [NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_KEY] = {"expected ']' to close computed key", 1}, + [NOOMP_ERROR_EXPECTED_EQUALS_AFTER_KEY] = {"expected '=' after table key", 1}, + [NOOMP_ERROR_EXPECTED_FIELD_IDENTIFIER] = {"expected identifier after '.' for field access", 1}, + [NOOMP_ERROR_EXPECTED_METHOD_CALL] = {"expected identifier after ':' for method call", 1}, + [NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_INDEX] = {"expected ']' after index expression", 1}, + [NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION] = {"expected ')' after expression", 1}, + [NOOMP_ERROR_EXPECTED_LPAREN_FOR_PARAMETERS] = {"expected '(' for function parameters", 1}, + [NOOMP_ERROR_EXPECTED_RPAREN_FOR_PARAMETERS] = {"expected ')' for function parameters", 1}, + [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL_FUNCTION] = {"expected identifier after 'local function'\n", 0}, + [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FUNCTION] = {"expected identifier after 'function'\n", 0}, + [NOOMP_ERROR_EXPECTED_END_AFTER_LOCAL_FUNCTION] = {"expected 'end' to close local function declaration", 1}, + [NOOMP_ERROR_EXPECTED_END_AFTER_FUNCTION] = {"expected 'end' to close function declaration", 1}, + [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL] = {"expected identifier after 'local'\n", 0}, + [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LANGLE] = {"expected identifier after '<' for attribute\n", 0}, + [NOOMP_ERROR_EXPECTED_RANGLE_TO_CLOSE_ATTRIBUTE] = {"expected '>' to close attribute after identifier", 1}, + [NOOMP_ERROR_EXPECTED_THEN_AFTER_EXPRESSION] = {"expected 'then' after expression", 1}, + [NOOMP_ERROR_EXPECTED_ELSE_ELSEIF_OR_END] = {"expected 'else', 'elseif', or 'end'", 1}, + [NOOMP_ERROR_EXPECTED_END_AFTER_IF] = {"expected 'end' to close if statement", 1}, + [NOOMP_ERROR_EXPECTED_DO_AFTER_EXPRESSION] = {"expected 'do' after expression", 1}, + [NOOMP_ERROR_EXPECTED_END_AFTER_WHILE] = {"expected 'end' to close while statement", 1}, + [NOOMP_ERROR_EXPECTED_END_AFTER_FOR] = {"expected 'end' to close for statement", 1}, + [NOOMP_ERROR_EXPECTED_END_AFTER_DO] = {"expected 'end' to close do statement", 1}, + [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FOR] = {"expected identifier after 'for'\n", 1}, + [NOOMP_ERROR_EXPECTED_VARIABLE_AFTER_COMMA_IN_FOR] = {"expected variable name after ',' in for loop\n", 0}, + [NOOMP_ERROR_EXPECTED_IN] = {"expected 'in'", 1}, + [NOOMP_ERROR_EXPECTED_UNTIL] = {"expected 'until' to close repeat expression", 1}, + [NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_GOTO] = {"expected identifier after goto\n", 0}, + [NOOMP_ERROR_EXPECTED_COLONCOLON] = {"expected :: to end label identifier", 1}, + [NOOMP_ERROR_UNEXPECTED_VALUE] = {"unexpected value", 1}, + // I want someone smarter than me [tema5002] to give these a proper description + [NOOMP_ERROR_UNEXPECTED_SOMETHING1] = {"", 1}, + [NOOMP_ERROR_UNEXPECTED_SOMETHING2] = {"", 1}, + [NOOMP_ERROR_UNEXPECTED_SOMETHING3] = {"", 1}, + [NOOMP_ERROR_UNEXPECTED_SOMETHING4] = {"", 1}, + [NOOMP_ERROR_FAKEATTRIBUTE] = {"invalid attribute", 2}, + [NOOMP_ERROR_RETURN_NOT_END] = {"'return' must be the last statement in a block\n", 0}, + [NOOMP_ERROR_FOR_WRONG_AMOUNT] = {"'for' initializer must have 2 or 3 expressions\n", 0} + }; + + static const struct noom_error lexer_errors[] = { + [NOOML_ERROR_NONE] = {0, 0}, + + [NOOML_ERROR_UNKNOWN] = {"unknown token", 1}, + [NOOML_ERROR_MALFORMED_NUM] = {"malformed number", 1}, + [NOOML_ERROR_UNFINISHED_COMMENT] = {"unfinished comment", 1}, + [NOOML_ERROR_UNFINISHED_STRING] = {"unfinished string", 1}, + [NOOML_ERROR_UNFINISHED_LONG_STRING] = {"unfinished long string", 1}, + [NOOML_ERROR_DECIMAL_ESCAPE_TOO_BIG] = {"decimal escape sequence too big (max 255)", 1}, + [NOOML_ERROR_HEX_ESCAPE_INVALID] = {"invalid hexadecimal escape sequence", 1}, + [NOOML_ERROR_UNICODE_ESCAPE_UNOPENED] = {"expected '{' after '\\u' for Unicode escape", 1}, + [NOOML_ERROR_UNICODE_ESCAPE_UNCLOSED] = {"expected '}' to close Unicode escape sequence", 1}, + [NOOML_ERROR_UNICODE_ESCAPE_TOO_BIG] = {"Unicode escape sequence exceeds maximum (0x10FFFF)", 1}, + }; + + noomP_Error base_err = parser->error_state; + noom_uint_t lexer_code = 0; + noom_uint_t pos = 0; + + if (parser->error_state & NOOMP_ERROR_LEXER) { + base_err = NOOMP_ERROR_LEXER; + lexer_code = parser->error_state & ~NOOMP_ERROR_LEXER; + } + + struct noom_error err = (base_err == NOOMP_ERROR_LEXER) ? lexer_errors[lexer_code] : parser_errors[base_err]; + + noom_uint_t row = 1, column = 1; + for (noom_uint_t i = 0; i < parser->lex_offset; i++) { + if (parser->code[i] == '\n') { + row++; + column = 1; + } + else { + column++; + } + } + + if (buffer == 0) { + noom_uint_t linedig = 0; + for (noom_uint_t eh = row; eh; eh /= 10, linedig++); + + return + sizeof("noom: ") - 1 + + noom_strlen(parser->filename) + + sizeof(":") - 1 + + linedig + + sizeof(":") - 1 + + noom_strlen(err.s) + + + 1 + // \0 + (err.near ? ( + (err.near == 1 ? sizeof(" near") - 1 : 0) + + sizeof(" '") - 1 + + parser->last_token_length + + sizeof("'\n") - 1 + ) : 0); + } + + noom_safe_strcpy(buffer, &pos, buffer_size, "noom: "); + noom_safe_strcpy(buffer, &pos, buffer_size, parser->filename); + noom_safe_strcpy(buffer, &pos, buffer_size, ":"); + + char num_buf[20]; + noom_uint_t num_len = 0; + if (row == 0) { + num_buf[num_len++] = '0'; + } + else { + noom_uint_t temp = row; + noom_uint_t divisor = 1; + while (temp / divisor >= 10) divisor *= 10; + while (divisor > 0) { + num_buf[num_len++] = '0' + (temp / divisor); + temp %= divisor; + divisor /= 10; + } + } + + for (noom_uint_t i = 0; i < num_len && pos < buffer_size - 1; i++) { + buffer[pos++] = num_buf[i]; + } + + noom_safe_strcpy(buffer, &pos, buffer_size, ":"); + noom_safe_strcpy(buffer, &pos, buffer_size, err.s); + if (err.near) { + if (err.near == 1) { + noom_safe_strcpy(buffer, &pos, buffer_size, " near"); + } + noom_safe_strcpy(buffer, &pos, buffer_size, " '"); + for (noom_uint_t i = 0; i < parser->last_token_length && pos < buffer_size - 1; i++) { + buffer[pos++] = parser->code[parser->last_token_offset + i]; + } + noom_safe_strcpy(buffer, &pos, buffer_size, "'\n"); + } + if (pos < buffer_size) buffer[pos] = '\0'; + return pos; +} diff --git a/src/error.h b/src/error.h new file mode 100644 index 0000000..81eef5e --- /dev/null +++ b/src/error.h @@ -0,0 +1,5 @@ +// js let me use include guards 🥀🥀🥀🥀🥀🥀🥀 +#include "types.h" +#include "parser.h" + +noom_uint_t noom_format_error(const noomP_Parser* parser, char* buffer, noom_uint_t buffer_size); diff --git a/src/helper.c b/src/helper.c index 84f6c92..233a3b3 100644 --- a/src/helper.c +++ b/src/helper.c @@ -21,6 +21,19 @@ int noom_streql(const char* stra, noom_uint_t lena, const char* strb, noom_uint_ return 1; } +noom_uint_t noom_strlen(const char *s) +{ + const char *a = s; + while (*s) s++; + return s - a; +} + +void noom_safe_strcpy(char* buffer, noom_uint_t* pos, noom_uint_t buffer_size, const char* src) { + while (*src && *pos < buffer_size - 1) { + buffer[(*pos)++] = *src++; + } +} + #include // TODO: remove void* noom_alloc(noom_uint_t size) { diff --git a/src/helper.h b/src/helper.h index b39b5ab..1e2ce55 100644 --- a/src/helper.h +++ b/src/helper.h @@ -2,6 +2,8 @@ int noom_startswith(const char* str, const char* compare); int noom_streql(const char* stra, noom_uint_t lena, const char* strb, noom_uint_t lenb); // rename to something better? +noom_uint_t noom_strlen(const char *s); +void noom_safe_strcpy(char* buffer, noom_uint_t* pos, noom_uint_t buffer_size, const char* src); void* noom_alloc(noom_uint_t size); void noom_free(void* ptr); diff --git a/src/main.c b/src/main.c index fac9a64..8f0fb45 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ #include // for now // #include "lexer.h" -#include "parser.h" #include "helper.h" +#include "error.h" void tab(noom_uint_t amount) { amount *= 2; @@ -10,17 +10,17 @@ void tab(noom_uint_t amount) { } } -void print_node(noomP_Node* node, noom_uint_t depth) { +void print_node(noomP_Node *node, noom_uint_t depth) { tab(depth); printf("{\n"); - tab(depth+1); + tab(depth + 1); printf("type: %s\n", noomP_formatNodeType(node->type)); - tab(depth+1); + tab(depth + 1); printf("location: %lld\n", node->source_offset); - tab(depth+1); + tab(depth + 1); printf("subnodes:\n"); for (noom_uint_t i = 0; i < node->subnodec; i++) { @@ -31,25 +31,56 @@ void print_node(noomP_Node* node, noom_uint_t depth) { printf("}\n"); } -int main(int argc, char** argv) { +int main(int argc, char **argv) { // uhh uhhh uhhhhh - const char* code = "local t = {'a'; 2; 6}}"; + const char *code = "local t = {'a'; 2; 6 \"\\xgg\""; noom_uint_t pos = 0; printf("LEX OUTPUT:\n"); - noomL_Token token; + fputs("\x1b[48;2;10;10;10m", stdout); while (1) { - noomL_lex(code, pos, &token, NOOM_VERSION_54); + noomL_Token token; + //noomL_lex(code, pos, &token, NOOM_VERSION_54); + noomL_ErrorType err = noomL_lex(code, pos, &token, NOOM_VERSION_54); + if (err) break; - printf("%s ", noomL_formatTokenType(token.type)); - for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); - putchar('\n'); + if (token.type == NOOML_TOKEN_KEYWORD) { + fputs("\x1b[38;2;207;142;109m", stdout); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + fflush(stdout); + } else if (token.type == NOOML_TOKEN_WHITESPACE) { + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + } else if (token.type == NOOML_TOKEN_IDENTIFIER) { + fputs("\x1b[38;2;255;255;255m", stdout); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + fflush(stdout); + } else if (token.type == NOOML_TOKEN_SYMBOL) { + fputs("\x1b[38;2;0;255;255m", stdout); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + fflush(stdout); + } else if (token.type == NOOML_TOKEN_STRING) { + fputs("\x1b[38;2;255;0;0m", stdout); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + fflush(stdout); + } else if (token.type == NOOML_TOKEN_NUMBER) { + fputs("\x1b[38;2;0;255;0m", stdout); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + fflush(stdout); + } else { + fputs("\x1b[0m\n", stdout); + printf("%s ", noomL_formatTokenType(token.type)); + for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]); + fputs("\x1b[48;2;10;10;10m", stdout); + putchar('\n'); + fflush(stdout); + } pos += token.length; if (token.type == NOOML_TOKEN_EOF) break; } + fputs("\x1b[0m\n", stdout); // time for parser testing printf("\nPARSE OUTPUT:\n"); @@ -60,16 +91,23 @@ int main(int argc, char** argv) { int success = noomP_parse(code, "shitass", NOOM_VERSION_54, &program, &parser); if (success == 0) print_node(program, 0); + else { + noom_uint_t bleh = noom_format_error(&parser, NULL, 0); + char* buf = noom_alloc(bleh); + noom_format_error(&parser, buf, bleh); + fputs(buf, stdout); + noom_free(buf); + } // freeing time noomP_Node *last_node = parser.last_node; while (last_node) { - noomP_Node* next = last_node->previous_node; + noomP_Node *next = last_node->previous_node; // subnodes could be null if we OOM'd during a realloc of it if (last_node->subnodes) noom_free(last_node->subnodes); noom_free(last_node); last_node = next; } - + return 0; } diff --git a/src/parser.c b/src/parser.c index be6f2ea..a83f041 100644 --- a/src/parser.c +++ b/src/parser.c @@ -109,6 +109,11 @@ int noomP_peek(noomP_Parser* parser, noomL_Token* token) { parser->lex_offset += token->length; continue; } + + if (token->type != NOOML_TOKEN_EOF) { + parser->last_token_offset = token->offset; + parser->last_token_length = token->length; + } return 0; } @@ -135,7 +140,7 @@ noomP_Node* noomP_allocNode(noomP_Parser* parser) { noom_free(node); return 0; } - + node->previous_node = parser->last_node; parser->last_node = node; @@ -163,7 +168,7 @@ noomP_Node* noomP_parseTableLiteral(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "{", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_LCURLY; return 0; } noomP_skip(parser, &token); @@ -194,14 +199,14 @@ noomP_Node* noomP_parseTableLiteral(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "]", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_KEY; return 0; } noomP_skip(parser, &token); if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "=", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_EQUALS_AFTER_KEY; return 0; } noomP_skip(parser, &token); @@ -278,7 +283,7 @@ noomP_Node* noomP_parseTableLiteral(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "}", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RCURLY; return 0; } noomP_skip(parser, &token); @@ -300,7 +305,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_FIELD_IDENTIFIER; return 0; } noomP_skip(parser, &token); // skip the field name @@ -331,7 +336,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode if (noomP_peek(parser, &token)) return 0; // look for ] if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, "]", 1))) { // damn it :( - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_INDEX; return 0; } noomP_skip(parser, &token); // skip ] @@ -378,7 +383,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode // check for ) if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ")", 1))) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION; return 0; } @@ -448,7 +453,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode // check for ) if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ")", 1))) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION; return 0; } noomP_skip(parser, &token); @@ -601,7 +606,7 @@ noomP_Node* noomP_parseRawExpression(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, ")", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION; return 0; // unexpected } noomP_skip(parser, &token); @@ -837,7 +842,7 @@ noomP_Node* noomP_parseFunctionParameters(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "(", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_LPAREN_FOR_PARAMETERS; return 0; } noomP_skip(parser, &token); @@ -889,7 +894,7 @@ noomP_Node* noomP_parseFunctionParameters(noomP_Parser* parser) { // closing paren if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, ")", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RPAREN_FOR_PARAMETERS; return 0; } noomP_skip(parser, &token); @@ -953,7 +958,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL_FUNCTION; return 0; } noomP_skip(parser, &token); @@ -976,7 +981,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_LOCAL_FUNCTION; return 0; } noomP_skip(parser, &token); @@ -994,7 +999,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL; return 0; } noomP_skip(parser, &token); @@ -1015,7 +1020,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // the attribute is an identifier. if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LANGLE; return 0; // unexpected } noom_uint_t attr = token.offset; @@ -1028,7 +1033,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, ">", 1)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_RANGLE_TO_CLOSE_ATTRIBUTE; return 0; } noomP_skip(parser, &token); @@ -1104,7 +1109,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "then", 4)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_THEN_AFTER_EXPRESSION; return 0; // unexpected } @@ -1119,7 +1124,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_ELSE_ELSEIF_OR_END; return 0; // unexpected } @@ -1134,7 +1139,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "then", 4)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_THEN_AFTER_EXPRESSION; return 0; // unexpected } noomP_skip(parser, &token); @@ -1160,14 +1165,14 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { break; // will check for end outside the loop because else and things } else { // unexpected - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_ELSE_ELSEIF_OR_END; return 0; } } if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_IF; return 0; // unexpected } noomP_skip(parser, &token); @@ -1190,7 +1195,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "do", 2)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_DO_AFTER_EXPRESSION; return 0; // unexpected } noomP_skip(parser, &token); // skip `do` @@ -1202,7 +1207,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_WHILE; return 0; // unexpected } noomP_skip(parser, &token); // skip `end` @@ -1240,7 +1245,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { fname->source_offset = token.offset; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FUNCTION; return 0; // unex. } noomP_skip(parser, &token); @@ -1265,7 +1270,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_FIELD_IDENTIFIER; return 0; } noomP_skip(parser, &token); @@ -1282,7 +1287,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_METHOD_CALL; return 0; } noomP_skip(parser, &token); @@ -1316,7 +1321,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // remove `end` if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_FUNCTION; return 0; } noomP_skip(parser, &token); @@ -1418,7 +1423,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FOR; return 0; } noom_uint_t vname = token.offset; @@ -1468,7 +1473,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { while (1) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_VARIABLE_AFTER_COMMA_IN_FOR; return 0; } noomP_skip(parser, &token); @@ -1494,7 +1499,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // okay. that took a while. now for the in and the expressions if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "in", 2)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IN; return 0; } noomP_skip(parser, &token); @@ -1519,7 +1524,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // making this the same for all of them: do [block] end if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "do", 2)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_DO_AFTER_EXPRESSION; return 0; } noomP_skip(parser, &token); @@ -1531,7 +1536,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_FOR; return 0; } noomP_skip(parser, &token); @@ -1548,7 +1553,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_IDENTIFIER) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_GOTO; return 0; } noomP_skip(parser, &token); @@ -1578,7 +1583,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "until", 5)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_UNTIL; return 0; } noomP_skip(parser, &token); @@ -1606,7 +1611,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_END_AFTER_DO; return 0; } noomP_skip(parser, &token); @@ -1637,7 +1642,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (noomP_peek(parser, &token)) return 0; if (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "::", 2)) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_EXPECTED_COLONCOLON; return 0; } noomP_skip(parser, &token); @@ -1680,7 +1685,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (token.type != NOOML_TOKEN_IDENTIFIER && (token.type != NOOML_TOKEN_SYMBOL || !noom_streql(parser->code + token.offset, token.length, "(", 1))) { // unexpected - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_UNEXPECTED_SOMETHING1; return 0; } @@ -1689,7 +1694,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { if (item == 0) return 0; if (item->type != NOOMP_NODE_INDEX && item->type != NOOMP_NODE_GETFIELD && item->type != NOOMP_NODE_VARIABLE) { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_UNEXPECTED_SOMETHING2; return 0; // unexpected } @@ -1708,7 +1713,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { break; } } else { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_UNEXPECTED_SOMETHING3; return 0; // unexpected } } @@ -1737,12 +1742,12 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) { // this expression is now a statement. return base; // no need to eat any more. } else { - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_UNEXPECTED_SOMETHING4; return 0; // unexpected. e.g. random string or whatever } } - parser->error_state = NOOMP_ERROR_UNEXPECTED; + parser->error_state = NOOMP_ERROR_UNEXPECTED_VALUE; return 0; } @@ -1795,6 +1800,7 @@ int noomP_initParser(noomP_Parser* parser, const char* code, const char* filenam parser->code = code; parser->filename = filename; parser->lex_offset = 0; + parser->last_token_length = 0; parser->last_node = (void *)0; parser->version = version; diff --git a/src/parser.h b/src/parser.h index 2622fa9..0d6f2a7 100644 --- a/src/parser.h +++ b/src/parser.h @@ -71,13 +71,59 @@ typedef enum noomP_NodeType { typedef enum noomP_Error { NOOMP_ERROR_NONE = 0, NOOMP_ERROR_OOM, - - NOOMP_ERROR_UNEXPECTED, // TODO: maybe split into multiple for better errors? + + NOOMP_ERROR_EXPECTED_LCURLY, // table start + NOOMP_ERROR_EXPECTED_RCURLY, // table end + NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_KEY, + NOOMP_ERROR_EXPECTED_EQUALS_AFTER_KEY, + + NOOMP_ERROR_EXPECTED_FIELD_IDENTIFIER, + NOOMP_ERROR_EXPECTED_METHOD_CALL, + NOOMP_ERROR_EXPECTED_RBRACKET_AFTER_INDEX, + + NOOMP_ERROR_EXPECTED_RPAREN_AFTER_EXPRESSION, + + NOOMP_ERROR_EXPECTED_LPAREN_FOR_PARAMETERS, + NOOMP_ERROR_EXPECTED_RPAREN_FOR_PARAMETERS, + + NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL_FUNCTION, + NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FUNCTION, + NOOMP_ERROR_EXPECTED_END_AFTER_LOCAL_FUNCTION, + NOOMP_ERROR_EXPECTED_END_AFTER_FUNCTION, + + NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LOCAL, + + NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_LANGLE, + NOOMP_ERROR_EXPECTED_RANGLE_TO_CLOSE_ATTRIBUTE, + + NOOMP_ERROR_EXPECTED_THEN_AFTER_EXPRESSION, + NOOMP_ERROR_EXPECTED_ELSE_ELSEIF_OR_END, + NOOMP_ERROR_EXPECTED_END_AFTER_IF, + NOOMP_ERROR_EXPECTED_DO_AFTER_EXPRESSION, + NOOMP_ERROR_EXPECTED_END_AFTER_WHILE, + NOOMP_ERROR_EXPECTED_END_AFTER_FOR, + NOOMP_ERROR_EXPECTED_END_AFTER_DO, + NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_FOR, + NOOMP_ERROR_EXPECTED_VARIABLE_AFTER_COMMA_IN_FOR, + NOOMP_ERROR_EXPECTED_IN, + NOOMP_ERROR_EXPECTED_UNTIL, + + NOOMP_ERROR_EXPECTED_IDENTIFIER_AFTER_GOTO, + NOOMP_ERROR_EXPECTED_COLONCOLON, + + NOOMP_ERROR_UNEXPECTED_VALUE, + + // i am sorry + NOOMP_ERROR_UNEXPECTED_SOMETHING1, + NOOMP_ERROR_UNEXPECTED_SOMETHING2, + NOOMP_ERROR_UNEXPECTED_SOMETHING3, + NOOMP_ERROR_UNEXPECTED_SOMETHING4, + NOOMP_ERROR_FAKEATTRIBUTE, NOOMP_ERROR_RETURN_NOT_END, NOOMP_ERROR_FOR_WRONG_AMOUNT, - NOOMP_ERROR_LEXER = 1 << 31, // bitwise or'd with the lexer error number + NOOMP_ERROR_LEXER = 1 << 31, // bitwise or's with the lexer error number } noomP_Error; typedef struct noomP_Node { @@ -97,6 +143,9 @@ typedef struct noomP_Parser { // todo: track location in code with line/column? const char* code; const char* filename; + noom_uint_t last_token_offset; + noom_uint_t last_token_length; + noom_uint_t lex_offset; noom_uint_t error_state; -- 2.49.1