standardising error messages

This commit is contained in:
ghostie 2025-07-26 19:18:36 -05:00
parent 8571900105
commit f50774f279
7 changed files with 133 additions and 27 deletions

View File

@ -5,7 +5,7 @@ RM=rm
CFLAGS=-Wall -Werror -std=gnu99 -O0 -g
LIBS=
FILES=build/main.o build/lexer.o build/token.o build/parser.o build/model.o build/utils/vector.o build/utils/buffer.o
FILES=build/main.o build/lexer.o build/token.o build/parser.o build/model.o build/error.o build/utils/vector.o build/utils/buffer.o
OUT=bin/pinky.out
all: $(FILES)
@ -32,6 +32,10 @@ build/model.o: src/model.c
@$(ECHO) "CC\t\t"$<
@$(CC) $(CFLAGS) $< -c -o $@ $(LIBS)
build/error.o: src/error.c
@$(ECHO) "CC\t\t"$<
@$(CC) $(CFLAGS) $< -c -o $@ $(LIBS)
build/utils/vector.o: src/utils/vector.c
@$(ECHO) "CC\t\t"$<
@$(CC) $(CFLAGS) $< -c -o $@ $(LIBS)

25
src/error.c Normal file
View File

@ -0,0 +1,25 @@
#include "error.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "colors.h"
#include "utils/buffer.h"
void
display_error (unsigned int lineno, const char *fmt, ...)
{
va_list args;
va_start (args, fmt);
struct buffer buf = buffer_create ();
buffer_printf (&buf, COLOR_RED "[Line %d] Error: %s.\n" COLOR_WHITE, lineno,
fmt);
vprintf (buffer_get (&buf), args);
buffer_free (&buf);
va_end (args);
exit (1);
}

6
src/error.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef __ERROR_H
#define __ERROR_H
void display_error (unsigned int lineno, const char *fmt, ...);
#endif

View File

@ -1,13 +1,14 @@
#include "lexer.h"
#include "token.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "error.h"
#include "token.h"
/* helper functions */
char
advance (struct lexer *l)
@ -133,14 +134,9 @@ handle_string (char quote, struct lexer *l)
while (peek (l) != quote && l->cur < buffer_length (l->source))
advance (l);
if (l->cur >= buffer_length (l->source))
{
/* we reached the end of the file without closing the string */
fprintf (stderr,
"lexer.c: handle_string - unterminated string on line %d\n",
l->line);
exit (EXIT_FAILURE);
}
if (l->cur >= buffer_length (l->source))
display_error (l->line, "Unterminated string");
advance (l); /* consume the closing quote */
@ -300,8 +296,7 @@ lexer_lex (struct lexer *l)
else if (isalpha (c) || c == '_')
handle_identifier (l);
else
fprintf (stderr, "lexer_lex: unexpected character `%c' at line %d\n",
c, l->line);
display_error (l->line, "Unexpected character `%c'", c);
}
}

View File

