#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. Возможно, я задам новые вопросы.