Разница между написанием утверждений в определениях и в частях правил в lex - PullRequest
0 голосов
/ 16 октября 2019

Я новичок в lex. Предположим, что целью является написание программы lex для подсчета количества слов. Мы должны объявить счетчик переменной int и увеличивать его каждый раз, когда видят слова. Вопрос в том, в чем разница между этими примерами кода:

%option main
%{ 
#include<stdio.h> 
#include<string.h> 
             int i = 0;
%} 

%%
([a-zA-Z0-9])+    {i++;}
%%

и

%option main
%{ 
#include<stdio.h> 
#include<string.h> 
%} 
%%
             int i = 0;
([a-zA-Z0-9])+    {i++;}
%%

и

%option main
#include<stdio.h> 
#include<string.h> 
            int i = 0;
%%
([a-zA-Z0-9])+    {i++;}
%%

Влияет ли расположение #include<stdio.h> #include<string.h> накод здесь? Меняется ли программа в зависимости от того, где мы объявляем целую переменную i?

1 Ответ

0 голосов
/ 17 октября 2019

Да, порядок имеет значение. Но здесь дело не в #include строках.

Вот один правильный способ написания этой программы:

%option main
/* The %{ and %} delimiters must be at the beginning of the line.
   Lines between %{ and %} are copied verbatim into the generated
   file, near to the beginning.
*/
%{ 
  #include <stdio.h> 
  #include <string.h>
%} 
%%
  /* These lines must be indented. Indented lines after the %% and
   * before the first rule are inserted verbatim into the generated
   * lexer right at the beginning of the definition of the function
   * yylex. This lets you declare local variables, like nwords.
   */
  int nwords = 0;
([a-zA-Z0-9])+    { ++nwords; }
  /* Other rules go here. Every possible input should be matched by
   * some rule.
   */

  /* At a minimum, you can ignore all unmatched characters
   * using the following fall back (which should be the last rule).
   */
.|\n              ;

<<EOF>>           { printf("%d words found.\n", nwords); }

Правило <<EOF>> необходимо здесь, чтобы распечататьколичество слов, потому что nwords не будет доступно за пределами yylex. Альтернативой является сделать nwords глобальной переменной, но глобальные переменные обычно считаются плохой идеей. (И в любом случае вы используете %option main, что означает, что вы не собираетесь писать функцию main(), поэтому нет другого логического места, чтобы сообщить количество слов.

Если вы хотите сделать nwords global, вы должны объявить nwords в блоке %{...%}, чтобы он был объявлен вне какой-либо функции.

Flex позволяет исключать %{ и %} до тех пор, пока кодвставка с отступом. Но это довольно хрупко и может смутить многих людей, читающих ваш код; определенно рекомендуется использовать разделители, и тогда вам не нужно беспокоиться о том, вставлен ли код с отступом или нет.

...