我正在尝试使用lex和yacc构建一个非常简单的语言 它可以通过赋值只有一个int变量,如
a = 1
它可以像这样打印变量
print a
只有在变量名称匹配时才必须打印该值,否则必须打印错误消息
我的lex文件是
%{
#include "y.tab.h"
#include <stdlib.h>
void yyerror(char *);
%}
letter [A-z]
digit [0-9]
%%
"print" {return PRINT;}
{letter}+ { yylval.id = yytext;return IDENTIFIER;}
{digit}+ { yylval.num = atoi(yytext);return NUMBER; }
[=\n] return *yytext;
[ \t] ; /* skip whitespace */
. yyerror("invalid character");
%%
int yywrap(void) {
return 1;
}
我的yacc文件是
%{
#include <stdio.h>
#include <string.h>
int yylex(void);
void yyerror(char *);
int value;
char *key;
void print_var(char *s);
%}
%union {char *id;int num;}
%start exp
%token <id> IDENTIFIER
%token <num> NUMBER
%token PRINT
%%
exp: IDENTIFIER '=' NUMBER '\n' {key = $1;value = $3;}
|PRINT IDENTIFIER '\n' {print_var($2);}
|exp IDENTIFIER '=' NUMBER '\n' {key = $2;value = $4;}
|exp PRINT IDENTIFIER '\n' {print_var($3);}
;
%%
void yyerror(char *s) {
fprintf(stderr, "%s\n", s);
}
void print_var(char *s){
if(strcmp(s,key) == 0){
printf("%s:%d\n",key,value);
}else{
printf("%s not found\n",s);
}
}
int main(void) {
yyparse();
return 0;
}
但是当我输入类似这样的内容时
a = 1
print a
我收到以下错误 一个 找不到
答案 0 :(得分:0)
一旦你的lex程序返回到yacc(或基本上,在规则之外的任何地方),yytext
值不一定是不受影响的。您应该使用id
或其他内容在yytext
中对字符串进行复制,而不是将strdup
指向yytext
。< / p>
21.3 A Note About yytext And Memory 中的flex手册中提到了这一点。
在你的语法中,这是唯一显示的规则:
exp: IDENTIFIER '=' NUMBER '\n' {key = $1;value = $3;}
|PRINT IDENTIFIER '\n' {print_var($2);}
|exp IDENTIFIER '=' NUMBER '\n' {key = $2;value = $4;}
|exp PRINT IDENTIFIER '\n' {print_var($3);}
;
它将指针复制到全局变量key
(再次,这会遇到内存损坏问题)并打印$2
标识符。如果您在lex程序中分配了yytext
的副本,则可以在print_var
中安全地释放该副本。 key
的两个赋值应该替换为设置key
的函数的调用,同时检查它是否已设置,例如,
void set_key(const char *value)
{
if (key != 0)
free(key);
key = strdup(value);
}
这样,一次只能分配一份yytext
- 一份微不足道的记忆。