⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flex.texi

📁 Flex词法/语法分析器源码
💻 TEXI
📖 第 1 页 / 共 5 页
字号:
<example>foo   do_something();<INITIAL,example>bar    something_else();@end exampleWithout the @samp{<INITIAL,example>} qualifier, the @samp{bar} patternin the second example wouldn't be active (i.e., couldn't match) whenin start condition @samp{example}.  If we just used @samp{<example>}to qualify @samp{bar}, though, then it would only be active in@samp{example} and not in @code{INITIAL}, while in the first exampleit's active in both, because in the first example the @samp{example}starting condition is an @emph{inclusive} (@samp{%s}) start condition.Also note that the special start-condition specifier @samp{<*>}matches every start condition.  Thus, the above examplecould also have been written;@example%x example%%<example>foo   do_something();<*>bar    something_else();@end exampleThe default rule (to @samp{ECHO} any unmatched character) remainsactive in start conditions.  It is equivalent to:@example<*>.|\\n     ECHO;@end example@samp{BEGIN(0)} returns to the original state where only therules with no start conditions are active.  This state canalso be referred to as the start-condition "INITIAL", so@samp{BEGIN(INITIAL)} is equivalent to @samp{BEGIN(0)}.  (Theparentheses around the start condition name are not required butare considered good style.)@code{BEGIN} actions can also be given as indented code at thebeginning of the rules section.  For example, thefollowing will cause the scanner to enter the "SPECIAL" startcondition whenever @samp{yylex()} is called and the globalvariable @code{enter_special} is true:@example        int enter_special;%x SPECIAL%%        if ( enter_special )            BEGIN(SPECIAL);<SPECIAL>blahblahblah@dots{}more rules follow@dots{}@end exampleTo illustrate the uses of start conditions, here is ascanner which provides two different interpretations of astring like "123.456".  By default it will treat it as asthree tokens, the integer "123", a dot ('.'), and theinteger "456".  But if the string is preceded earlier inthe line by the string "expect-floats" it will treat it asa single token, the floating-point number 123.456:@example%@{#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]+      @{Version 2.5               December 1994                        18            printf( "found an integer, = %d\n",                    atoi( yytext ) );            @}"."         printf( "found a dot\n" );@end exampleHere is a scanner which recognizes (and discards) Ccomments while maintaining a count of the current input line.@example%x comment%%        int line_num = 1;"/*"         BEGIN(comment);<comment>[^*\n]*        /* eat anything that's not a '*' */<comment>"*"+[^*/\n]*   /* eat up '*'s not followed by '/'s */<comment>\n             ++line_num;<comment>"*"+"/"        BEGIN(INITIAL);@end exampleThis scanner goes to a bit of trouble to match as muchtext as possible with each rule.  In general, whenattempting to write a high-speed scanner try to match asmuch possible in each rule, as it's a big win.Note that start-conditions names are really integer valuesand can be stored as such.  Thus, the above could beextended in the following fashion:@example%x comment foo%%        int line_num = 1;        int comment_caller;"/*"         @{             comment_caller = INITIAL;             BEGIN(comment);             @}@dots{}<foo>"/*"    @{             comment_caller = foo;             BEGIN(comment);             @}<comment>[^*\n]*        /* eat anything that's not a '*' */<comment>"*"+[^*/\n]*   /* eat up '*'s not followed by '/'s */<comment>\n             ++line_num;<comment>"*"+"/"        BEGIN(comment_caller);@end exampleFurthermore, you can access the current start conditionusing the integer-valued @code{YY_START} macro.  For example, theabove assignments to @code{comment_caller} could instead bewritten@examplecomment_caller = YY_START;@end exampleFlex provides @code{YYSTATE} as an alias for @code{YY_START} (since thatis what's used by AT&T @code{lex}).Note that start conditions do not have their ownname-space; %s's and %x's declare names in the same fashion as#define's.Finally, here's an example of how to match C-style quotedstrings using exclusive start conditions, includingexpanded escape sequences (but not including checking fora string that's too long):@example%x str%%        char string_buf[MAX_STR_CONST];        char *string_buf_ptr;\"      string_buf_ptr = string_buf; BEGIN(str);<str>\"        @{ /* saw closing quote - all done */        BEGIN(INITIAL);        *string_buf_ptr = '\0';        /* return string constant token type and         * value to parser         */        @}<str>\n        @{        /* error - unterminated string constant */        /* generate error message */        @}<str>\\[0-7]@{1,3@} @{        /* octal escape sequence */        int result;        (void) sscanf( yytext + 1, "%o", &result );        if ( result > 0xff )                /* error, constant is out-of-bounds */        *string_buf_ptr++ = result;        @}<str>\\[0-9]+ @{        /* generate error - bad escape sequence; something         * like '\48' or '\0777777'         */        @}<str>\\n  *string_buf_ptr++ = '\n';<str>\\t  *string_buf_ptr++ = '\t';<str>\\r  *string_buf_ptr++ = '\r';<str>\\b  *string_buf_ptr++ = '\b';<str>\\f  *string_buf_ptr++ = '\f';<str>\\(.|\n)  *string_buf_ptr++ = yytext[1];<str>[^\\\n\"]+        @{        char *yptr = yytext;        while ( *yptr )                *string_buf_ptr++ = *yptr++;        @}@end exampleOften, such as in some of the examples above, you wind upwriting a whole bunch of rules all preceded by the samestart condition(s).  Flex makes this a little easier andcleaner by introducing a notion of start condition @dfn{scope}.A start condition scope is begun with:@example<SCs>@{@end example@noindentwhere SCs is a list of one or more start conditions.Inside the start condition scope, every rule automaticallyhas the prefix @samp{<SCs>} applied to it, until a @samp{@}} whichmatches the initial @samp{@{}.  So, for example,@example<ESC>@{    "\\n"   return '\n';    "\\r"   return '\r';    "\\f"   return '\f';    "\\0"   return '\0';@}@end example@noindentis equivalent to:@example<ESC>"\\n"  return '\n';<ESC>"\\r"  return '\r';<ESC>"\\f"  return '\f';<ESC>"\\0"  return '\0';@end exampleStart condition scopes may be nested.Three routines are available for manipulating stacks ofstart conditions:@table @samp@item void yy_push_state(int new_state)pushes the current start condition onto the top ofthe start condition stack and switches to @var{new_state}as though you had used @samp{BEGIN new_state} (recall thatstart condition names are also integers).@item void yy_pop_state()pops the top of the stack and switches to it via@code{BEGIN}.@item int yy_top_state()returns the top of the stack without altering thestack's contents.@end tableThe start condition stack grows dynamically and so has nobuilt-in size limitation.  If memory is exhausted, programexecution aborts.To use start condition stacks, your scanner must include a@samp{%option stack} directive (see Options below).@node Multiple buffers, End-of-file rules, Start conditions, Top@section Multiple input buffersSome scanners (such as those which support "include"files) require reading from several input streams.  As@code{flex} scanners do a large amount of buffering, one cannotcontrol where the next input will be read from by simplywriting a @code{YY_INPUT} which is sensitive to the scanningcontext.  @code{YY_INPUT} is only called when the scanner reachesthe end of its buffer, which may be a long time afterscanning a statement such as an "include" which requiresswitching the input source.To negotiate these sorts of problems, @code{flex} provides amechanism for creating and switching between multipleinput buffers.  An input buffer is created by using:@exampleYY_BUFFER_STATE yy_create_buffer( FILE *file, int size )@end example@noindentwhich takes a @code{FILE} pointer and a size and creates a bufferassociated with the given file and large enough to hold@var{size} characters (when in doubt, use @code{YY_BUF_SIZE} for thesize).  It returns a @code{YY_BUFFER_STATE} handle, which maythen be passed to other routines (see below).  The@code{YY_BUFFER_STATE} type is a pointer to an opaque @code{struct}@code{yy_buffer_state} structure, so you may safely initializeYY_BUFFER_STATE variables to @samp{((YY_BUFFER_STATE) 0)} if youwish, and also refer to the opaque structure in order tocorrectly declare input buffers in source files other thanthat of your scanner.  Note that the @code{FILE} pointer in thecall to @code{yy_create_buffer} is only used as the value of @code{yyin}seen by @code{YY_INPUT}; if you redefine @code{YY_INPUT} so it no longeruses @code{yyin}, then you can safely pass a nil @code{FILE} pointer to@code{yy_create_buffer}.  You select a particular buffer to scanfrom using:@examplevoid yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )@end exampleswitches the scanner's input buffer so subsequent tokenswill come from @var{new_buffer}.  Note that@samp{yy_switch_to_buffer()} may be used by @samp{yywrap()} to setthings up for continued scanning, instead of opening a newfile and pointing @code{yyin} at it.  Note also that switchinginput sources via either @samp{yy_switch_to_buffer()} or @samp{yywrap()}does @emph{not} change the start condition.@examplevoid yy_delete_buffer( YY_BUFFER_STATE buffer )@end example@noindentis used to reclaim the storage associated with a buffer.You can also clear the current contents of a buffer using:@examplevoid yy_flush_buffer( YY_BUFFER_STATE buffer )@end exampleThis function discards the buffer's contents, so the next time thescanner attempts to match a token from the buffer, it will first fillthe buffer anew using @code{YY_INPUT}.@samp{yy_new_buffer()} is an alias for @samp{yy_create_buffer()},provided for compatibility with the C++ use of @code{new} and @code{delete}for creating and destroying dynamic objects.Finally, the @code{YY_CURRENT_BUFFER} macro returns a@code{YY_BUFFER_STATE} handle to the current buffer.Here is an example of using these features for writing ascanner which expands include files (the @samp{<<EOF>>} featureis discussed below):@example/* the "incl" state is used for picking up the name * of an include file */%x incl%@{#define MAX_INCLUDE_DEPTH 10YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];int include_stack_ptr = 0;%@}%%include             BEGIN(incl);[a-z]+              ECHO;[^a-z\n]*\n?        ECHO;<incl>[ \t]*      /* eat the whitespace */<incl>[^ \t\n]+   @{ /* got the include file name */        if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )            @{            fprintf( stderr, "Includes nested too deeply" );            exit( 1 );            @}        include_stack[include_stack_ptr++] =            YY_CURRENT_BUFFER;        yyin = fopen( yytext, "r" );        if ( ! yyin )            error( @dots{} );        yy_switch_to_buffer(            yy_create_buffer( yyin, YY_BUF_SIZE ) );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -