Использование Flex & Bison - PullRequest
1 голос
/ 24 июня 2011

Я пытаюсь выучить Flex & Bison. Я прочитал материал и понимаю, как он работает на теоретическом уровне. Тем не менее, я не могу реализовать даже самые базовые вещи, не задев ментальный блок. (Примечание: я не посещал курсы по компиляции или что-то в этом роде ... это мое первое знакомство с любым из этих вещей). Я думаю, что когда я увижу эту сверхосновную вещь, реализованную, я смогу двигаться дальше и понимать ее гораздо легче.

По сути, все, что я пытаюсь сделать, это написать программу, которая, увидев type my_type /// some text, вызовет функцию my_type с именем "set_text" и установит для текста то, что следует после этого комментария. Скорее моя грамматика Bison будет вызывать функцию my_type.set_text(some text); Я понимаю, что мог бы сделать это легко, не используя Flex и Bison, но дело в том, чтобы научиться.

У меня уже есть правильно настроенные файлы ... все, что мне нужно реализовать, - это передача токена (из Flex) и действие, предпринятое (из Bison).

Мой токен Flex прошел до сих пор:

"\/"{3}               { return COMMENT; }

Мой токен Зубра схватил до сих пор

%token COMMENT

и это все, что я могу придумать. Я знаю, что еще мне нужно ... Я просто не могу понять, как это сделать. Я знаю, что мне нужно:
а) передать type и my_type как что-то
б) придумать «правило» в Bison для обработки этого материала и вызова функции правильной функции

Любая помощь? Я уже ухожу?

ОБНОВЛЕНИЕ (дальнейшие мысли о том, как это сделать): Может быть, мой файл Bison должен содержать правило типа

commented_variable:                           {($2).set_text($4);}
    IDENTIFIER NAME COMMENT COMMENT_TEXT                      

Таким образом, мой файл Flex должен передать ему эти токены? Я на правильном пути?

Ответы [ 2 ]

1 голос
/ 26 июня 2011

Позвольте мне предложить некоторые вещи. Хотя невозможно обработать COMMENT и COMMENT_TEXT индивидуально используя начальное условие flex, я полагаю, что легче обрабатывать их одновременно.
bison источник будет выглядеть следующим образом (вымышленный код):

%union {
  name_type *name;
  char const *comment;
}
%token <name> NAME
%token <comment> COMMENT
%%
commented_variable: IDENTIFIER NAME COMMENT {$2->set_text($3);}

С лексической точки зрения ваши IDENTIFIER и NAME кажутся неразличимыми. Поэтому я разобрал их в коде пользователя (не лексически). flex источник будет выглядеть следующим образом:

"///".*                 {
                        yylval.comment = strdup( yytext + 3 );
                        return COMMENT;
                        }
[A-Za-z_][A-Za-z_0-9]*  {
                        name_type *n = lookup_name( yytext );
                        if ( n ) {
                          yylval.name = n;
                          return NAME;
                        }
                        return IDENTIFIER;
                        }

Однако приведенный выше код все еще нуждается в соответствующем name_type и lookup_name и free указатель, возвращенный из strdup.
Если у вас нет большого опыта в flex / bison, я бы рекомендовал сначала подтверждающий лексер достаточно. Например, я предлагаю подтвердить, что ожидаемые токены распознаются с простым кодом, таким как
int main() { while ( yylex() ) {} } и

"///".*                 printf("comment %s\n", yytext);
[A-Za-z_][A-Za-z_0-9]*  printf("symbol %s\n", yytext);

Аналогично, что касается bison кода, я рекомендую сначала разрешить грамматическое проблема, как сдвиг / уменьшение-конфликт, и подтверждение того, что грамматика распознается с помощью простого кода, например:

commented_variable: IDENTIFIER NAME COMMENT { puts("OK"); }
0 голосов
/ 24 июня 2011

Учитывая, что вы на самом деле используете текст, следующий за разделителем, я бы не использовал слово "комментарий" для всего, что у вас есть выше. Тем не менее, то, что вы вложили в свое обновление, в значительной степени правильная идея.

...