flex lexer: какую переменную мне следует обновить после изменения yytext? - PullRequest
0 голосов
/ 10 апреля 2019

Я пытаюсь написать простой компилятор.Я в настоящее время нахожусь в части сканера.Что касается строкового токена, у меня есть следующее правило в файле 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 изменился. Интересно, есть ли у меня другая переменная для обновления, чтобы избежать неожиданного поведения в другой части программы.

1 Ответ

1 голос
/ 10 апреля 2019

Если вы не используете yymore() в своих действиях (и, очевидно, нет), сканеру, сгенерированному сгибанием, не требуется yyleng для отражения длины yytext.Вы можете изменить yyleng любым способом или изменить значение yytext между индексом 0 и индексом yyleng-1, в том числе сделать его короче.

Сказав это, вы должны знать, чтосодержимое yytext стабильно только до следующего вызова yylex.Почти во всех приложениях, особенно если вы планируете использовать сканер из анализатора с упреждением (например, анализатор, созданный с помощью yacc / bison), вы захотите, чтобы сканер использовал копию содержимогоyytext.В частности, сканеры, сгенерированные yacc / bison, ожидают найти семантическое значение токенов (то есть строку токена или некоторое значение, полученное из нее) в некотором члене объединения yylval, обычно в форме указателя.

Поэтому я настоятельно рекомендую, чтобы ваша функция поместила желаемое содержимое строки в mystr, а затем вернула его (вместо того, чтобы немедленно его освободить), и чтобы действие поместило указатель в место, где анализатор может его использовать,Это потребует лишь незначительных изменений в вашем коде и сделает сканер пригодным для использования с парсером, сгенерированным yacc / bison.

...