97 lines
2.8 KiB
C
97 lines
2.8 KiB
C
//
|
||
// 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);
|
||
}
|
||
} |