尽管逐个字符读取,但输入缓冲区溢出

Input buffer overflow in spite of reading character by character

为了克服lex中输入缓冲区溢出的问题,我写了代码,每当我希望看到一个长字符串时,一个字符一个字符地读取传入的流,但是,仍然得到输入缓冲区溢出的错误,can' t 扩大缓冲区,因为扫描器使用 REJECT

代码片段:

<STATE> {identifier} {
    string str = yytext; 
    if(str == "ExpectedStr")
       handleLongStr(str);
    copyString(yylval.str, str);
    return IDENTIFIER; 
}

void handleLongStr(string &str)
{
  str.clear();
  char ch;
  while((ch = yyinput()) != '\n')
    str.push_back(ch);
  unput(ch); 
}

yyinput 用尽了缓冲区中的缓冲区 space,尽管它不会让您恢复从 yytext 读取的数据。我想出的这种行为的唯一原因是它允许你 unput() 与你 input() 一样多的字符而不会破坏 yytext,这在以下情况下很有用您正在使用 input() 作为查看下一个输入的方式。

无论出于何种原因,这意味着您不能使用 yyinput 来避免缓冲区重新分配。所以你需要做下一个最好的事情:将长令牌分成更小的部分。例如,您可以这样做:

%%
  /* Variable is local to a call to yylex */
  std::string longtoken;

<STATE>{identifier}  {
  /* Personally I'd prefer to use a regex pattern than an if here */
  if (is_long_prefix(yytext)) {
    longtoken.clear();
    BEGIN(STATE_LONG_IDENTIFIER);
  }
  else {
    yylval.str = strdup(yytext);
    return IDENTIFIER;
  }
  // ...
}

<STATE_LONG_IDENTIFIER>{
   /* Here we handle subtokens of up to 100 characters. The number
    * is arbitrary, but the nature of flex is that the resulting DFA
    * will have one state per repetition, and large repetitions create
    * a lot of states.
    */
   .{1,100} { longtoken.append(yytext, yyleng); }
   \n       { yylval.str = strdup(longtoken.c_str(););
              BEGIN(STATE);
              return IDENTIFIER;
            }
   <<EOF>>  { error("Unterminated long identifier"); }
}