do i = 1, 10
es equivalente a la cadena
DOI=1,10
. Un conocido conflicto ocurre entre una cadena
con la estructura do i = 1.10
(esto es DOI=1.10
) y
la cadena anterior. En la primera DO
e I
son dos
``tokens'' diferentes, el primero correspondiendo a la palabra reservada que indica un bucle. En la segunda, DOI
constituye un único ``token''
y la sentencia se refiere a una asignación.
El conflicto puede resolverse utilizando el operador de ``trailing'' r/s
.
Como se mencionó, el operador de ``trailing''r/s
permite reconocer una r
pero sólo si va seguida de una s
. El texto casado con s
se incluye a la hora de decidir cual es el emparejamiento mas largo, pero se devuelve a la entrada cuando se ejecuta la acción. La acción sólo ve el texto asociado con r
. El fichero fortran4.l
ilustra una posible solución:
cat fortran4.l %array %{ #include <string.h> #undef YY_INPUT #define YY_INPUT(buf,result,max) (result = my_input(buf,max)) %} number [0-9]+ integer [+-]?{number} float ({integer}\.{number}?|\.{number})(E{integer})? label [A-Z0-9]+ id [A-Z]{label}* %% DO/{label}={number}\, { printf("do loop\n"); } {id} { printf("Identifier %s\n",yytext); } {number} { printf("Num %d\n",atoi(yytext)); } {float} { printf("Float %f\n",atof(yytext)); } (.|\n) %% int my_input(char *buf, int max) { char *q1, *q2, *p = (char *) malloc(max); int i; if ('\0' != fgets(p,max,yyin)) { for(i=0, q1=buf, q2=p;(*q2 != '\0');q2++) { if (*q2 != ' ') { *q1++ = toupper(*q2); i++; }; } free(p); return i; } else exit(1); }La función
char *fgets(char *s, int size, FILE *stream)
lee a lo mas uno menos que size
caracteres desde stream
y los almacena en el buffer
apuntado por s
. La lectura termina después de un EOF
o un retorno de carro.
Si se lee un \n
, se almacena en el buffer. La función pone un carácter nulo \0
como último carácter en el buffer.
A continuación, puedes ver los detalles de una ejecución:
$ flex fortran4.l; gcc lex.yy.c -lfl; a.out do j = 1 . 10 Identifier DOJ Float 1.100000 do k = 1, 5 do loop Identifier K Num 1 Num 5