无法灵活识别关键字字符串

时间:2018-04-26 16:00:38

标签: c flex-lexer

我正在尝试使用flex为C编程语言编写语法高亮显示。我的问题是当程序到达任何关键字模式时程序停止读取输入并以某种方式卡住。 (关键字定义规则是规则部分中定义的第一个规则)我不知道为什么会发生这种情况,关键字的正则表达式似乎很好。

这是代码:

%{
#include <stdio.h>
#include <string.h>
enum token_type{
    KEYWORD,
    ID,
    INTEGER,
    FLOAT_NUMBER,
    SOME_CHARACTER,
    SOME_STRING,
    SPECIAL_CHARACTER,
    COMMENT,
    MULTILINE_COMMENT,
    ENDING_DOUBLE_QUOTE
};
int yy_left_integer;
double yy_left_double;
char* yy_left_string;

%}

%x in_multiline_comment
%x in_string
%option noyywrap
%%

"auto"|"int"|"const"|"short"|"break"|"long"|"continue"|"double"|"struct"|"float"|"unsigned"|"else"|"switch"|"for"|"signed"|"case"|"register"|"default"|"sizeof"|"char"|"return"|"do"|"static"|"void"|"enum"|"typedef"|"goto"|"volatile"|"extern"|"union"|"if"|"while"   {yy_left_string = yytext; return KEYWORD;} 

"/*" BEGIN(in_multiline_comment);

"//"[^ \n]* {yy_left_string = yytext; return COMMENT;}

[a-zA-Z_][a-zA-Z0-9_]* {yy_left_string = yytext; return ID;}

(("0x")[+-]?[0-9A-F]+) | ([+-]?[0-9]+) {yy_left_integer = atoi(yytext); return INTEGER;}

([+-]?[0-9]*\.[0-9]+)(E[+-]?[0-9]+)? {yy_left_double = atof(yytext); return FLOAT_NUMBER;}

\" {BEGIN(in_string);}

<in_string>{
[\\.?] {yy_left_string = yytext; return SPECIAL_CHARACTER;}
[^\"\\]* {strncpy(yy_left_string, yytext + 1, strlen(yytext -1)); return SOME_STRING;}
\"  {yy_left_string = yytext; BEGIN(INITIAL); return ENDING_DOUBLE_QUOTE;}
}

\\(.?) {yy_left_string = yytext; return SPECIAL_CHARACTER;}

\'[^ \']?\' {yy_left_string = yytext; return SOME_CHARACTER;}


<in_multiline_comment>{
    "*/" {yy_left_string = yytext; BEGIN(INITIAL); return MULTILINE_COMMENT;}
    ^[*\n]+
    "*"
    "\n"    yylineno++;
}
[\n] {yylineno++;}
[\t\v] {}
. {yy_left_string = yytext;}
%%
int main(int argc, char** argv)
{
    int token;
    if(argc > 1){
        if(!(yyin = fopen(argv[1], "r"))){
        perror(argv[1]);
        return 1;
        }

    }  
    FILE* highlighted_html_file = fopen("highlighted.html", "w");
    if(highlighted_html_file == NULL){
        printf("error opening file\n");
        return 1;
    }
    while(token = yylex()){
        if(token == KEYWORD){fprintf(highlighted_html_file,"<b><span style=\"color:Blue\">%s</span> </b>", yy_left_string);}
        else if(token == ID){fprintf(highlighted_html_file,"<span style = \"color:Orange\"> %s </span>", yy_left_string);}
        else if(token == INTEGER){fprintf(highlighted_html_file, "<span style = \"color:Purple\"> %d </span>", yy_left_integer);}
        else if(token == FLOAT_NUMBER){fprintf(highlighted_html_file, "<i><span style = \"color:Purple\">%f</span></i>", yy_left_double);}
        else if(token == SPECIAL_CHARACTER){fprintf(highlighted_html_file,  "<span style = \"color:LightBlue\"> \"%s </span>", yy_left_string);}
        else if(token == SOME_STRING){fprintf(highlighted_html_file, "<span style = \"color:Red\"> \"%s", yy_left_string);}
        else if(token == ENDING_DOUBLE_QUOTE){fprintf(highlighted_html_file,  "<span style = \"color:Red>\"</span>");}
        else if(token == SOME_CHARACTER){fprintf(highlighted_html_file,  "<span style = \"color:LightRed\"> \"%s </span>", yy_left_string);}
        else if(token == COMMENT || token == MULTILINE_COMMENT){fprintf(highlighted_html_file, "<span style = \"color:Grey\"> %s</span>", yy_left_string);}
        else {fprintf(highlighted_html_file, "%s", yy_left_string);}
    }
}  

2 个答案:

答案 0 :(得分:1)

枚举token_type KEYWORD的值为0,如果令牌为0,则循环终止。 变化

enum token_type{
    KEYWORD,

是:

enum token_type{
    KEYWORD = 1,

这个问题就会消失。

答案 1 :(得分:0)

我知道你不应该只使用变量赋值将“yytext”复制到变量中。你应该使用strdup或类似的东西来复制它。

此外,以下代码很糟糕:

<in_string>{
[\\.?] {yy_left_string = yytext; return SPECIAL_CHARACTER;}
[^\"\\]* {strncpy(yy_left_string, yytext + 1, strlen(yytext -1)); return SOME_STRING;}

意味着什么?这意味着如果您处理\ a,那么您将执行“yy_left_string = yytext”。 I. e。现在yy_left_string是“char *”,指向flex内部的一些内存。让我们假设您处理普通的char,比如z。现在你做“strncpy(yy_left_string,...)”。所以,你将yy_left_string(即指向一些flex内部存储器的指针!!!)传递给strncpy。因此,您将一些数据写入flex内部。这可以打破一切。你甚至不知道yy_left_string是否有足够的空间来存储所有yytext字符。因此,您很容易陷入细分错误。

你了解C中的记忆是如何工作的吗?你了解指针等吗?你了解C中的字符串处理吗?

另外,我不确定我提供的有关yytext的所有信息。 I. e。我不确定yytext是否真的不应该存储在你的vars中。而且我不确定写入yytext指向的内存是不错的主意。阅读flex docs以获取所有这些信息。

(另外,你的标签“flex”是错误的,因为它与其他flex有关。)