flex 词法分析器:yytext 更改后我应该更新哪个变量?

flex lexer : Which variable should I update after yytext change?

我正在尝试编写一个简单的编译器。我目前在扫描仪部分。 关于字符串标记,我在 flex 文件中有以下规则:

\"([^\\n]|\.)*\" { clean_string(); return TK_STRING; }

它完美地工作(这不是问题)。 clean_string 调用函数删除前导和尾随 " 并将 \n 和 \t 转换为相应的 ascii 字符。

int clean_string () {
  char * mystr;

  mystr=strdup(yytext+1) ; // copy yytext and remove leading "
  if (! mystr) return 1;
  mystr[yyleng-2]='[=10=]'; // remove trailing "
  for (int i=0, j=0; i<=strlen(mystr); i++, j++) { // "<=" and not "<" to get /0, i : mystr indice and j : yytext indice
    if (mystr[i]=='\') {
      i++;
      if (mystr[i]=='n')        yytext[j]='\n';
      else if (mystr[i]=='t')   yytext[j]='\t';
      else yytext[j]=mystr[i];
    }
    else yytext[j]=mystr[i];
  }
  yyleng=strlen(yytext);
  free(mystr);
  return 0 ;
}

它也很完美。

我的问题如下:
在函数结束时,我更新了 yyleng,因为 yytext 已更改。我想知道我是否有另一个变量要更新以避免程序另一部分出现意外行为。

除非您在操作中使用 yymore()(显然您没有),否则 flex 生成的扫描器不需要 yyleng 来反映 yytext 的长度。您可以以任何方式修改yyleng,也可以修改索引0和索引yyleng-1之间的yytext的内容,包括使其更短。

话虽如此,您需要注意 yytext 的内容只有在您下次调用 yylex 时才会稳定。在几乎所有应用程序中,特别是如果您计划使用具有前瞻性的解析器(例如由 yacc/bison 生成的解析器)的扫描器,您将希望扫描器使用 copy yytext 的内容。特别是,yacc/bison 生成的扫描器希望在联盟 yylval 的某些成员中找到令牌的语义值(即令牌字符串或从中派生的某些值),通常以指针。

所以我强烈建议您的函数将所需的字符串内容放入 mystr 然后 return 它(而不是立即释放它),并且该操作将指针放在解析器可以使用它的地方。这将只需要对您的代码进行微小的修改,并且将使扫描器可以与 yacc/bison 生成的解析器一起使用。