error: add proper error strings

Co-authored-by: tema5002 <tema5002@tuta.io>
Reviewed-on: #3
Co-committed-by: tema5002 <tema5002@tuta.io>
This commit was merged in pull request #3.
This commit is contained in:
2026-05-24 12:08:07 +02:00
committed by Blendi
parent 0d6b1c6729
commit fbbe2e8285
9 changed files with 329 additions and 61 deletions

3
.gitignore vendored
View File

@@ -3,4 +3,5 @@
/zig-out
.idea
noom
noom.*
noom.*
Makefile

View File

@@ -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',

150
src/error.c Normal file
View File

@@ -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;
}

5
src/error.h Normal file
View File

@@ -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);

View File

@@ -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 <stdlib.h> // TODO: remove
void* noom_alloc(noom_uint_t size) {

View File

@@ -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);

View File

@@ -1,7 +1,7 @@
#include <stdio.h> // 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 <close> = {'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;
}

View File

@@ -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;

View File

@@ -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;