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

时间:2014-12-04 01:04:03

标签: variables yacc flex-lexer

我的语法允许:

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

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

要完成它,我的lex文件是:

[a-z]{
    yylval.var_index=get_var_index(yytext);
    return VAR;
}

get_var_index返回列表中变量的索引,如果它不存在则会创建一个。 它正在运作!

问题是:

  • 每次在lex文件中匹配变量时,它都会为该变量创建一个索引。
  • 我必须报告是否打印(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];}

1 个答案:

答案 0 :(得分:1)

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

通常情况下,人们不会以这种方式使用野牛/ yacc。人们可以使用bison / yacc进行解析,然后制作一个解析树然后走路来执行语义检查,例如在使用前检查声明等等。标识符通常在符号表中进行管理,而不仅仅是一个值表,以启用其他属性,例如声明进行管理。出于这些原因,它看起来像是一种练习,而不是工具的实际应用。好;那些免责声明被处理掉了,让我们回答。

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