yyless(n)
permite retrasar el puntero de lectura
de manera que apunta al carácter n de yytext.
Veamos un ejemplo:
$ cat yyless.l %% foobar ECHO; yyless(4); [a-z]+ ECHO; $ flex yyless.l; gcc lex.yy.c -lfl; a.out foobar foobararVeamos un ejemplo mas ``real''. supongamos que tenemos que reconocer las cadenas entre comillas dobles, pero que pueden aparecer en las mismas secuencias de escape
\"
. La estrategia general del algoritmo
es utilizar la expresión regular \"[^"]+\"
y examinar si
los dos últimos carácteres en yytext
son \"
. En tal caso,
se concatena la cadena actual (sin la "
final) como prefijo para
el próximo emparejamiento (utilizando yymore
).
La eliminación de la "
se hace a través de la ejecución de
yyless(yyleng-1)
, que al mismo tiempo garantiza que el próximo emparejamiento
tendrá lugar con este mismo patrón \"[^"]+\"
.
$ cat quotes.l %% \"[^"]+\" { printf("Processing string. %d: %s\n",yyleng,yytext); if (yytext[yyleng-2] =='\\') { yyless(yyleng-1); /* so that it will match next time */ yymore(); /* concatenate with current yytext */ printf("After yyless. %d: %s\n",yyleng,yytext); } else { printf("Finished. The string is: %s\n",yytext); } }El ejemplo no puede entenderse si no se tiene en cuenta que
yyless(yyleng-1)
actualiza los valores de yyleng
y yytext, como muestra la salida.
yymore()
e yyless(yyleng-1)
en el código? >Cambiara la salida?
La respuesta es que no. Parece que la concatenación se hace con el valor
final de yytext y no con el valor que este tenía en el momento de
la llamada a yymore.
En general, el uso de estas funciones nos puede resolver el problema de reconocer límites que de otra forma serían difíciles de expresar con una expresión regular.
$ flex quotes.l ; gcc lex.yy.c -lfl ; a.out "Hello \"Peter\", nice to meet you" Procesing string. 9: "Hello \" After yyless. 8: "Hello \ Procesing string. 16: "Hello \"Peter\" After yyless. 15: "Hello \"Peter\ Procesing string. 35: "Hello \"Peter\", nice to meet you" Finished. The string is: "Hello \"Peter\", nice to meet you"