首页 > 解决方案 > flex lexer:在 yytext 更改后我应该更新哪个变量?

问题描述

我正在尝试编写一个简单的编译器。我目前在扫描仪部分。关于字符串标记,我在 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]='\0'; // 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 已更改。我想知道我是否有另一个变量要更新,以避免程序的另一部分出现一些意外行为。

标签: flex-lexer

解决方案


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

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

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


推荐阅读