Windows下Bison/Flex生成的布尔计算器EXE运行异常求助
布尔计算器运行异常的问题排查与修复
核心问题分析
- 语义动作与栈逻辑混乱:
你自定义了bool stack[]存储布尔值,但处理IDENTIFIER时错误操作Bison内部的yystack而非自己的栈;同时完全缺失标识符到布尔值的映射逻辑——程序不知道输入的变量(如a、b)是true还是false,直接操作栈会触发未定义行为。另外expression的%type被定义为<identifier>,但实际需要布尔值结果,类型不匹配导致后续printf("%s", $1)完全错误。 - 语法规则错误:
input规则的空规则会让程序无输入时直接结束,且line '\n'的动作里用字符串格式打印布尔值,类型不匹配引发错误;同时缺少表达式结果的正确输出逻辑,无法将计算后的布尔值转为"True"/"False"输出。 - 缺失关键函数实现:
仅声明yyerror但未实现,语法错误时Bison无法正确处理,可能导致程序崩溃。 - Flex错误处理不完整:
遇到无效字符时仅打印提示但未终止解析,可能导致后续解析混乱。
修正后的代码
Flex文件(boolcalc.l)
%{ #include "boolcalc.tab.h" %} %% [a-zA-Z][a-zA-Z0-9]* { yylval.identifier = strdup(yytext); return IDENTIFIER; } "and" { return AND; } "or" { return OR; } "not" { return NOT; } "true" { yylval.bool_val = true; return BOOL_LITERAL; } "false" { yylval.bool_val = false; return BOOL_LITERAL; } [ \t] ; /* 跳过空白符 */ \n { return '\n'; } . { fprintf(stderr, "Invalid character: %c\n", *yytext); exit(1); } %% int yywrap() { return 1; }
Bison文件(boolcalc.y)
%{ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #define MAX_EXPR_LENGTH 100 int yylex(); void yyerror(const char *msg) { fprintf(stderr, "Syntax error: %s\n", msg); } // 变量映射表(示例),可扩展为动态哈希表 typedef struct { char* name; bool value; } VarMap; VarMap vars[MAX_EXPR_LENGTH]; int var_count = 0; bool get_var_value(char* name) { for (int i = 0; i < var_count; i++) { if (strcmp(vars[i].name, name) == 0) { return vars[i].value; } } fprintf(stderr, "Undefined variable: %s\n", name); exit(1); } %} %union { char* identifier; bool bool_val; } %token <identifier> IDENTIFIER %token <bool_val> BOOL_LITERAL %token AND OR NOT %left OR %left AND %right NOT %type <bool_val> expression %% input: | input line '\n' { printf("%s\n", $2 ? "True" : "False"); } ; line: expression { $$ = $1; } | error { $$ = false; fprintf(stderr, "Invalid expression\n"); } ; expression: IDENTIFIER { $$ = get_var_value($1); free($1); } | BOOL_LITERAL { $$ = $1; } | expression AND expression { $$ = $1 && $2; } | expression OR expression { $$ = $1 || $2; } | NOT expression { $$ = !$2; } | '(' expression ')' { $$ = $2; } ; %% int main(int argc, char **argv) { // 预定义示例变量 vars[var_count].name = strdup("a"); vars[var_count].value = true; var_count++; vars[var_count].name = strdup("b"); vars[var_count].value = false; var_count++; printf("Boolean Calculator (supports variables a=true, b=false, true/false, and/or/not, parentheses)\n"); printf("Enter expression, press Enter to calculate:\n"); yyparse(); // 释放变量内存 for (int i = 0; i < var_count; i++) { free(vars[i].name); } printf("\nPress any key to exit..."); getchar(); getchar(); return 0; }
编译与运行说明
- 生成词法分析器:
flex boolcalc.l - 生成语法分析器:
bison -d boolcalc.y - 编译生成EXE:
gcc -o boolcalc.exe lex.yy.c boolcalc.tab.c - 运行程序:直接双击
boolcalc.exe或在控制台执行boolcalc.exe
关键改进点
- 添加布尔字面量(
true/false)支持,保留变量映射功能 - 修正语义动作,直接在语法规则中计算布尔值,无需手动维护栈
- 实现
yyerror函数,规范语法错误处理 - 修复内存泄漏问题,释放
strdup分配的内存 - 优化退出逻辑,确保程序运行后等待用户输入再关闭
内容的提问来源于stack exchange,提问作者Piotr Telok
相关产品推荐
相关产品推荐

