【002】FlexBison原理分析

0. 前言

Flex和Bison是用于構建處理結構化輸入的程序的工具。它們最初是用于構建編譯器的工具,但它們已被證明在許多其他領域都很有用。

在第一章中,我們將首先看一點(但不是太多)它們背后的理論,然后我們將深入研究一些使用它們的例子。

1. 詞法分析&解析

早在20世紀50年代,最早的編譯器就使用了專門的技術來分析他們正在編譯的程序的源代碼的語法。在20世紀60年代
這個領域得到了學術界的廣泛關注,到20世紀70年代初,語法分析已經成為一個廣為人知的領域。

其中一個關鍵見解是將這項工作分為兩個部分:詞匯分析(lexical analysis ,也稱為詞法分析或掃描)和語法分析(syntax analysis,或解析)。

粗略地說,掃描將輸入劃分為有意義的塊,稱為tokens,并通過解析找出tokens之間的關系。例如,考慮以下C代碼片段:

alpha = beta + gamma ;

掃描儀將其分為標記alpha、等號、beta、加號、gamma和分號。然后解析器確定beta+gamma是一個表達式,并且
表達式被指定給alpha

1.1 獲取Flex和Bison

大多數Linux和BSD系統都將flex和bison作為基本系統的一部分。如果您的系統沒有它們,或者有過時的版本,它們都很容易安裝。

Flex是一個Sourceforge項目,網址是http://flex.sourceforge.net/。2009年初的當前版本是2.5.35。版本之間的變化通常很小,所以如果它接近0.35,就沒有必要更新你的版本,但有些系統仍然使用2.5.4或2.5.4a版本,這是十多年前的版本。

Bison可從http://www.gnu.org/software/bison/獲得。2009年初的當前版本是2.4.1。Bison的開發相當活躍,所以值得購買最新版本,看看有什么新功能。例如,版本2.4增加了對Java解析器的支持。BSD用戶通常可以使用ports集合安裝flex或bison的當前版本。Linux用戶可以找到當前的RPMs。如果沒有,flex和bison都使用標準的GNU構建過程,所以要安裝它們,從網站上下載并解壓縮當前的flex和bison tarball,運行 ./configure然后make來構建它們,然后成為超級用戶并make install來安裝它們。

Flex和bison都依賴于GNU m4宏處理器。Linux和BSD應該都有m4,但如果他們沒有,或者他們有一個古老的版本,當前的GNU m4在http://www.gnu.org/software/m4/

對于Windows用戶,bison和flex都包含在可從http://www.cygwin.com/獲得的Cygwin Linux仿真環境中。您可以使用它們用Cygwin開發工具或本機Windows開發工具生成的C或c++代碼

1.2 正則表達式和掃描

掃描器通常通過查找輸入中的字符模式來工作。例如,在C程序中,整型常量是由一個或多個數字組成的字符串,變量名是一個字母后面跟著零個或多個字母或數字,各種操作符是單個字符或字符對。描述這些模式的一種直接方法是正則表達式(regular expressions),通常簡稱為regexregexp。這些模式與編輯器edvi以及搜索程序egrep用來描述要搜索的文本的模式相同。flex程序基本上由一個regexps列表組成,其中包含了當輸入與其中任何一個regexp匹配時的操作指令,即所謂的操作。flex生成的掃描器讀取其輸入,將輸入與所有regexp進行匹配,并對每個匹配執行適當的操作。Flex將所有regexp轉換為一種有效的內部形式,使其能夠同時針對所有模式匹配輸入,因此對于100個模式和一個模式的速度一樣快。★

★ 內部形式稱為確定性有限自動化(DFA)。幸運的是,在這一點上,您真正需要知道的關于dfa的唯一一件事是它們非常快,而且速度與模式的數量或復雜性無關。

  • 第一個flex程序
    Unix系統(我指的是Unix-ish系統,包括Linux和bsd)附帶了一個單詞計數程序,該程序讀取文件并報告文件中的行數、單詞數和字符數。Flex允許我們用幾十行代碼編寫wc,如例1-1所示。
/* just like Unix wc */
%{
int chars = 0;
int words = 0;
int lines = 0;
%}%%
[a-zA-Z]+ { words++; chars += strlen(yytext); }
\n { chars++; lines++; }
. { chars++; }
%%main(int argc, char **argv)
{yylex();printf("%8d%8d%8d\n", lines, words, chars);
}

上面flex程序的解釋:

對于C程序員來說,這個程序的大部分應該看起來很熟悉,因為它的大部分是C語言。一個flex程序由三個部分組成,用%%行分隔。第一部分包含聲明和選項設置。第二部分是模式和操作的列表,第三部分是復制到生成的掃描器中的C代碼,通常是與操作中的代碼相關的小例程。

在聲明部分,%{%}內部的代碼被逐字復制到生成的C源文件開頭附近。在本例中,它只是為行(lines)、詞(words)和字符(characters)設置變量。

在第二部分中,每個模式位于一行的開頭,后面是模式匹配時要執行的C代碼。C代碼可以是一條語句,也可以是用大括號{}括起來的多行塊。(每個模式必須從行首開始,因為flex認為任何以空格開頭的行都是要復制到生成的C程序中的代碼。)

在這個程序中,只有三種模式。第一個, [a-zA-Z]+匹配一個單詞。括號中的字符(稱為字符類)匹配任何單個大寫或小寫字母,+號表示匹配前面的一個或多個字符,這里指的是一串字母或一個單詞。action代碼更新所看到的單詞和字符的數量。在任何flex操作中,變量yytext被設置為指向模式剛剛匹配的輸入文本。在這種情況下,我們所關心的是它有多少字符,這樣我們就可以適當地更新字符數。

第二個模式\n,只匹配一個新行。該操作更新行數和字符(characters)。

最后一個模式是一個點(.),它是任何字符的正則表達式。(類似于在shell腳本中的問號(?))動作更新字符的數量。這就是我們需要的所有模式。

最后的C代碼是一個主程序,它調用yylex() (flex給掃描器例程的名稱),然后打印結果。在沒有任何其他安排的情況下,掃描器從標準輸入讀取。我們運行一下。

[root@node164 0430]# flex 2.l
[root@node164 0430]# ls
2.l  lex.yy.c
[root@node164 0430]# gcc lex.yy.c -lfl

首先,我們告訴flex翻譯我們的程序,按照經典的Unix方式,因為沒有錯誤,所以它翻譯了程序,什么也沒說。然后我們編譯lex.yy.c,它生成的C程序;鏈接它與flex庫,-lfl;運行它;然后輸入一點讓它計數。似乎有效。

