flex lexer: какую переменную я должен обновить после изменения yytext?

#flex-lexer

#flex-lexer

Вопрос:

Я пытаюсь написать простой компилятор. В настоящее время я нахожусь в части сканера. Что касается строкового токена, у меня есть следующее правило в файле 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]=''; // 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:

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

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

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

Комментарии:

1. Большое спасибо за ответ. Что касается bison, вы правы. Это мой следующий шаг по созданию AST. Возможно, я задам новые вопросы.