使用flex和bison开发6502汇编器时,$1为何被赋值为整个匹配内容?
6502汇编器解析异常问题排查
我正在学习用Flex和Bison开发6502汇编器,当前的Flex令牌定义如下:
[a-zA-Z]{3} { yylval.a = yytext; return MNEMONIC; } \$[0-9a-fA-F]{2} { yylval.zp = strtol(yytext + 1, NULL, 16); return ZEROPAGE; }
对应的Bison语法规则:
program: program expression '\n' { } | program '\n' { } | program error '\n' { yyerrok; } | /* NOTHING */ ; expression: MNEMONIC { printf("I: %s\n", $1); } | MNEMONIC ZEROPAGE { printf("ZP: '%s' %d\n", $1, $2); } ;
按预期,解析LDA $99时,MNEMONIC ZEROPAGE规则应该把LDA存入$1,$99的数值存入$2,但实际打印时$1的值变成了LDA $99,请问哪里出错了?
问题原因与解决方法
核心问题出在Flex的yytext是指向内部缓冲区的指针,并非独立分配的内存。你直接将yytext赋值给yylval.a,当Flex继续解析下一个令牌($99)时,内部缓冲区会被覆盖改写,导致Bison中$1指向的内容已经不是最初的LDA,而是后续扫描后的缓冲区内容(比如整行的LDA $99)。
解决方法是为yylval.a分配独立内存,复制yytext的内容,使用strdup函数即可:
[a-zA-Z]{3} { yylval.a = strdup(yytext); return MNEMONIC; }
注意:使用strdup会在堆上分配内存,后续需要手动调用free释放,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Bart Friederichs
相关产品推荐
相关产品推荐

