Provide multiple input buffers for Flex! Multiple Input Buffers

xiaoxiao2021-03-06  44

Some scanners (such as those which support "include" files) require reading from several input streams. As flex scanners do a large amount of buffering, one can not control where the next input will be read from by simply writing a YY_INPUT which is sensitive to the scanning context. YY_INPUT is only called when the scanner reaches the end of its buffer, which may be a long time after scanning a statement such as an "include" which requires switching the input source.

To Negotiate There Sorts of Problems, Flex Provides A Mechanism for Creating and Switching Between Multiple Input Buffers. An Input Buffer IS CREATED BYUSING:

YY_BUFFER_STATE YY_CREATE_BUFFER (File * file, int size)

which takes a FILE pointer and a size and creates a buffer associated with the given file and large enough to hold size characters (when in doubt, use YY_BUF_SIZE for the size). It returns a YY_BUFFER_STATE handle, which may then be passed to other routines (see below). The YY_BUFFER_STATE type is a pointer to an opaque struct yy_buffer_state structure, so you may safely initialize YY_BUFFER_STATE variables to ((YY_BUFFER_STATE) 0) if you wish, and also refer to the opaque structure in order to correctly declare input buffers . in source files other than that of your scanner Note that the FILE pointer in the call to yy_create_buffer is only used as the value of yyin seen by YY_INPUT; if you redefine YY_INPUT so it no longer uses yyin, then you can safely pass a nil File Pointer to YY_CREATE_BUFFER. You SELECT A Particular Buffer To Scan from Using:

Void yy_switch_to_buffer (YY_Buffer_State new_buffer)

switches the scanner's input buffer so subsequent tokens will come from new_buffer. Note that yy_switch_to_buffer () may be used by yywrap () to set things up for continued scanning, instead of opening a new file and pointing yyin at it. Note also that switching input Sources via either yy_switch_to_buffer () or yywrap () does not change the start condition.void yy_delete_buffer (YY_Buffer_State Buffer)

Is Used to Reclaim The Storage Associated with a buffer. You Can Also Clear The Current Contents of A Buffer Using:

Void yy_flush_buffer (YY_Buffer_State Buffer)

This Function Discards The Buffer's Contents, So The Next Time The Scanner Attempts To Match A Token From The Buffer, IT Will First Fill The Buffer Anew Using Yy_Input.

YY_NEW_BUFFER () is an alias for yy_create_buffer (), provided for Compatibility with the C use of new and delete for create and destroying Dynamic Objects.

Finally, The YY_CURRENT_BUFFER Macro Returns a yy_buffer_state handle to the current buffer.

Here is an esample of using these features for Writing a scanner Which Expands include files (the << EOF >> Feature IS Discussed Below):

/ * The "incl" state is buy for picking up the name

* of an include file

* /

% x INCL

% {

#define max_include_depth 10

YY_BUFFER_STATE INCLUDE_STACK [MAX_INCLUDE_DEPTH];

INT INCLUDE_STACK_PTR = 0;

%}

%%

INCLUDE BEGIN (INCL);

[A-Z] ECHO;

[^ a-z / n] * / n? echo;

IF (include_stack_ptr> = max_include_depth)

{

FPRINTF (stderr, "incrudes nested to deeply);

Exit (1);

}

INCLUDE_STACK [INCLUDE_STACK_PTR ] = YY_CURRENT_BUFFER;

YYIN = FOPEN (YYTEXT, "R");

IF (! yyin)

Error (...);

YY_SWITCH_TO_BUFFER

YY_CREATE_BUFFER (YYIN, YY_BUF_SIZE));

Begin (Initial);

}

<< EOF >> {

IF (--NClude_stack_ptr <0)

{

Yyterminate ();

}

Else

{

YY_DELETE_BUFFER (YY_CURRENT_BUFFER);

YY_SWITCH_TO_BUFFER

INCLUDE_STACK [INCLUDE_STACK_PTR]);

}

}

Three routines are available for setting up input buffers for scanning in-memory strings instead of files. All of them create a new input buffer for scanning the string, and return a corresponding YY_BUFFER_STATE handle (which you should delete with yy_delete_buffer () when done with IT). The next call to yylex () Will Start Scanning The String.

YY_SCAN_STRING (Const Char * STR)

Scans a Nul-Terminated String.

YY_SCAN_BYTES (Const Char * Bytes, INT LEN)

SCANS LEN BYTES (Including Possibly Nul ') Starting At Location Bytes.

Note That Both of these Functions Create and scan a copy of the string or bytes (Since YyleX () Modifies The Contents of the Buffer IT IS Scanning.) You can avoid the copy by using:

YY_SCAN_BUFFER (Char * Base, YY_SIZE_T SIZE)

which scans in place the buffer starting at base, consisting of size bytes, the last two bytes of which must be YY_END_OF_BUFFER_CHAR (ASCII NUL) These last two bytes are not scanned;. thus, scanning consists of base [0] through base [size -2], Inclusive.

If You Fail to set up base in this manner (i.e., forget the final two yy_end_of_buffer_char bytes), The YY_SCAN_Buffer () Returns A NIL Pointer INSTEAD OF CREATING A New Input Buffer.

转载请注明原文地址:https://www.9cbs.com/read-78662.html

New Post(0)