Return of the Lex

cppfortranlexyacc

I don’t touch the flex/yacc since the final exam of the class, until today I have to cope with the FORTRAN 90 input data. The input file is like:

80000.00 50.00
 80000.00 0.00
120000.00 0.00

with various data formats, flexible lengths of white space, scattered white lines. I first tired the standard string search/match, and soon lost the patience for tedious if..else. Therefore, I decided to try Lex, the very first flex in action.

First, the flex rule. We just need the float pointer number, and ignore all the spaces, new-lines and end-of-file. We expect the token is returned one by one, so we return the flag as soon as the pattern matches.

%option noyywrap

space [ \t]+
number [-+]?[0-9]*\.?[0-9]*

%%

{number} { return 1; }

{space} |
\n ;

%%

In main.c, we would like to override default input file handle stdin for yyin if additional argument is fed. Then we fetch the token one by one, convert the matched yytext to float-point number until the end of file.

extern FILE* yyin;
extern char* yytext;
extern int yylex(void);

int main(int argc, char* argv[] )
{
     double x;
     assert( yyin );
     if( argc == 1 )
     yyin = stdin;

     while( yylex() )
     {
         fprintf(stderr, "text = %s ", yytext );
         x = atof( yytext );
         fprintf(stderr, "x = %f\n", x );
     }

 return 0;
}

At then end, Makefile glues all the parts together.

LEX = flex
LEXFLAGS = -t
CFLAGS = -g
OBJS = obstac.o main.o
TARGET = scan

all : ${TARGET}

${TARGET} : ${OBJS}
  ${CC} ${CFLAGS} -o ${TARGET} ${OBJS}

%.c : %.l
  ${LEX} ${LEXFLAGS} $ $@

%.o : %.c
  ${CC} ${CFLAGS} -o $@ -c $

Here is the tarball for the source code and example input file.