не может согнуться, чтобы распознать строки ключевых слов - PullRequest
0 голосов
/ 26 апреля 2018

Я пытаюсь написать подсветку синтаксиса для языка программирования C, используя flex. Моя проблема в том, что программа перестает читать ввод, когда он достигает какой-либо комбинации ключевых слов и как-то застревает. (правило определения ключевого слова - самое первое правило, определенное в разделе правил). Я понятия не имею, почему это происходит, и регулярное выражение для ключевых слов, похоже, отлично.

это код:

%{
#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 голосов
/ 27 апреля 2018

Насколько я знаю, вы не должны копировать «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". И. е. теперь yy_left_string - "char *", указывающая на некоторую внутреннюю память для гибкости. Давайте предположим, что вы обрабатываете обычный символ, скажем, z. Теперь вы делаете "strncpy (yy_left_string, ...)". Итак, вы передаете yy_left_string (т.е. указатель на некоторую внутреннюю память flex!) В strncpy. Итак, вы записываете некоторые данные во флекс. Это может сломать все. И вы даже не знаете, достаточно ли места для yy_left_string для хранения всех символов yytext. Таким образом, вы можете легко попасть в ошибку сегментации.

Вы понимаете, как работает память в C? Вы понимаете указатели и т.д.? Вы понимаете обработку строк в C?

Кроме того, я не уверен во всей информации, которую я предоставил о yytext. И. е. Я не уверен, что yytext действительно не должен храниться в ваших файлах. И я не уверен, что писать в память, на которую указывает yytext, - плохая идея. Прочитайте документацию, чтобы получить всю эту информацию.

(Кроме того, ваш тег «flex» неверен, поскольку речь идет о другом flex.)

0 голосов
/ 26 апреля 2018

Enum token_type KEYWORD имеет значение 0, и ваш цикл завершается, если ваш токен равен 0. Изменение

enum token_type{
    KEYWORD,

будет:

enum token_type{
    KEYWORD = 1,

и эта проблема исчезнет.

...