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);
 | 
						||
    }
 | 
						||
} |