vety-language/parser/error.c

97 lines
2.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//
// Created for error reporting
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parser.h"
#include "../utils/file.h"
// ANSI 转义序列颜色代码
#define ANSI_COLOR_RED "\033[31m"
#define ANSI_COLOR_YELLOW "\033[33m"
#define ANSI_COLOR_CYAN "\033[36m"
#define ANSI_COLOR_RESET "\033[0m"
// 获取指定行的代码
static char* get_line_at(const char* source, int line_number) {
if (source == NULL || line_number <= 0) return NULL;
int current_line = 1;
const char* line_start = source;
const char* p = source;
// 找到指定行的起始位置
while (*p != '\0') {
if (current_line == line_number) {
line_start = p;
break;
}
if (*p == '\n') {
current_line++;
}
p++;
}
// 如果没找到指定行返回NULL
if (current_line != line_number) return NULL;
// 找到行的结束位置
p = line_start;
while (*p != '\0' && *p != '\n') p++;
// 复制行内容
int length = p - line_start;
char* line = (char*)malloc(length + 1);
if (line == NULL) return NULL;
strncpy(line, line_start, length);
line[length] = '\0';
return line;
}
// 在指定位置打印错误指示箭头
static void print_error_indicator(int column) {
// 打印错误指示箭头
fprintf(stderr, " | " ANSI_COLOR_RED);
for (int i = 1; i < column; i++) {
fprintf(stderr, "~");
}
// 打印错误指示箭头
fprintf(stderr, "^" ANSI_COLOR_RESET "\n");
}
// 在当前token位置报告错误
void parser_error_at_current(Parser* parser, const char* message) {
parser_error_at(parser, &parser->current_token, message);
exit(0);
}
void parser_error_at(Parser* parser, Token* token, const char* message) {
if (parser->had_error) return;
// 添加错误到errors数组
parser->error_count++;
parser->errors = realloc(parser->errors, sizeof(*parser->errors) * parser->error_count);
parser->errors[parser->error_count - 1].message = strdup(message);
parser->errors[parser->error_count - 1].line = token->line;
parser->errors[parser->error_count - 1].column = token->column;
// 打印错误位置和消息
fprintf(stderr, ANSI_COLOR_CYAN "%s" ANSI_COLOR_RESET ":"
ANSI_COLOR_YELLOW "%d:%d" ANSI_COLOR_RESET ": "
ANSI_COLOR_RED "Syntax error: %s" ANSI_COLOR_RESET "\n",
parser->filename, token->line, token->column, message);
char* source = read_file(parser->filename);
if (source != NULL) {
char* line = get_line_at(source, token->line);
if (line != NULL) {
fprintf(stderr, "%4d | %s\n", token->line, line);
print_error_indicator(token->column);
free(line);
}
free(source);
}
}