實際的wc程序對單詞的定義略有不同,它是一串非空白字符。一旦我們查找了所有的空白字符是什么,我們只需要將匹配單詞的行替換為匹配非空白字符字符串的行:

[^ \t\n\r\f\v]+ { words++; chars += strlen(yytext); }

字符類開頭的^表示匹配類中字符以外的任何字符,+再次表示匹配前面的一個或多個模式。這展示了flex的優點之一,對模式進行小的更改是很容易的,并讓flex擔心這些更改會如何影響生成的代碼。

附:lex.yy.c程序的源碼


#line 2 "lex.yy.c"#define  YY_INT_ALIGNED short int/* A lexical scanner generated by flex */#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif/* First, we deal with  platform-specific or compiler-specific issues. *//* begin standard C headers. */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>/* end standard C headers. *//* flex integer type definitions */#ifndef FLEXINT_H
#define FLEXINT_H/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,* if you want the limit (max/min) macros for int types. */
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif#include <inttypes.h>
typedef int8_t flex_int8_t;
typedef uint8_t flex_uint8_t;
typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
typedef unsigned char flex_uint8_t; 
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;/* Limits of integral types. */
#ifndef INT8_MIN
#define INT8_MIN               (-128)
#endif
#ifndef INT16_MIN
#define INT16_MIN              (-32767-1)
#endif
#ifndef INT32_MIN
#define INT32_MIN              (-2147483647-1)
#endif
#ifndef INT8_MAX
#define INT8_MAX               (127)
#endif
#ifndef INT16_MAX
#define INT16_MAX              (32767)
#endif
#ifndef INT32_MAX
#define INT32_MAX              (2147483647)
#endif
#ifndef UINT8_MAX
#define UINT8_MAX              (255U)
#endif
#ifndef UINT16_MAX
#define UINT16_MAX             (65535U)
#endif
#ifndef UINT32_MAX
#define UINT32_MAX             (4294967295U)
#endif#ifndef SIZE_MAX
#define SIZE_MAX               (~(size_t)0)
#endif#endif /* ! C99 */#endif /* ! FLEXINT_H *//* begin standard C++ headers. *//* TODO: this is always defined, so inline it */
#define yyconst const#if defined(__GNUC__) && __GNUC__ >= 3
#define yynoreturn __attribute__((__noreturn__))
#else
#define yynoreturn
#endif/* Returned upon end-of-file. */
#define YY_NULL 0/* Promotes a possibly negative, possibly signed char to an*   integer in range [0..255] for use as an array index.*/
#define YY_SC_TO_UI(c) ((YY_CHAR) (c))/* Enter a start condition.  This macro really ought to take a parameter,* but we do it the disgusting crufty way forced on us by the ()-less* definition of BEGIN.*/
#define BEGIN (yy_start) = 1 + 2 *
/* Translate the current start state into a value that can be later handed* to BEGIN to return to the state.  The YYSTATE alias is for lex* compatibility.*/
#define YY_START (((yy_start) - 1) / 2)
#define YYSTATE YY_START
/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
/* Special action meaning "start processing a new file". */
#define YY_NEW_FILE yyrestart( yyin  )
#define YY_END_OF_BUFFER_CHAR 0/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
#ifdef __ia64__
/* On IA-64, the buffer size is 16k, not 8k.* Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.* Ditto for the __ia64__ case accordingly.*/
#define YY_BUF_SIZE 32768
#else
#define YY_BUF_SIZE 16384
#endif /* __ia64__ */
#endif/* The state buf must be large enough to hold one state per character in the main buffer.*/
#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))#ifndef YY_TYPEDEF_YY_BUFFER_STATE
#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef size_t yy_size_t;
#endifextern int yyleng;extern FILE *yyin, *yyout;#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2#define YY_LESS_LINENO(n)#define YY_LINENO_REWIND_TO(ptr)/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \do \{ \/* Undo effects of setting up yytext. */ \int yyless_macro_arg = (n); \YY_LESS_LINENO(yyless_macro_arg);\*yy_cp = (yy_hold_char); \YY_RESTORE_YY_MORE_OFFSET \(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \YY_DO_BEFORE_ACTION; /* set up yytext again */ \} \while ( 0 )
#define unput(c) yyunput( c, (yytext_ptr)  )#ifndef YY_STRUCT_YY_BUFFER_STATE
#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state{FILE *yy_input_file;char *yy_ch_buf;		/* input buffer */char *yy_buf_pos;		/* current position in input buffer *//* Size of input buffer in bytes, not including room for EOB* characters.*/int yy_buf_size;/* Number of characters read into yy_ch_buf, not including EOB* characters.*/int yy_n_chars;/* Whether we "own" the buffer - i.e., we know we created it,* and can realloc() it to grow it, and should free() it to* delete it.*/int yy_is_our_buffer;/* Whether this is an "interactive" input source; if so, and* if we're using stdio for input, then we want to use getc()* instead of fread(), to make sure we stop fetching input after* each newline.*/int yy_is_interactive;/* Whether we're considered to be at the beginning of a line.* If so, '^' rules will be active on the next match, otherwise* not.*/int yy_at_bol;int yy_bs_lineno; /**< The line count. */int yy_bs_column; /**< The column count. *//* Whether to try to fill the input buffer when we reach the* end of it.*/int yy_fill_buffer;int yy_buffer_status;#define YY_BUFFER_NEW 0
#define YY_BUFFER_NORMAL 1/* When an EOF's been seen but there's still some text to process* then we mark the buffer as YY_EOF_PENDING, to indicate that we* shouldn't try reading from the input source any more.  We might* still have a bunch of tokens to match, though, because of* possible backing-up.** When we actually see the EOF, we change the status to "new"* (via yyrestart()), so that the user can continue scanning by* just pointing yyin at a new input file.*/
#define YY_BUFFER_EOF_PENDING 2};
#endif /* !YY_STRUCT_YY_BUFFER_STATE *//* Stack of input buffers. */
static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. *//* We provide macros for accessing buffer states in case in the* future we want to put the buffer states in a more general* "scanner state".** Returns the top of the stack, or NULL.*/
#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \? (yy_buffer_stack)[(yy_buffer_stack_top)] \: NULL)
/* Same as previous macro, but useful when we know that the buffer stack is not* NULL or when we need an lvalue. For internal use only.*/
#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]/* yy_hold_char holds the character lost when yytext is formed. */
static char yy_hold_char;
static int yy_n_chars;		/* number of characters read into yy_ch_buf */
int yyleng;/* Points to current character in buffer. */
static char *yy_c_buf_p = NULL;
static int yy_init = 0;		/* whether we need to initialize */
static int yy_start = 0;	/* start state number *//* Flag which is used to allow yywrap()'s to do buffer switches* instead of setting up a fresh yyin.  A bit of a hack ...*/
static int yy_did_buffer_switch_on_eof;void yyrestart ( FILE *input_file  );
void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer  );
YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size  );
void yy_delete_buffer ( YY_BUFFER_STATE b  );
void yy_flush_buffer ( YY_BUFFER_STATE b  );
void yypush_buffer_state ( YY_BUFFER_STATE new_buffer  );
void yypop_buffer_state ( void );static void yyensure_buffer_stack ( void );
static void yy_load_buffer_state ( void );
static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file  );
#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER )YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size  );
YY_BUFFER_STATE yy_scan_string ( const char *yy_str  );
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len  );void *yyalloc ( yy_size_t  );
void *yyrealloc ( void *, yy_size_t  );
void yyfree ( void *  );#define yy_new_buffer yy_create_buffer
#define yy_set_interactive(is_interactive) \{ \if ( ! YY_CURRENT_BUFFER ){ \yyensure_buffer_stack (); \YY_CURRENT_BUFFER_LVALUE =    \yy_create_buffer( yyin, YY_BUF_SIZE ); \} \YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \}
#define yy_set_bol(at_bol) \{ \if ( ! YY_CURRENT_BUFFER ){\yyensure_buffer_stack (); \YY_CURRENT_BUFFER_LVALUE =    \yy_create_buffer( yyin, YY_BUF_SIZE ); \} \YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \}
#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)/* Begin user sect3 */
typedef flex_uint8_t YY_CHAR;FILE *yyin = NULL, *yyout = NULL;typedef int yy_state_type;extern int yylineno;
int yylineno = 1;extern char *yytext;
#ifdef yytext_ptr
#undef yytext_ptr
#endif
#define yytext_ptr yytextstatic yy_state_type yy_get_previous_state ( void );
static yy_state_type yy_try_NUL_trans ( yy_state_type current_state  );
static int yy_get_next_buffer ( void );
static void yynoreturn yy_fatal_error ( const char* msg  );/* Done after the current pattern has been matched and before the* corresponding action - sets up yytext.*/
#define YY_DO_BEFORE_ACTION \(yytext_ptr) = yy_bp; \yyleng = (int) (yy_cp - yy_bp); \(yy_hold_char) = *yy_cp; \*yy_cp = '\0'; \(yy_c_buf_p) = yy_cp;
#define YY_NUM_RULES 4
#define YY_END_OF_BUFFER 5
/* This struct is not used in this scanner,but its presence is necessary. */
struct yy_trans_info{flex_int32_t yy_verify;flex_int32_t yy_nxt;};
static const flex_int16_t yy_accept[9] ={   0,0,    0,    5,    3,    2,    1,    1,    0} ;static const YY_CHAR yy_ec[256] ={   0,1,    1,    1,    1,    1,    1,    1,    1,    1,    2,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    3,    3,    3,    3,    3,    3,3,    3,    3,    3,    3,    3,    3,    3,    3,    3,3,    3,    3,    3,    3,    3,    3,    3,    3,    3,1,    1,    1,    1,    1,    1,    3,    3,    3,    3,3,    3,    3,    3,    3,    3,    3,    3,    3,    3,3,    3,    3,    3,    3,    3,    3,    3,    3,    3,3,    3,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1,    1,    1,    1,    1,    1,1,    1,    1,    1,    1} ;static const YY_CHAR yy_meta[4] ={   0,1,    1,    2} ;static const flex_int16_t yy_base[10] ={   0,0,    0,    5,    6,    6,    0,    0,    6,    2} ;static const flex_int16_t yy_def[10] ={   0,8,    1,    8,    8,    8,    9,    9,    0,    8} ;static const flex_int16_t yy_nxt[10] ={   0,4,    5,    6,    7,    8,    3,    8,    8,    8} ;static const flex_int16_t yy_chk[10] ={   0,1,    1,    1,    9,    3,    8,    8,    8,    8} ;static yy_state_type yy_last_accepting_state;
static char *yy_last_accepting_cpos;extern int yy_flex_debug;
int yy_flex_debug = 0;/* The intent behind this definition is that it'll catch* any uses of REJECT which flex missed.*/
#define REJECT reject_used_but_not_detected
#define yymore() yymore_used_but_not_detected
#define YY_MORE_ADJ 0
#define YY_RESTORE_YY_MORE_OFFSET
char *yytext;
#line 1 "2.l"
/* just like Unix wc */
#line 3 "2.l"
int chars = 0;
int words = 0;
int lines = 0;
#line 445 "lex.yy.c"
#line 446 "lex.yy.c"#define INITIAL 0#ifndef YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way* down here because we want the user's section 1 to have been scanned first.* The user has a chance to override it with an option.*/
#include <unistd.h>
#endif#ifndef YY_EXTRA_TYPE
#define YY_EXTRA_TYPE void *
#endifstatic int yy_init_globals ( void );/* Accessor methods to globals.These are made visible to non-reentrant scanners for convenience. */int yylex_destroy ( void );int yyget_debug ( void );void yyset_debug ( int debug_flag  );YY_EXTRA_TYPE yyget_extra ( void );void yyset_extra ( YY_EXTRA_TYPE user_defined  );FILE *yyget_in ( void );void yyset_in  ( FILE * _in_str  );FILE *yyget_out ( void );void yyset_out  ( FILE * _out_str  );int yyget_leng ( void );char *yyget_text ( void );int yyget_lineno ( void );void yyset_lineno ( int _line_number  );/* Macros after this point can all be overridden by user definitions in* section 1.*/#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
extern "C" int yywrap ( void );
#else
extern int yywrap ( void );
#endif
#endif#ifndef YY_NO_UNPUTstatic void yyunput ( int c, char *buf_ptr  );#endif#ifndef yytext_ptr
static void yy_flex_strncpy ( char *, const char *, int );
#endif#ifdef YY_NEED_STRLEN
static int yy_flex_strlen ( const char * );
#endif#ifndef YY_NO_INPUT
#ifdef __cplusplus
static int yyinput ( void );
#else
static int input ( void );
#endif#endif/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#ifdef __ia64__
/* On IA-64, the buffer size is 16k, not 8k */
#define YY_READ_BUF_SIZE 16384
#else
#define YY_READ_BUF_SIZE 8192
#endif /* __ia64__ */
#endif/* Copy whatever the last rule matched to the standard output. */
#ifndef ECHO
/* This used to be an fputs(), but since the string might contain NUL's,* we now use fwrite().*/
#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
#endif/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,* is returned in "result".*/
#ifndef YY_INPUT
#define YY_INPUT(buf,result,max_size) \if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \{ \int c = '*'; \int n; \for ( n = 0; n < max_size && \(c = getc( yyin )) != EOF && c != '\n'; ++n ) \buf[n] = (char) c; \if ( c == '\n' ) \buf[n++] = (char) c; \if ( c == EOF && ferror( yyin ) ) \YY_FATAL_ERROR( "input in flex scanner failed" ); \result = n; \} \else \{ \errno=0; \while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \{ \if( errno != EINTR) \{ \YY_FATAL_ERROR( "input in flex scanner failed" ); \break; \} \errno=0; \clearerr(yyin); \} \}\
\

