|
|
Some problems require for their solution a greater sensitivity to prior context than is afforded by the ^ operator alone. You may want different rules to be applied to an expression depending on a prior context that is more complex than the end of a line or the start of a file. In this situation you could set a flag to mark the change in context that is the condition for the application of a rule, then write code to test the flag. Alternatively, you could define for lex the different ``start conditions'' under which it is to apply each rule.
Consider this problem: copy the input to the output, except change the word magic to the word first on every line that begins with the letter a; change magic to second on every line that begins with b; change magic to third on every line that begins with c. Here is how the problem might be handled with a flag. Recall that ECHO is a lex macro equivalent to printf("%s", yytext):
int flag %% ^a {flag = 'a'; ECHO;} ^b {flag = 'b'; ECHO;} ^c {flag = 'c'; ECHO;} \n {flag = 0; ECHO;} magic { switch (flag) { case 'a': printf("first"); break; case 'b': printf("second"); break; case 'c': printf("third"); break; default: ECHO; break; } }
To handle the same problem with start conditions, each start condition must be introduced to lex in the definitions section with a line reading
%Start name1 name2 . . .where the conditions may be named in any order. The word Start may be abbreviated to ``S'' or ``s''. The conditions are referenced at the head of a rule with ``<>'' brackets. So
<name1>expressionis a rule that is only recognized when the scanner is in start condition name1. To enter a start condition, execute the action statement
BEGIN name1;which changes the start condition to name1. To resume the normal state
BEGIN 0;resets the initial condition of the scanner. A rule may be active in several start conditions. That is,
<name1,name2,name3>is a valid prefix. Any rule not beginning with the <> prefix operators is always active.
The example can be written with start conditions as follows:
%Start AA BB CC %% ^a {ECHO; BEGIN AA;} ^b {ECHO; BEGIN BB;} ^c {ECHO; BEGIN CC;} \n {ECHO; BEGIN 0;} <AA>magic printf("first"); <BB>magic printf("second"); <CC>magic printf("third");