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

Ren*_*tos 5 variables yacc flex-lexer

我的语法允许:

C ?id := E // 将值/表达式赋给变量 (VAR)

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

为了完成它,我的 lex 文件是:

[a-z]{
    yylval.var_index=get_var_index(yytext);
    return VAR;
}
Run Code Online (Sandbox Code Playgroud)

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];}
Run Code Online (Sandbox Code Playgroud)

Bri*_*汤莱恩 2

这看起来确实有点像我们要做的计算机科学课作业问题。

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

通过记住已声明的内容和未声明的内容即可解决该问题。如果不打算使用完整的符号表,则可以使用一个简单的布尔值数组来指示哪些是有效值。该数组可以初始化为false并在声明时设置为true。使用变量时可以检查该值。由于C使用整数表示布尔值,我们可以使用它。唯一需要的更改是在 bison/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 */}
Run Code Online (Sandbox Code Playgroud)