standardising error messages
This commit is contained in:
parent
8571900105
commit
f50774f279
6
Makefile
6
Makefile
@ -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
25
src/error.c
Normal 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
6
src/error.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef __ERROR_H
|
||||
#define __ERROR_H
|
||||
|
||||
void display_error (unsigned int lineno, const char *fmt, ...);
|
||||
|
||||
#endif
|
17
src/lexer.c
17
src/lexer.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
42
src/parser.c
42
src/parser.c
@ -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 */
|
||||
|
61
src/token.c
61
src/token.c
@ -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 */
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user