Variables Flex/Lex-如何知道是否声明了变量

Variables Flex/Lex-如何知道是否声明了变量,variables,yacc,flex-lexer,Variables,Yacc,Flex Lexer,我的语法允许: C→ id:=E//将值/表达式分配给变量(VAR) C→ 打印(id)//打印变量(VAR)值 要完成此操作,我的lex文件是: [a-z]{ yylval.var_index=get_var_index(yytext); return VAR; } get_var_index返回列表中变量的索引,如果该索引不存在,则创建一个。 它正在工作 问题是: 每次在lex文件上匹配变量时,它都会创建该变量的索引 我必须报告是否调用了“print(a)”,而没有声明“

我的语法允许:

C→ id:=E//将值/表达式分配给变量(VAR)

C→ 打印(id)//打印变量(VAR)值

要完成此操作,我的lex文件是:

[a-z]{
    yylval.var_index=get_var_index(yytext);
    return VAR;
}
get_var_index返回列表中变量的索引,如果该索引不存在,则创建一个。 它正在工作

问题是:

  • 每次在lex文件上匹配变量时,它都会创建该变量的索引
  • 我必须报告是否调用了“print(a)”,而没有声明“a”,这永远不会发生,因为print(a)总是创建一个指向“a”的索引*
我如何解决它?

yacc文件的一部分:

   %union {
int     int_val;
int var_index;
} 
%token <int_val>   INTEGER
%token <var_index>   VAR
...
| PRINT '(' VAR ')'{
 n_lines++;
printf("%d\n",values[$3]);
}
...
| VAR {$$ =values[$1];}
%union{
国际价值;
int-var_指数;
} 
%令牌整数
%令牌变量
...
|打印“('VAR')”{
n_行++;
printf(“%d\n”,值[$3]);
}
...
|变量{$$=值[$1];}

对于我们来说,这确实有点像计算机科学课的家庭作业问题

通常情况下,人们不会以这种方式使用bison/yacc。我们将使用bison/yacc进行解析,并生成一个解析树,然后遍历该树以执行语义检查,例如使用前检查声明等。标识符通常在一个符号表中管理,而不仅仅是一个值表,以启用其他属性,例如声明要管理的属性。正是由于这些原因,它看起来像是一个练习,而不是工具的实际应用。好啊那些免责声明被处理掉了,让我们得到一个答案

这个问题可以通过记住已经声明的内容和没有声明的内容来解决。如果不打算使用完整的符号表,那么可以使用一个简单的布尔数组来指示哪些是有效值。数组可以初始化为false,并在声明时设置为true。使用变量时可以检查此值。因为C使用整数表示布尔值,所以我们可以使用它。唯一需要改变的是野牛/yacc。您省略了声明的任何语法,但正如您所指出的,声明中必须有一些语法。我猜

%union {
int     int_val;
int var_index;
} 
int [MAX_TABLE_SIZE] declared; /* initialize to zero before starting parse */
%token <int_val>   INTEGER
%token <var_index>   VAR
...
| DECLARE '(' VAR ')' { n_lines++; declared[$3] = 1; }
...
| PRINT '(' VAR ')'{
 n_lines++;
if (declared[$3]) printf("%d\n",values[$3]);
else printf("Variable undeclared\n");
}
...
| VAR {$$ =value[$1]; /* perhaps need to show more syntax to show how VAR used */}
%union{
国际价值;
int-var_指数;
} 
声明的int[MAX_TABLE_SIZE];/*在开始解析之前初始化为零*/
%令牌整数
%令牌变量
...
|声明“('VAR')”{n_lines++;声明的[$3]=1;}
...
|打印“('VAR')”{
n_行++;
如果(声明为[$3])printf(“%d\n”,值为[$3]);
else printf(“未声明的变量\n”);
}
...
|VAR{$$=value[$1];/*可能需要显示更多语法来显示VAR是如何使用的*/}