我正在尝试编写一个简单的编译器。我目前在扫描仪部分。 关于字符串标记,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已更改。我想知道是否还有另一个变量要更新,以避免程序另一部分出现意外行为。
答案 0 :(得分:1)
除非您在操作中使用yymore()
(并且显然没有这样做),否则由Flex生成的扫描仪不需要yyleng
来反映yytext
的长度。您可以通过任何方式修改yyleng
,也可以在索引0和索引yytext
之间修改yyleng-1
的内容,包括使其更短。
话虽如此,您需要了解yytext
的内容仅在下次调用yylex
之前是稳定的。在几乎所有应用程序中,尤其是如果您打算从具有超前性的解析器(例如yacc / bison生成的解析器)中使用扫描仪,您将希望扫描仪使用内容的 copy yytext
中的。特别是,由yacc / bison生成的扫描程序期望在联合体yylval
的某个成员中找到标记的语义值(即,标记字符串或从中得出的某些值),通常以指针的形式。
因此,我强烈建议您的函数将所需的字符串内容放入mystr
中,然后将其返回(而不是立即释放它),并且该操作将指针放置在解析器可以使用的位置它。只需对您的代码进行少量修改,即可使扫描器与yacc / bison生成的解析器一起使用。