@ -1,8 +1,10 @@
#include "parser.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "error.h"
#include "model.h"
/* prototypes */
@ -36,16 +38,6 @@ struct expression *expression (struct parser *p);
/* return (struct token *)vector_at (p->curr, p->tokens); */
/* } */
/* static _Bool */
/* expect (enum token_type type, struct parser *p) */
/* { */
/* if (!p) */
/* return 0; */
/* struct token *tok = (struct token *)vector_at (p->curr, p->tokens); */
/* return tok->type == type; */
/* } */
static struct token *
prev_tok (struct parser *p)
{
@ -58,6 +50,29 @@ prev_tok (struct parser *p)
return (struct token *)vector_at (p->curr - 1, p->tokens);
}
/* static _Bool */
/* expect (enum token_type type, struct parser *p) */
/* { */
/* if (!p) */
/* return 0; */
/* struct token *tok = (struct token *)vector_at (p->curr, p->tokens); */
/* if (!tok) */
/* { */
/* struct token *prev = prev_tok (p); */
/* display_error (prev->line, "Found `%s' at the end of
* parsing"); */
/* } */
/* if (tok->type != type) */
/* display_error (tok->line, "Expected token of type `%s', found
* `%s'", */
/* token_type_to_str
* (type), token_type_to_str (tok->type)); */
/* return 1; */
/* } */
static struct token *
match (enum token_type type, struct parser *p)
{
@ -87,11 +102,8 @@ primary (struct parser *p)
if ((tok = match (TOK_LPAREN, p)))
{
struct expression *expr = expression (p);
if (!(tok = match (TOK_RPAREN, p)))
{
fprintf (stderr, "Error: `)' expected at line %d.\n", tok->line);
exit (1);
}
if (!match (TOK_RPAREN, p))
display_error (tok->line, "`)' expected");
return expression_create_grouping (expr);
}
return NULL; /* unmatched */

View File

@ -46,3 +46,64 @@ token_free_heap (struct token *t)
buffer_free (&t->lexeme);
free (t);
}
/* utils */
/* clang-format off */
const char *token_type_to_str(enum token_type type) {
switch (type) {
case TOK_LPAREN: return "TOK_LPAREN";
case TOK_RPAREN: return "TOK_RPAREN";
case TOK_LCURLY: return "TOK_LCURLY";
case TOK_RCURLY: return "TOK_RCURLY";
case TOK_LSQUAR: return "TOK_LSQUAR";
case TOK_RSQUAR: return "TOK_RSQUAR";
case TOK_COMMA: return "TOK_COMMA";
case TOK_DOT: return "TOK_DOT";
case TOK_PLUS: return "TOK_PLUS";
case TOK_MINUS: return "TOK_MINUS";
case TOK_STAR: return "TOK_STAR";
case TOK_SLASH: return "TOK_SLASH";
case TOK_CARET: return "TOK_CARET";
case TOK_MOD: return "TOK_MOD";
case TOK_COLON: return "TOK_COLON";
case TOK_SEMICOLON: return "TOK_SEMICOLON";
case TOK_QUESTION: return "TOK_QUESTION";
case TOK_NOT: return "TOK_NOT";
case TOK_GT: return "TOK_GT";
case TOK_LT: return "TOK_LT";
case TOK_EQ: return "TOK_EQ";
case TOK_GE: return "TOK_GE";
case TOK_LE: return "TOK_LE";
case TOK_NE: return "TOK_NE";
case TOK_EQEQ: return "TOK_EQEQ";
case TOK_ASSIGN: return "TOK_ASSIGN";
case TOK_GTGT: return "TOK_GTGT";
case TOK_LTLT: return "TOK_LTLT";
case TOK_IDENTIFIER:return "TOK_IDENTIFIER";
case TOK_STRING: return "TOK_STRING";
case TOK_INTEGER: return "TOK_INTEGER";
case TOK_FLOAT: return "TOK_FLOAT";
case TOK_IF: return "TOK_IF";
case TOK_THEN: return "TOK_THEN";
case TOK_ELSE: return "TOK_ELSE";
case TOK_TRUE: return "TOK_TRUE";
case TOK_FALSE: return "TOK_FALSE";
case TOK_AND: return "TOK_AND";
case TOK_OR: return "TOK_OR";
case TOK_WHILE: return "TOK_WHILE";
case TOK_DO: return "TOK_DO";
case TOK_FOR: return "TOK_FOR";
case TOK_FUNC: return "TOK_FUNC";
case TOK_NULL: return "TOK_NULL";
case TOK_END: return "TOK_END";
case TOK_PRINT: return "TOK_PRINT";
case TOK_PRINTLN: return "TOK_PRINTLN";
case TOK_RET: return "TOK_RET";
default: return "UNKNOWN_TOKEN";
}
}
/* clang-format on */

View File

@ -77,4 +77,7 @@ struct token *token_create_heap (enum token_type type, unsigned int line,
void token_free (struct token *t);
void token_free_heap (struct token *t);
/* utils */
const char *token_type_to_str (enum token_type type);
#endif