📄 flexdoc.1
字号:
.B yyrestart()is first called (see below)..LPActions are not allowed to modify yytext or yyleng..LPThere are a number of special directives which can be included withinan action:.IP -.B ECHOcopies yytext to the scanner's output..IP -.B BEGINfollowed by the name of a start condition places the scanner in thecorresponding start condition (see below)..IP -.B REJECTdirects the scanner to proceed on to the "second best" rule which matched theinput (or a prefix of the input). The rule is chosen as describedabove in "How the Input is Matched", and.B yytextand.B yylengset up appropriately.It may either be one which matched as much textas the originally chosen rule but came later in the.I flexinput file, or one which matched less text.For example, the following will both count thewords in the input and call the routine special() whenever "frob" is seen:.nf int word_count = 0; %% frob special(); REJECT; [^ \\t\\n]+ ++word_count;.fiWithout the.B REJECT,any "frob"'s in the input would not be counted as words, since thescanner normally executes only one action per token.Multiple.B REJECT'sare allowed, each one finding the next best choice to the currentlyactive rule. For example, when the following scanner scans the token"abcd", it will write "abcdabcaba" to the output:.nf %% a | ab | abc | abcd ECHO; REJECT; .|\\n /* eat up any unmatched character */.fi(The first three rules share the fourth's action since they usethe special '|' action.).B REJECTis a particularly expensive feature in terms scanner performance;if it is used in.I anyof the scanner's actions it will slow down.I allof the scanner's matching. Furthermore,.B REJECTcannot be used with the.I -for.I -Foptions (see below)..IPNote also that unlike the other special actions,.B REJECTis a.I branch;code immediately following it in the action will.I notbe executed..IP -.B yymore()tells the scanner that the next time it matches a rule, the correspondingtoken should be.I appendedonto the current value of.B yytextrather than replacing it. For example, given the input "mega-kludge"the following will write "mega-mega-kludge" to the output:.nf %% mega- ECHO; yymore(); kludge ECHO;.fiFirst "mega-" is matched and echoed to the output. Then "kludge"is matched, but the previous "mega-" is still hanging around at thebeginning of.B yytextso the.B ECHOfor the "kludge" rule will actually write "mega-kludge".The presence of.B yymore()in the scanner's action entails a minor performance penalty in thescanner's matching speed..IP -.B yyless(n)returns all but the first.I ncharacters of the current token back to the input stream, where theywill be rescanned when the scanner looks for the next match..B yytextand.B yylengare adjusted appropriately (e.g.,.B yylengwill now be equal to.I n). For example, on the input "foobar" the following will write out"foobarbar":.nf %% foobar ECHO; yyless(3); [a-z]+ ECHO;.fiAn argument of 0 to.B yylesswill cause the entire current input string to be scanned again. Unless you'vechanged how the scanner will subsequently process its input (using.B BEGIN,for example), this will result in an endless loop..IP -.B unput(c)puts the character.I cback onto the input stream. It will be the next character scanned.The following action will take the current token and cause itto be rescanned enclosed in parentheses..nf { int i; unput( ')' ); for ( i = yyleng - 1; i >= 0; --i ) unput( yytext[i] ); unput( '(' ); }.fiNote that since each.B unput()puts the given character back at the.I beginningof the input stream, pushing back strings must be done back-to-front..IP -.B input()reads the next character from the input stream. For example,the following is one way to eat up C comments:.nf %% "/*" { register int c; for ( ; ; ) { while ( (c = input()) != '*' && c != EOF ) ; /* eat up text of comment */ if ( c == '*' ) { while ( (c = input()) == '*' ) ; if ( c == '/' ) break; /* found the end */ } if ( c == EOF ) { error( "EOF in comment" ); break; } } }.fi(Note that if the scanner is compiled using.B C++,then.B input()is instead referred to as.B yyinput(),in order to avoid a name clash with the.B C++stream by the name of.I input.).IP -.B yyterminate()can be used in lieu of a return statement in an action. It terminatesthe scanner and returns a 0 to the scanner's caller, indicating "all done".Subsequent calls to the scanner will immediately return unless precededby a call to.B yyrestart()(see below).By default,.B yyterminate()is also called when an end-of-file is encountered. It is a macro andmay be redefined..SH THE GENERATED SCANNERThe output of.I flexis the file.B lex.yy.c,which contains the scanning routine.B yylex(),a number of tables used by it for matching tokens, and a numberof auxiliary routines and macros. By default,.B yylex()is declared as follows:.nf int yylex() { ... various definitions and the actions in here ... }.fi(If your environment supports function prototypes, then it willbe "int yylex( void )".) This definition may be changed by redefiningthe "YY_DECL" macro. For example, you could use:.nf #undef YY_DECL #define YY_DECL float lexscan( a, b ) float a, b;.fito give the scanning routine the name.I lexscan,returning a float, and taking two floats as arguments. Note thatif you give arguments to the scanning routine using aK&R-style/non-prototyped function declaration, you must terminatethe definition with a semi-colon (;)..LPWhenever.B yylex()is called, it scans tokens from the global input file.I yyin(which defaults to stdin). It continues until it either reachesan end-of-file (at which point it returns the value 0) orone of its actions executes a.I returnstatement.In the former case, when called again the scanner will immediatelyreturn unless.B yyrestart()is called to point.I yyinat the new input file. (.B yyrestart()takes one argument, a.B FILE *pointer.)In the latter case (i.e., when an actionexecutes a return), the scanner may then be called again and itwill resume scanning where it left off..LPBy default (and for purposes of efficiency), the scanner usesblock-reads rather than simple.I getc()calls to read characters from.I yyin.The nature of how it gets its input can be controlled by redefining the.B YY_INPUTmacro.YY_INPUT's calling sequence is "YY_INPUT(buf,result,max_size)". Itsaction is to place up to.I max_sizecharacters in the character array.I bufand return in the integer variable.I resulteither thenumber of characters read or the constant YY_NULL (0 on Unix systems)to indicate EOF. The default YY_INPUT reads from theglobal file-pointer "yyin"..LPA sample redefinition of YY_INPUT (in the definitionssection of the input file):.nf %{ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \\ { \\ int c = getchar(); \\ result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \\ } %}.fiThis definition will change the input processing to occurone character at a time..LPYou also can add in things like keeping track of theinput line number this way; but don't expect your scanner togo very fast..LPWhen the scanner receives an end-of-file indication from YY_INPUT,it then checks the.B yywrap()function. If.B yywrap()returns false (zero), then it is assumed that thefunction has gone ahead and set up.I yyinto point to another input file, and scanning continues. If it returnstrue (non-zero), then the scanner terminates, returning 0 to itscaller..LPThe default.B yywrap()always returns 1. Presently, to redefine it you must first"#undef yywrap", as it is currently implemented as a macro. As indicatedby the hedging in the previous sentence, it may be changed toa true function in the near future..LPThe scanner writes its.B ECHOoutput to the.I yyoutglobal (default, stdout), which may be redefined by the user simplyby assigning it to some other.B FILEpointer..SH START CONDITIONS.I flexprovides a mechanism for conditionally activating rules. Any rulewhose pattern is prefixed with "<sc>" will only be active whenthe scanner is in the start condition named "sc". For example,.nf <STRING>[^"]* { /* eat up the string body ... */ ... }.fiwill be active only when the scanner is in the "STRING" startcondition, and.nf <INITIAL,STRING,QUOTE>\\. { /* handle an escape ... */ ... }.fiwill be active only when the current start condition iseither "INITIAL", "STRING", or "QUOTE"..LPStart conditionsare declared in the definitions (first) section of the inputusing unindented lines beginning with either.B %sor.B %xfollowed by a list of names.The former declares.I inclusivestart conditions, the latter.I exclusivestart conditions. A start condition is activated using the.B BEGINaction. Until the next.B BEGINaction is executed, rules with the given startcondition will be active andrules with other start conditions will be inactive.If the start condition is.I inclusive,then rules with no start conditions at all will also be active.If it is.I exclusive,then.I onlyrules qualified with the start condition will be active.A set of rules contingent on the same exclusive start conditiondescribe a scanner which is independent of any of the other rules in the.I flexinput. Because of this,exclusive start conditions make it easy to specify "mini-scanners"which scan portions of the input that are syntactically differentfrom the rest (e.g., comments)..LPIf the distinction between inclusive and exclusive start conditionsis still a little vague, here's a simple example illustrating theconnection between the two. The set of rules:.nf %s example %% <example>foo /* do something */.fiis equivalent to.nf %x example %% <INITIAL,example>foo /* do something */.fi.LPThe default rule (to.B ECHOany unmatched character) remains active in start conditions..LP.B BEGIN(0)returns to the original state where only the rules withno start conditions are active. This state can also bereferred to as the start-condition "INITIAL", so.B BEGIN(INITIAL)is equivalent to.B BEGIN(0).(The parentheses around the start condition name are not required butare considered good style.).LP.B BEGINactions can also be given as indented code at the beginningof the rules section. For example, the following will causethe scanner to enter the "SPECIAL" start condition whenever.I yylex()is called and the global variable.I enter_specialis true:.nf int enter_special; %x SPECIAL %% if ( enter_special ) BEGIN(SPECIAL); <SPECIAL>blahblahblah ...more rules follow....fi.LPTo illustrate the uses of start conditions,here is a scanner which provides two different interpretationsof a string like "123.456". By default it will treat it asas three tokens, the integer "123", a dot ('.'), and the integer "456".But if the string is preceded earlier in the line by the string"expect-floats"it will treat it as a single token, the floating-point number123.456:.nf %{ #include <math.h> %} %s expect %% expect-floats BEGIN(expect); <expect>[0-9]+"."[0-9]+ { printf( "found a float, = %f\\n", atof( yytext ) ); } <expect>\\n { /* that's the end of the line, so * we need another "expect-number" * before we'll recognize any more * numbers */ BEGIN(INITIAL); } [0-9]+ { printf( "found an integer, = %d\\n", atoi( yytext ) ); } "." printf( "found a dot\\n" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -