refactor report

This commit is contained in:
sfja 2025-04-01 17:36:57 +02:00
parent b451548bec
commit ba643a68a3

View File

@ -30,6 +30,43 @@ typedef struct {
int col; int col;
} Loc; } Loc;
#define REPORTF_INNER(FMT, ...) \
(fprintf(stderr, "error: " FMT "\n", __VA_ARGS__))
#define REPORTF(...) REPORTF_INNER(__VA_ARGS__)
static inline void report_with_loc(const char* filename,
const char* text,
size_t text_len,
const char* msg,
Loc loc)
{
size_t line_start = loc.idx;
while (line_start > 0 && text[line_start] != '\n') {
line_start -= 1;
}
if (text[line_start] == '\n') {
line_start += 1;
}
size_t line_end = loc.idx + 1;
while (line_end < text_len && text[line_end] != '\n') {
line_end += 1;
}
const char* line = &text[line_start];
int line_len = (int)line_end - (int)line_start;
REPORTF("%s", msg);
fprintf(stderr,
" --> %s:%d:%d\n |\n%5d|%.*s\n |%*c^\n",
filename,
loc.line,
loc.col,
loc.line,
line_len,
line,
loc.col - 1,
' ');
}
typedef enum { typedef enum {
TT_Err, TT_Err,
TT_Eof, TT_Eof,
@ -136,32 +173,7 @@ static inline int lexer_skip_literal_char(Lexer* lexer)
static inline void lexer_report(Lexer* lexer, const char* msg, Loc loc) static inline void lexer_report(Lexer* lexer, const char* msg, Loc loc)
{ {
lexer->error_occured = true; lexer->error_occured = true;
report_with_loc(lexer->filename, lexer->text, lexer->text_len, msg, loc);
size_t line_start = loc.idx;
while (line_start > 0 && lexer->text[line_start] != '\n') {
line_start -= 1;
}
if (lexer->text[line_start] == '\n') {
line_start += 1;
}
size_t line_end = loc.idx + 1;
while (line_end < lexer->text_len && lexer->text[line_end] != '\n') {
line_end += 1;
}
const char* line = &lexer->text[line_start];
int line_len = (int)line_end - (int)line_start;
fprintf(stderr,
"error: %s\n --> %s:%d:%d\n |\n%5d|%.*s\n |%*c^\n",
msg,
lexer->filename,
loc.line,
loc.col,
loc.line,
line_len,
line,
loc.col - 1,
' ');
} }
Tok lexer_next(Lexer* lexer) Tok lexer_next(Lexer* lexer)
@ -513,33 +525,11 @@ static inline char* parser_ident_val(const Parser* parser, Tok tok)
static inline void parser_report(Parser* parser, const char* msg, Loc loc) static inline void parser_report(Parser* parser, const char* msg, Loc loc)
{ {
parser->error_occured = true; parser->error_occured = true;
report_with_loc(parser->lexer.filename,
size_t line_start = loc.idx; parser->lexer.text,
while (line_start > 0 && parser->lexer.text[line_start] != '\n') { parser->lexer.text_len,
line_start -= 1;
}
if (parser->lexer.text[line_start] == '\n') {
line_start += 1;
}
size_t line_end = loc.idx + 1;
while (line_end < parser->lexer.text_len
&& parser->lexer.text[line_end] != '\n') {
line_end += 1;
}
const char* line = &parser->lexer.text[line_start];
int line_len = (int)line_end - (int)line_start;
fprintf(stderr,
"error: %s\n --> %s:%d:%d\n |\n%5d|%.*s\n |%*c^\n",
msg, msg,
parser->lexer.filename, loc);
loc.line,
loc.col,
loc.line,
line_len,
line,
loc.col - 1,
' ');
} }
static inline void parser_skip_newlines(Parser* parser) static inline void parser_skip_newlines(Parser* parser)
@ -857,8 +847,7 @@ int main(int argc, char** argv)
FILE* input_fp = fopen(args.input_file, "r"); FILE* input_fp = fopen(args.input_file, "r");
if (!input_fp) { if (!input_fp) {
fprintf(stderr, REPORTF("could not open input file '%s': %s",
"error: could not open input file '%s': %s\n",
args.input_file, args.input_file,
strerror(errno)); strerror(errno));
return -1; return -1;
@ -871,8 +860,7 @@ int main(int argc, char** argv)
size_t bytes_read = fread(input_text, sizeof(char), file_size, input_fp); size_t bytes_read = fread(input_text, sizeof(char), file_size, input_fp);
fclose(input_fp); fclose(input_fp);
if (bytes_read != file_size) { if (bytes_read != file_size) {
fprintf(stderr, REPORTF("could not read input file'%s': %s",
"error: could not read input file '%s': %s\n",
args.input_file, args.input_file,
strerror(errno)); strerror(errno));
return -1; return -1;
@ -903,20 +891,20 @@ static inline Args parse_args(int argc, char** argv)
if (strcmp(argv[i], "-o") == 0) { if (strcmp(argv[i], "-o") == 0) {
i += 1; i += 1;
if (i >= argc) { if (i >= argc) {
fprintf(stderr, "error: no filename given to -o\n"); REPORTF("%s", "no filename given to -o");
exit(1); exit(1);
} }
output_file = argv[i]; output_file = argv[i];
} else { } else {
if (input_file != NULL) { if (input_file != NULL) {
fprintf(stderr, "error: multiple input files specified\n"); REPORTF("%s", "multiple input files specified");
exit(1); exit(1);
} }
input_file = argv[i]; input_file = argv[i];
} }
} }
if (input_file == NULL) { if (input_file == NULL) {
fprintf(stderr, "error: no input file\n"); REPORTF("%s", "no input file");
exit(1); exit(1);
} }
if (output_file == NULL) { if (output_file == NULL) {