%s
para los estados ``inclusivos'' o bien %x
para los estados ``exclusivos'',
seguidos de los nombres de los estados. No pueden haber caracteres en blanco antes de la declaración.
Un estado se activa mediante la
acción BEGIN estado. A partir de ese momento, las reglas que esten
prefijadas con el estado pasan a estar activas. En el caso de que el estado
sea inclusivo, las reglas no prefijadas también permanecen activas.
Los estados exclusivos son especialmente útiles para especificar ``sub analizadores''
que analizan porciones de la entrada cuya estructura ``sintáctica'' es diferente
de la del resto de la entrada.
El ejemplo ``absorbe'' los comentarios, conservando el numero de
líneas del fichero en la variable linenum
$ cat comments.l %option noyywrap %{ int linenum = 0; %} %x comment %% "/*" BEGIN(comment); printf("comment=%d, YY_START = %d, YYSTATE = %d",comment,YY_START,YYSTATE); <comment>[^*\n]* /* eat anything that is not a star * / <comment>"*"+[^*/\n]* /* eat up starts not followed by / */ <comment>\n ++linenum; /* update number of lines */ <comment>"*"+"/" BEGIN(0); \n ECHO; linenum++; . ECHO; %% main() { yylex(); printf("\n%d lines\n",linenum); }La opción
noyywrap
hace que yylex()
no llame a la función yywrap()
al final del fichero y que asuma que no hay mas entrada por procesar.
Los estados se traducen por enteros, pudiendo ser manipulados como tales.
La macro INITIAL
puede utilizarse para referirse al estado 0.
Las macros YY_START
y YYSTATE
contienen el valor del estado actual.
$ flex comments.l ; gcc lex.yy.c ; a.out < hello.c main() <% int a<:1:>; comment=1, YY_START = 1, YYSTATE = 1 a<:0:> = 4; comment=1, YY_START = 1, YYSTATE = 1 printf("hello world! a(0) is %d\n",a<:0:>); %> 6 lines $ cat hello.c main() <% int a<:1:>; /* a comment */ a<:0:> = 4; /* a comment in two lines */ printf("hello world! a(0) is %d\n",a<:0:>); %>En flex es posible asociar un ámbito con los estados o condiciones iniciales. Basta con colocar entre llaves las parejas patrón acción gobernadas por ese estado. El siguiente ejemplo procesa las cadenas C:
$ cat ststring.l %option main %x str %{ #define MAX_STR_CONST 256 char string_buffer[MAX_STR_CONST]; char *string_buf_ptr; %} %% \" string_buf_ptr = string_buffer; BEGIN(str); <str>{ \" {BEGIN (INITIAL); *string_buf_ptr = '\0'; printf("%s",string_buffer); } \n { printf("Error: non terminated string\n"); exit(1); } \\[0-7]{1,3} { int result; /* octal escape sequence */ (void) sscanf(yytext+1,"%o",&result); if (result > 0xff) {printf("Error: constant out of bounds\n"); exit(2); } *string_buf_ptr++ = result; } \\[0-9]+ { printf("Error: bad escape sequence\n"); exit(2); } \\n {*string_buf_ptr++ = '\n';} \\t {*string_buf_ptr++ = '\t';} \\b {*string_buf_ptr++ = '\b';} \\r {*string_buf_ptr++ = '\r';} \\f {*string_buf_ptr++ = '\f';} \\(.|\n) {*string_buf_ptr++ = yytext[1];} [^\\\n\"]+ {char *yptr = yytext; while(*yptr) *string_buf_ptr++ = *yptr++; } } (.|\n) %% $ flex ststring.l ; gcc lex.yy.c ; a.out < hello.c hello world! a(0) is %d $ cat hello.c main() <% int a<:1:>; /* a comment */ a<:0:> = 4; /* a comment in two lines */ printf("\thell\157\nworld! a(0) is %d\n",a<:0:>); %>Obsérve la conducta del programa ante las siguientes entradas:
"hello \ dolly"¿Cuál será la salida? ¿Que patrón del programa anterior es el que casa aqui?
"hello\ndolly"
.
¿Cuál será la salida? ¿Que patrón del programa anterior es el que casa aqui?
| "helloDonde hay un retorno del carro después de
hello
.
¿Cuál será la salida?