#endif/* No semi-colon after return; correct usage is to write "yyterminate();" -* we don't want an extra ';' after the "return" because that will cause* some compilers to complain about unreachable statements.*/
#ifndef yyterminate
#define yyterminate() return YY_NULL
#endif/* Number of entries by which start-condition stack grows. */
#ifndef YY_START_STACK_INCR
#define YY_START_STACK_INCR 25
#endif/* Report a fatal error. */
#ifndef YY_FATAL_ERROR
#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
#endif/* end tables serialization structures and prototypes *//* Default declaration of generated scanner - a define so the user can* easily add parameters.*/
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1extern int yylex (void);#define YY_DECL int yylex (void)
#endif /* !YY_DECL *//* Code executed at the beginning of each rule, after yytext and yyleng* have been set up.*/
#ifndef YY_USER_ACTION
#define YY_USER_ACTION
#endif/* Code executed at the end of each rule. */
#ifndef YY_BREAK
#define YY_BREAK /*LINTED*/break;
#endif#define YY_RULE_SETUP \YY_USER_ACTION/** The main scanner function which does all the work.*/
YY_DECL
{yy_state_type yy_current_state;char *yy_cp, *yy_bp;int yy_act;if ( !(yy_init) ){(yy_init) = 1;#ifdef YY_USER_INITYY_USER_INIT;
#endifif ( ! (yy_start) )(yy_start) = 1;	/* first start state */if ( ! yyin )yyin = stdin;if ( ! yyout )yyout = stdout;if ( ! YY_CURRENT_BUFFER ) {yyensure_buffer_stack ();YY_CURRENT_BUFFER_LVALUE =yy_create_buffer( yyin, YY_BUF_SIZE );}yy_load_buffer_state(  );}{
#line 7 "2.l"#line 665 "lex.yy.c"while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */{yy_cp = (yy_c_buf_p);/* Support of yytext. */*yy_cp = (yy_hold_char);/* yy_bp points to the position in yy_ch_buf of the start of* the current run.*/yy_bp = yy_cp;yy_current_state = (yy_start);
yy_match:do{YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;if ( yy_accept[yy_current_state] ){(yy_last_accepting_state) = yy_current_state;(yy_last_accepting_cpos) = yy_cp;}while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ){yy_current_state = (int) yy_def[yy_current_state];if ( yy_current_state >= 9 )yy_c = yy_meta[yy_c];}yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];++yy_cp;}while ( yy_base[yy_current_state] != 6 );yy_find_action:yy_act = yy_accept[yy_current_state];if ( yy_act == 0 ){ /* have to back up */yy_cp = (yy_last_accepting_cpos);yy_current_state = (yy_last_accepting_state);yy_act = yy_accept[yy_current_state];}YY_DO_BEFORE_ACTION;do_action:	/* This label is used only to access EOF actions. */switch ( yy_act ){ /* beginning of action switch */case 0: /* must back up *//* undo the effects of YY_DO_BEFORE_ACTION */*yy_cp = (yy_hold_char);yy_cp = (yy_last_accepting_cpos);yy_current_state = (yy_last_accepting_state);goto yy_find_action;case 1:
YY_RULE_SETUP
#line 8 "2.l"
{ words++; chars += strlen(yytext); }YY_BREAK
case 2:
/* rule 2 can match eol */
YY_RULE_SETUP
#line 9 "2.l"
{ chars++; lines++; }YY_BREAK
case 3:
YY_RULE_SETUP
#line 10 "2.l"
{ chars++; }YY_BREAK
case 4:
YY_RULE_SETUP
#line 11 "2.l"
ECHO;YY_BREAK
#line 743 "lex.yy.c"
case YY_STATE_EOF(INITIAL):yyterminate();case YY_END_OF_BUFFER:{/* Amount of text matched not including the EOB char. */int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;/* Undo the effects of YY_DO_BEFORE_ACTION. */*yy_cp = (yy_hold_char);YY_RESTORE_YY_MORE_OFFSETif ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ){/* We're scanning a new file or input source.  It's* possible that this happened because the user* just pointed yyin at a new source and called* yylex().  If so, then we have to assure* consistency between YY_CURRENT_BUFFER and our* globals.  Here is the right place to do so, because* this is the first action (other than possibly a* back-up) that will match for the new input source.*/(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;}/* Note that here we test for yy_c_buf_p "<=" to the position* of the first EOB in the buffer, since yy_c_buf_p will* already have been incremented past the NUL character* (since all states make transitions on EOB to the* end-of-buffer state).  Contrast this with the test* in input().*/if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ){ /* This was really a NUL. */yy_state_type yy_next_state;(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;yy_current_state = yy_get_previous_state(  );/* Okay, we're now positioned to make the NUL* transition.  We couldn't have* yy_get_previous_state() go ahead and do it* for us because it doesn't know how to deal* with the possibility of jamming (and we don't* want to build jamming into it because then it* will run more slowly).*/yy_next_state = yy_try_NUL_trans( yy_current_state );yy_bp = (yytext_ptr) + YY_MORE_ADJ;if ( yy_next_state ){/* Consume the NUL. */yy_cp = ++(yy_c_buf_p);yy_current_state = yy_next_state;goto yy_match;}else{yy_cp = (yy_c_buf_p);goto yy_find_action;}}else switch ( yy_get_next_buffer(  ) ){case EOB_ACT_END_OF_FILE:{(yy_did_buffer_switch_on_eof) = 0;if ( yywrap(  ) ){/* Note: because we've taken care in* yy_get_next_buffer() to have set up* yytext, we can now set up* yy_c_buf_p so that if some total* hoser (like flex itself) wants to* call the scanner after we return the* YY_NULL, it'll still work - another* YY_NULL will get returned.*/(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;yy_act = YY_STATE_EOF(YY_START);goto do_action;}else{if ( ! (yy_did_buffer_switch_on_eof) )YY_NEW_FILE;}break;}case EOB_ACT_CONTINUE_SCAN:(yy_c_buf_p) =(yytext_ptr) + yy_amount_of_matched_text;yy_current_state = yy_get_previous_state(  );yy_cp = (yy_c_buf_p);yy_bp = (yytext_ptr) + YY_MORE_ADJ;goto yy_match;case EOB_ACT_LAST_MATCH:(yy_c_buf_p) =&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];yy_current_state = yy_get_previous_state(  );yy_cp = (yy_c_buf_p);yy_bp = (yytext_ptr) + YY_MORE_ADJ;goto yy_find_action;}break;}default:YY_FATAL_ERROR("fatal flex scanner internal error--no action found" );} /* end of action switch */} /* end of scanning one token */} /* end of user's declarations */
} /* end of yylex *//* yy_get_next_buffer - try to read in a new buffer** Returns a code representing an action:*	EOB_ACT_LAST_MATCH -*	EOB_ACT_CONTINUE_SCAN - continue scanning from current position*	EOB_ACT_END_OF_FILE - end of file*/
static int yy_get_next_buffer (void)
{char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;char *source = (yytext_ptr);int number_to_move, i;int ret_val;if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )YY_FATAL_ERROR("fatal flex scanner internal error--end of buffer missed" );if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ){ /* Don't try to fill the buffer, so this is an EOF. */if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ){/* We matched a single character, the EOB, so* treat this as a final EOF.*/return EOB_ACT_END_OF_FILE;}else{/* We matched some text prior to the EOB, first* process it.*/return EOB_ACT_LAST_MATCH;}}/* Try to read more data. *//* First move last chars to start of buffer. */number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1);for ( i = 0; i < number_to_move; ++i )*(dest++) = *(source++);if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )/* don't do the read, it's not guaranteed to return an EOF,* just force an EOF*/YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;else{int num_to_read =YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;while ( num_to_read <= 0 ){ /* Not enough room in the buffer - grow it. *//* just a shorter name for the current buffer */YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;int yy_c_buf_p_offset =(int) ((yy_c_buf_p) - b->yy_ch_buf);if ( b->yy_is_our_buffer ){int new_size = b->yy_buf_size * 2;if ( new_size <= 0 )b->yy_buf_size += b->yy_buf_size / 8;elseb->yy_buf_size *= 2;b->yy_ch_buf = (char *)/* Include room in for 2 EOB chars. */yyrealloc( (void *) b->yy_ch_buf,(yy_size_t) (b->yy_buf_size + 2)  );}else/* Can't grow it, we don't own it. */b->yy_ch_buf = NULL;if ( ! b->yy_ch_buf )YY_FATAL_ERROR("fatal error - scanner input buffer overflow" );(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -number_to_move - 1;}if ( num_to_read > YY_READ_BUF_SIZE )num_to_read = YY_READ_BUF_SIZE;/* Read in more data. */YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),(yy_n_chars), num_to_read );YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);}if ( (yy_n_chars) == 0 ){if ( number_to_move == YY_MORE_ADJ ){ret_val = EOB_ACT_END_OF_FILE;yyrestart( yyin  );}else{ret_val = EOB_ACT_LAST_MATCH;YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =YY_BUFFER_EOF_PENDING;}}elseret_val = EOB_ACT_CONTINUE_SCAN;if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {/* Extend the array by 50%, plus the number we really need. */int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size  );if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );/* "- 2" to take care of EOB's */YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);}(yy_n_chars) += number_to_move;YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];return ret_val;
}/* yy_get_previous_state - get the state just before the EOB char was reached */static yy_state_type yy_get_previous_state (void)
{yy_state_type yy_current_state;char *yy_cp;yy_current_state = (yy_start);for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ){YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);if ( yy_accept[yy_current_state] ){(yy_last_accepting_state) = yy_current_state;(yy_last_accepting_cpos) = yy_cp;}while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ){yy_current_state = (int) yy_def[yy_current_state];if ( yy_current_state >= 9 )yy_c = yy_meta[yy_c];}yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];}return yy_current_state;
}/* yy_try_NUL_trans - try to make a transition on the NUL character** synopsis*	next_state = yy_try_NUL_trans( current_state );*/static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
{int yy_is_jam;char *yy_cp = (yy_c_buf_p);YY_CHAR yy_c = 1;if ( yy_accept[yy_current_state] ){(yy_last_accepting_state) = yy_current_state;(yy_last_accepting_cpos) = yy_cp;}while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ){yy_current_state = (int) yy_def[yy_current_state];if ( yy_current_state >= 9 )yy_c = yy_meta[yy_c];}yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];yy_is_jam = (yy_current_state == 8);return yy_is_jam ? 0 : yy_current_state;
}#ifndef YY_NO_UNPUTstatic void yyunput (int c, char * yy_bp )
{char *yy_cp;yy_cp = (yy_c_buf_p);/* undo effects of setting up yytext */*yy_cp = (yy_hold_char);if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ){ /* need to shift things up to make room *//* +2 for EOB chars. */int number_to_move = (yy_n_chars) + 2;char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];char *source =&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )*--dest = *--source;yy_cp += (int) (dest - source);yy_bp += (int) (dest - source);YY_CURRENT_BUFFER_LVALUE->yy_n_chars =(yy_n_chars) = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size;if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )YY_FATAL_ERROR( "flex scanner push-back overflow" );}*--yy_cp = (char) c;(yytext_ptr) = yy_bp;(yy_hold_char) = *yy_cp;(yy_c_buf_p) = yy_cp;
}#endif#ifndef YY_NO_INPUT
#ifdef __cplusplusstatic int yyinput (void)
#elsestatic int input  (void)
#endif{int c;*(yy_c_buf_p) = (yy_hold_char);if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ){/* yy_c_buf_p now points to the character we want to return.* If this occurs *before* the EOB characters, then it's a* valid NUL; if not, then we've hit the end of the buffer.*/if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )/* This was really a NUL. */*(yy_c_buf_p) = '\0';else{ /* need more input */int offset = (int) ((yy_c_buf_p) - (yytext_ptr));++(yy_c_buf_p);switch ( yy_get_next_buffer(  ) ){case EOB_ACT_LAST_MATCH:/* This happens because yy_g_n_b()* sees that we've accumulated a* token and flags that we need to* try matching the token before* proceeding.  But for input(),* there's no matching to consider.* So convert the EOB_ACT_LAST_MATCH* to EOB_ACT_END_OF_FILE.*//* Reset buffer status. */yyrestart( yyin );/*FALLTHROUGH*/case EOB_ACT_END_OF_FILE:{if ( yywrap(  ) )return 0;if ( ! (yy_did_buffer_switch_on_eof) )YY_NEW_FILE;
#ifdef __cplusplusreturn yyinput();
#elsereturn input();
#endif}case EOB_ACT_CONTINUE_SCAN:(yy_c_buf_p) = (yytext_ptr) + offset;break;}}}c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */*(yy_c_buf_p) = '\0';	/* preserve yytext */(yy_hold_char) = *++(yy_c_buf_p);return c;
}
#endif	/* ifndef YY_NO_INPUT *//** Immediately switch to a different input stream.* @param input_file A readable stream.* * @note This function does not reset the start condition to @c INITIAL .*/void yyrestart  (FILE * input_file )
{if ( ! YY_CURRENT_BUFFER ){yyensure_buffer_stack ();YY_CURRENT_BUFFER_LVALUE =yy_create_buffer( yyin, YY_BUF_SIZE );}yy_init_buffer( YY_CURRENT_BUFFER, input_file );yy_load_buffer_state(  );
}/** Switch to a different input buffer.* @param new_buffer The new input buffer.* */void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
{/* TODO. We should be able to replace this entire function body* with*		yypop_buffer_state();*		yypush_buffer_state(new_buffer);*/yyensure_buffer_stack ();if ( YY_CURRENT_BUFFER == new_buffer )return;if ( YY_CURRENT_BUFFER ){/* Flush out information for old buffer. */*(yy_c_buf_p) = (yy_hold_char);YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);}YY_CURRENT_BUFFER_LVALUE = new_buffer;yy_load_buffer_state(  );/* We don't actually know whether we did this switch during* EOF (yywrap()) processing, but the only time this flag* is looked at is after yywrap() is called, so it's safe* to go ahead and always set it.*/(yy_did_buffer_switch_on_eof) = 1;
}static void yy_load_buffer_state  (void)
{(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;(yy_hold_char) = *(yy_c_buf_p);
}/** Allocate and initialize an input buffer state.* @param file A readable stream.* @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.* * @return the allocated buffer state.*/YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
{YY_BUFFER_STATE b;b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state )  );if ( ! b )YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );b->yy_buf_size = size;/* yy_ch_buf has to be 2 characters longer than the size given because* we need to put in 2 end-of-buffer characters.*/b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2)  );if ( ! b->yy_ch_buf )YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );b->yy_is_our_buffer = 1;yy_init_buffer( b, file );return b;
}/** Destroy the buffer.* @param b a buffer created with yy_create_buffer()* */void yy_delete_buffer (YY_BUFFER_STATE  b )
{if ( ! b )return;if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;if ( b->yy_is_our_buffer )yyfree( (void *) b->yy_ch_buf  );yyfree( (void *) b  );
}/* Initializes or reinitializes a buffer.* This function is sometimes called more than once on the same buffer,* such as during a yyrestart() or at EOF.*/static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file ){int oerrno = errno;yy_flush_buffer( b );b->yy_input_file = file;b->yy_fill_buffer = 1;/* If b is the current buffer, then yy_init_buffer was _probably_* called from yyrestart() or through yy_get_next_buffer.* In that case, we don't want to reset the lineno or column.*/if (b != YY_CURRENT_BUFFER){b->yy_bs_lineno = 1;b->yy_bs_column = 0;}b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;errno = oerrno;
}/** Discard all buffered characters. On the next scan, YY_INPUT will be called.* @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.* */void yy_flush_buffer (YY_BUFFER_STATE  b )
{if ( ! b )return;b->yy_n_chars = 0;/* We always need two end-of-buffer characters.  The first causes* a transition to the end-of-buffer state.  The second causes* a jam in that state.*/b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;b->yy_buf_pos = &b->yy_ch_buf[0];b->yy_at_bol = 1;b->yy_buffer_status = YY_BUFFER_NEW;if ( b == YY_CURRENT_BUFFER )yy_load_buffer_state(  );
}/** Pushes the new state onto the stack. The new state becomes*  the current state. This function will allocate the stack*  if necessary.*  @param new_buffer The new state.*  */
void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
{if (new_buffer == NULL)return;yyensure_buffer_stack();/* This block is copied from yy_switch_to_buffer. */if ( YY_CURRENT_BUFFER ){/* Flush out information for old buffer. */*(yy_c_buf_p) = (yy_hold_char);YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);}/* Only push if top exists. Otherwise, replace top. */if (YY_CURRENT_BUFFER)(yy_buffer_stack_top)++;YY_CURRENT_BUFFER_LVALUE = new_buffer;/* copied from yy_switch_to_buffer. */yy_load_buffer_state(  );(yy_did_buffer_switch_on_eof) = 1;
}/** Removes and deletes the top of the stack, if present.*  The next element becomes the new top.*  */
void yypop_buffer_state (void)
{if (!YY_CURRENT_BUFFER)return;yy_delete_buffer(YY_CURRENT_BUFFER );YY_CURRENT_BUFFER_LVALUE = NULL;if ((yy_buffer_stack_top) > 0)--(yy_buffer_stack_top);if (YY_CURRENT_BUFFER) {yy_load_buffer_state(  );(yy_did_buffer_switch_on_eof) = 1;}
}/* Allocates the stack if it does not exist.*  Guarantees space for at least one push.*/
static void yyensure_buffer_stack (void)
{yy_size_t num_to_alloc;if (!(yy_buffer_stack)) {/* First allocation is just for 2 elements, since we don't know if this* scanner will even need a stack. We use 2 instead of 1 to avoid an* immediate realloc on the next call.*/num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc(num_to_alloc * sizeof(struct yy_buffer_state*));if ( ! (yy_buffer_stack) )YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));(yy_buffer_stack_max) = num_to_alloc;(yy_buffer_stack_top) = 0;return;}if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){/* Increase the buffer to prepare for a possible push. */yy_size_t grow_size = 8 /* arbitrary grow size */;num_to_alloc = (yy_buffer_stack_max) + grow_size;(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc((yy_buffer_stack),num_to_alloc * sizeof(struct yy_buffer_state*));if ( ! (yy_buffer_stack) )YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );/* zero only the new slots.*/memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));(yy_buffer_stack_max) = num_to_alloc;}
}/** Setup the input buffer state to scan directly from a user-specified character buffer.* @param base the character buffer* @param size the size in bytes of the character buffer* * @return the newly allocated buffer state object.*/
YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
{YY_BUFFER_STATE b;if ( size < 2 ||base[size-2] != YY_END_OF_BUFFER_CHAR ||base[size-1] != YY_END_OF_BUFFER_CHAR )/* They forgot to leave room for the EOB's. */return NULL;b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state )  );if ( ! b )YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );b->yy_buf_size = (int) (size - 2);	/* "- 2" to take care of EOB's */b->yy_buf_pos = b->yy_ch_buf = base;b->yy_is_our_buffer = 0;b->yy_input_file = NULL;b->yy_n_chars = b->yy_buf_size;b->yy_is_interactive = 0;b->yy_at_bol = 1;b->yy_fill_buffer = 0;b->yy_buffer_status = YY_BUFFER_NEW;yy_switch_to_buffer( b  );return b;
}/** Setup the input buffer state to scan a string. The next call to yylex() will* scan from a @e copy of @a str.* @param yystr a NUL-terminated string to scan* * @return the newly allocated buffer state object.* @note If you want to scan bytes that may contain NUL values, then use*       yy_scan_bytes() instead.*/
YY_BUFFER_STATE yy_scan_string (const char * yystr )
{return yy_scan_bytes( yystr, (int) strlen(yystr) );
}/** Setup the input buffer state to scan the given bytes. The next call to yylex() will* scan from a @e copy of @a bytes.* @param yybytes the byte buffer to scan* @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.* * @return the newly allocated buffer state object.*/
YY_BUFFER_STATE yy_scan_bytes  (const char * yybytes, int  _yybytes_len )
{YY_BUFFER_STATE b;char *buf;yy_size_t n;int i;/* Get memory for full buffer, including space for trailing EOB's. */n = (yy_size_t) (_yybytes_len + 2);buf = (char *) yyalloc( n  );if ( ! buf )YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );for ( i = 0; i < _yybytes_len; ++i )buf[i] = yybytes[i];buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;b = yy_scan_buffer( buf, n );if ( ! b )YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );/* It's okay to grow etc. this buffer, and we should throw it* away when we're done.*/b->yy_is_our_buffer = 1;return b;
}#ifndef YY_EXIT_FAILURE
#define YY_EXIT_FAILURE 2
#endifstatic void yynoreturn yy_fatal_error (const char* msg )
{fprintf( stderr, "%s\n", msg );exit( YY_EXIT_FAILURE );
}/* Redefine yyless() so it works in section 3 code. */#undef yyless
#define yyless(n) \do \{ \/* Undo effects of setting up yytext. */ \int yyless_macro_arg = (n); \YY_LESS_LINENO(yyless_macro_arg);\yytext[yyleng] = (yy_hold_char); \(yy_c_buf_p) = yytext + yyless_macro_arg; \(yy_hold_char) = *(yy_c_buf_p); \*(yy_c_buf_p) = '\0'; \yyleng = yyless_macro_arg; \} \while ( 0 )/* Accessor  methods (get/set functions) to struct members. *//** Get the current line number.* */
int yyget_lineno  (void)
{return yylineno;
}/** Get the input stream.* */
FILE *yyget_in  (void)
{return yyin;
}/** Get the output stream.* */
FILE *yyget_out  (void)
{return yyout;
}/** Get the length of the current token.* */
int yyget_leng  (void)
{return yyleng;
}/** Get the current token.* */char *yyget_text  (void)
{return yytext;
}/** Set the current line number.* @param _line_number line number* */
void yyset_lineno (int  _line_number )
{yylineno = _line_number;
}/** Set the input stream. This does not discard the current* input buffer.* @param _in_str A readable stream.* * @see yy_switch_to_buffer*/
void yyset_in (FILE *  _in_str )
{yyin = _in_str ;
}void yyset_out (FILE *  _out_str )
{yyout = _out_str ;
}int yyget_debug  (void)
{return yy_flex_debug;
}void yyset_debug (int  _bdebug )
{yy_flex_debug = _bdebug ;
}static int yy_init_globals (void)
{/* Initialization is the same as for the non-reentrant scanner.* This function is called from yylex_destroy(), so don't allocate here.*/(yy_buffer_stack) = NULL;(yy_buffer_stack_top) = 0;(yy_buffer_stack_max) = 0;(yy_c_buf_p) = NULL;(yy_init) = 0;(yy_start) = 0;/* Defined in main.c */
#ifdef YY_STDINITyyin = stdin;yyout = stdout;
#elseyyin = NULL;yyout = NULL;
#endif/* For future reference: Set errno on error, since we are called by* yylex_init()*/return 0;
}/* yylex_destroy is for both reentrant and non-reentrant scanners. */
int yylex_destroy  (void)
{/* Pop the buffer stack, destroying each element. */while(YY_CURRENT_BUFFER){yy_delete_buffer( YY_CURRENT_BUFFER  );YY_CURRENT_BUFFER_LVALUE = NULL;yypop_buffer_state();}/* Destroy the stack itself. */yyfree((yy_buffer_stack) );(yy_buffer_stack) = NULL;/* Reset the globals. This is important in a non-reentrant scanner so the next time* yylex() is called, initialization will occur. */yy_init_globals( );return 0;
}/** Internal utility routines.*/#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, const char * s2, int n )
{int i;for ( i = 0; i < n; ++i )s1[i] = s2[i];
}
#endif#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (const char * s )
{int n;for ( n = 0; s[n]; ++n );return n;
}
#endifvoid *yyalloc (yy_size_t  size )
{return malloc(size);
}void *yyrealloc  (void * ptr, yy_size_t  size )
{/* The cast to (char *) in the following accommodates both* implementations that use char* generic pointers, and those* that use void* generic pointers.  It works with the latter* because both ANSI C and C++ allow castless assignment from* any pointer type to void*, and deal with argument conversions* as though doing an assignment.*/return realloc(ptr, size);
}void yyfree (void * ptr )
{free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
}#define YYTABLES_NAME "yytables"#line 11 "2.l"main(int argc, char **argv)
{yylex();printf("%8d%8d%8d\n", lines, words, chars);
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/14068.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/14068.shtml
英文地址,請注明出處:http://en.pswp.cn/web/14068.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

K8S認證|CKA題庫+答案| 5. 創建 Ingress

5 . 創建 Ingress 您必須在以下Cluster/Node上完成此考題&#xff1a; Cluster Master node Worker node k8s master …

基于Tensorflow卷積神經網絡垃圾智能分類系統

歡迎大家點贊、收藏、關注、評論啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代碼。 文章目錄 一項目簡介 二、功能三、系統四. 總結 一項目簡介 一、項目背景與意義 隨著城市化進程的加速&#xff0c;垃圾問題日益嚴重&#xff0c;垃圾分類成為解決這一問題的關…

淺談金融行業數據安全分類分級

數據安全管理是一項從上而下的、多方配合開展的工作。在進行數據安全管理組織架構建設時&#xff0c;需要從上而下建設&#xff1b;從而全面推動數據安全管理工作的執行和落地&#xff1b;以保證數據安全的合法合規、并長效推動業務的發展和穩定運行。 金融行業機構應設立數據…

「項目」負載均衡在線OJ(ONLINE_JUDGE)系統

&#x1f436;博主主頁&#xff1a;??. 一懷明月? ???&#x1f525;專欄系列&#xff1a;線性代數&#xff0c;C初學者入門訓練&#xff0c;題解C&#xff0c;C的使用文章&#xff0c;「初學」C&#xff0c;linux &#x1f525;座右銘&#xff1a;“不要等到什么都沒有了…

機器學習系列--強化學習

強化學習&#xff08;Reinforcement Learning&#xff0c;RL&#xff09;是一種機器學習方法&#xff0c;旨在通過智能體&#xff08;Agent&#xff09;在環境&#xff08;Environment&#xff09;中采取行動&#xff08;Actions&#xff09;并獲取反饋&#xff08;Reward&…

技術驅動未來,全面揭秘 Sui 的生態發展和布局

在不到一年的時間里&#xff0c;由 Mysten Labs 團隊創立的 Layer1 區塊鏈 Sui 迅速崛起&#xff0c;成功躍升至去中心化金融&#xff08;DeFi&#xff09;的前十名。根據 DeFi Llama 的數據&#xff0c;Sui的總鎖定價值&#xff08;TVL&#xff09;在短短四個月內增長超過 100…

13-云原生監控體系-Mysqld_exporter 監控 MySQL[部署Dashborad告警規則實戰]

文章目錄 1. 部署1.1. 二進制方式部署1.1.1. 下載1.1.2. 部署1.1.3. MySQL 服務的配置1.2 docker-compose 方式1.3 配置 Prometheus1.4 測試1.5 mysqld_exporter 命令行運行參數1.5.1. 配置格式1.5.2. 運行參數詳解1.5.3. 監控不同的集群2. Dashboard2.

【好玩的經典游戲】Docker環境下部署retroarch-web經典游戲模擬器

【好玩的經典游戲】Docker環境下部署retroarch-web經典游戲模擬器 前言一、RetroArch-web介紹二、本地環境介紹2.1 本地環境規劃2.2 本次實踐介紹三、檢查本地環境3.1 檢查系統版本3.2 檢查Docker服務狀態四、拉取鏡像五、創建retroarch-web容器5.1 創建容器5.2 查看容器狀態六…

深度學習之基于Tensorflow+Flask框架Web手寫數字識別

歡迎大家點贊、收藏、關注、評論啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代碼。 文章目錄 一項目簡介 二、功能三、系統四. 總結 一項目簡介 一、項目背景與意義 手寫數字識別是深度學習領域中的一個經典問題&#xff0c;也是計算機視覺領域的重要應用之一。…

BFT Robotics - 您的智能自動化伙伴

“買機器人&#xff0c;上BFT” 自動化和機器人技術是推動現代工業發展的重要力量。BFT Robotics以其創新的產品系列和定制化解決方案&#xff0c;為企業提供了一條通往高效、智能生產環境的道路。通過采用BFT Robotics的產品和服務&#xff0c;企業不僅能夠提高生產效率&#…

編程語言的集合判斷邏輯

當判斷一個Item是否在集合中&#xff0c;比如List&#xff0c;Map&#xff0c;Array等&#xff0c;只可以判斷真&#xff0c;不可以判斷假。 如果執著判斷&#xff0c;也可以通過設置標志位去實現&#xff0c;這樣代碼就會顯得臃腫&#xff0c;效率低下。 比如 list.forEach…

js JSON.stringify 對象轉字符串

通過 JSON.stringify() 把 JavaScript 對象轉換為字符串 注&#xff1a; 在 JSON 中&#xff0c;不允許日期對象。JSON.stringify() 函數將把任何日期轉換為字符串。在 JSON 中&#xff0c;不允許函數作為對象值。 JSON.stringify() 函數將從 JavaScript 對象刪除任何函數&am…

iView實現表格拖拽列寬度,列顯示順序及顯示字段

需要實現表格列寬度調整,選擇展示表格字段,以及顯示順序,先看效果,每次變動后保存到本地緩存中,也可以與后臺配合保存到數據庫,實現用戶自定義表格. 1.安裝vuedraggable實現拖拽 npm i vuedraggable2.新建組件 FilterColumns.vue 我這里默認把操作列放到最后一個并且不允許…

機器學習(五) -- 監督學習(3) -- 決策樹

系列文章目錄及鏈接 上篇&#xff1a;機器學習&#xff08;五&#xff09; -- 監督學習&#xff08;2&#xff09; -- 樸素貝葉斯 下篇&#xff1a;機器學習&#xff08;五&#xff09; -- 監督學習&#xff08;4&#xff09; -- 集成學習方法-隨機森林 前言 tips&#xff1a…

學習Uni-app開發小程序Day23

今天學習了將上一章的所有核算的js&#xff0c;抽離出去&#xff0c;讓在其他地方可以直接調用&#xff0c;然后和適配抖音的辦法&#xff0c;封裝網絡請求&#xff1b; 抽離公共方法 如何將公共方法抽離&#xff1f; 1、在根目錄創建一個目錄&#xff0c;一般起名是:utils 2…

物聯網網關在電梯按需維保方案中起到什么作用?梯聯網網關

為減少電梯故障和預防電梯事故&#xff0c;保障人身和財產安全&#xff0c;基于物聯網技術的電梯按需維保已在全國多地陸續推行&#xff0c;做到了電梯安全隱患預測式排查&#xff0c;處理問題更具科學性、針對性和精準性&#xff0c;有效提升了電梯運行的安全性。那么&#xf…

深度學習之基于YoloV5入侵檢測系統

歡迎大家點贊、收藏、關注、評論啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代碼。 文章目錄 一項目簡介 二、功能三、系統四. 總結 一項目簡介 一、項目背景 隨著信息技術的飛速發展&#xff0c;網絡安全問題日益凸顯。入侵檢測系統&#xff08;IDS&#xff0…

IC設計運營管理ERP適合中小型芯片公司

在數字化、智能化的今天&#xff0c;企業資源計劃(ERP)系統已成為企業管理的重要工具。特別是在中小型芯片公司中&#xff0c;IC設計運營管理ERP更是發揮著舉足輕重的作用。 首先&#xff0c;ERP系統能夠實現對企業內各種資源的集成管理&#xff0c;包括資金、人力資源、設備和…

我的第一個JAVA程序IDEA版

目錄 第一步 新建一個空項目第二步 新建模塊第三步 新建包第四步 新建類第五步 新建main方法 第一步 新建一個空項目 第二步 新建模塊 第三步 新建包 第四步 新建類 然后在包文件夾下新建類 第五步 新建main方法