Я пытаюсь написать простой компилятор. Я в настоящее время в части сканера. Что касается токена строки, у меня есть следующее правило в файле 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 изменился. Интересно, есть ли у меня другая переменная для обновления, чтобы избежать неожиданного поведения в другой части программы.
Если вы не используете yymore()
в своем действии (а, очевидно, вы этого не делаете), сгенерированный flex-сканер не требует yyleng
для отражения длины yytext
. Вы можете изменить yyleng
любым способом или изменить содержимое yytext
между индексом 0 и индексом yyleng-1
, в том числе сделать его короче.
Сказав это, вы должны знать, что содержимое yytext
стабильно только до следующего звонка yylex
. Почти во всех приложениях, особенно если вы планируете использовать сканер из синтаксического анализатора с опережением (например, синтаксический анализатор, созданный yacc/bison), вам потребуется, чтобы сканер использовал копировать содержимого yytext
. В частности, сканеры, сгенерированные yacc/bison, ожидают найти семантическое значение токенов (то есть строку токена или какое-то производное от нее значение) в некотором члене объединения yylval
, как правило, в виде указателя.
Поэтому я настоятельно рекомендую, чтобы ваша функция поместила желаемое содержимое строки в mystr
, а затем вернула его (вместо того, чтобы сразу освобождать его), и чтобы действие поместило указатель в место, где анализатор может его использовать. Это потребует лишь незначительной модификации вашего кода и сделает сканер пригодным для использования с синтаксическим анализатором, созданным yacc/bison.
Большое спасибо за ответ. Насчет бизонов вы правы. Это мой следующий шаг по созданию AST. Возможно, я буду задавать новые вопросы.