如何将PackCC的输入从标准输入(stdin)改为读取文件内容?
解决PackCC忽略传入缓冲区、仍读取标准输入的问题
你的核心问题在于PackCC自动生成的解析器默认绑定了标准输入(stdin),仅把缓冲区传入上下文是不够的——必须修改PEG定义和解析器调用逻辑,强制让解析器从你提供的缓冲区读取数据。
关键修正步骤
1. 修改PEG文件,指定自定义输入源
在你的.peg文件中,需要替换默认的输入读取逻辑,改用辅助数据(缓冲区)作为输入源。通过%input指令覆盖默认行为:
%{ #include <string.h> // 自定义读取函数:从上下文的缓冲区取字符 static int read_from_buffer(scheme_context_t* ctx) { if (ctx->pos >= ctx->buffer_len) { return EOF; // 缓冲区读取完毕 } return ctx->buffer[ctx->pos++]; } %} // 告诉PackCC用自定义函数替代默认的stdin读取 %input{ read_from_buffer(ctx) } // 你的语法规则继续写在这里 scheme <- ...
2. 完善上下文结构体定义
确保scheme_context_t包含缓冲区、读取位置和长度三个关键字段:
typedef struct { const char* buffer; size_t buffer_len; size_t pos; // 当前读取到的位置 } scheme_context_t;
3. 修正scheme_create初始化逻辑
初始化上下文时要正确设置缓冲区参数:
scheme_context_t* scheme_create(const char* buffer) { scheme_context_t* ctx = malloc(sizeof(scheme_context_t)); ctx->buffer = buffer; ctx->buffer_len = strlen(buffer); ctx->pos = 0; // 从缓冲区起始位置开始读取 return ctx; }
4. 修复文件读取的潜在问题
你原来用fgets只能读取一行数据,若文件有多行会丢失内容,建议改为读取整个文件:
static void parser_read(const char *contents, int mode) { FILE *fp = fopen(contents, "r"); if (fp == NULL) { perror("Error opening file"); exit(EXIT_FAILURE); } // 获取文件大小 fseek(fp, 0, SEEK_END); long file_size = ftell(fp); fseek(fp, 0, SEEK_SET); // 分配足够的缓冲区(+1用于字符串终止符) char* buffer = malloc(file_size + 1); if (!buffer) { perror("Failed to allocate buffer"); fclose(fp); exit(EXIT_FAILURE); } // 读取整个文件内容 size_t read_bytes = fread(buffer, 1, file_size, fp); buffer[read_bytes] = '\0'; fclose(fp); scheme_context_t *ctx = scheme_create(buffer); ast *my_ast = NULL; scheme_parse(ctx, &my_ast); ast_print(my_ast); eval_ast(my_ast); // 释放资源 free(buffer); free(ctx); // 记得释放AST相关内存 }
无效原因说明
PackCC生成的解析器默认会调用标准输入的读取函数(比如fgetc(stdin)),不会自动识别你传入的上下文缓冲区。必须通过%input指令在PEG文件中显式指定自定义读取逻辑,才能让解析器从你的缓冲区取数据,而非标准输入。
内容的提问来源于stack exchange,提问作者TheSinisterStone
相关产品推荐
相关产品推荐

