|
|
You may want to use your own routines in lex for much the same reason that you do so in other programming languages. Action code that is to be used for several rules can be written once and called when needed. As with definitions, this can simplify the writing and reading of programs. The function put_in_tabl(), to be discussed in the next section on lex and yacc, is a good candidate for the user routines section of a lex specification.
Another reason to place a routine in this section is to highlight some code of interest or to simplify the rules section, even if the code is to be used for one rule only. As an example, consider the following routine to ignore comments in a language like C where comments occur between / and /:
%{ static skipcmnts(); %} %% "/" skipcmnts(); . . /* rest of rules */ %% static skipcmnts() { for(;;) { while (input() != '') ; if (input() != '/') unput(yytext[yyleng-1]) else return; } }
There are three points of interest in this example. First, the unput(c) macro (putting back the last character read) is necessary to avoid missing the final / if the comment ends with a /. In this case, eventually having read a , the scanner finds that the next character is not the terminal / and must read some more. Second, the expression yytext[yyleng-1] picks out that last character read. Third, this routine assumes that the comments are not nested, which is indeed the case with the C language.