青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

woaidongmao

文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
數據加載中……

flex詳解

flex
 
此篇不會講述規則表達式,自從.net流行之后,大量的原本只是在unix才使用的規則表達式現在廣泛使用在各種系統中。略.

1.內置變量
  yy_create_buffer:
見后面的緩沖管理
  yy_delete_buffer:
見后面的緩沖管理
  yy_flex_debug:
見后面的緩沖管理
  yy_init_buffer:
見后面的緩沖管理
  yy_flush_buffer:
見后面的緩沖管理
  yy_load_buffer_state:
見后面的緩沖管理
  yy_switch_to_buffer:
見后面的緩沖管理
 
  yyin:
輸入緩沖流的文件指針,可以被替換以實現解析某個自定義的文件
  yyleng:
當前匹配字串的長度
  yylex:
解析函數,接口
  yylineno:
當前匹配的文件行號
  yyout:  
輸出流的指針
  yyrestart:
手動調用yyrestart.會重啟解析
            yyrestart( yyin );
一般是打開某個文件之后,yyrestart(yyin)再解析.
  yytext
: 當前匹配的字串
  yywrap
: 解析一個文件完畢之后,會調用yywrap:返回1表示結束,0表示繼續(此時最好重新打開yyin或者重置yyin)

2. 幾個重要函數:
1). yymore(): yymore()
的含義是,當當前匹配的字串之后,想把后面配置的字串附加到這個字串后面,組成新的token返回.
 
比如:
            %%
          mega-    ECHO; yymore();
          kludge   ECHO;
 
如果:“mega-kludge" the following will write "mega-mega-kludge" to the output
 
為什么呢? 首先遇到 mega-,接著被more了一下,因此就會把kludga附加到mega-后面,而后面的kludge的動作又是打印,因此會打印出:mega-mega-kludge

2). yyless(): yyless()的含義是:當當前的匹配之后,我想只返回前面幾個字符,并且把后面回退到輸入
 
比如:
          %%
          foobar    ECHO; yyless(3);
          [a-z]+    ECHO;
        input "foobar" the following will write out     "foobarbar":
  
為什么呢? foobar輸入之后,匹配foobar,ECHO打印出來,接著yyless(3),則輸入流變為bar(yytextfoo).接著再匹配,于是匹配    [a-z]+,因此再次打印出bar.
  
3).BEGIN: flex
下一個起始解析狀態。見第3節,flex的狀態.

4).REJECT:  相當于拒絕此匹配,讓系統重新找下一個匹配。
"abcd", it
     will write "abcdabcaba" to the output:

          %%
          a        |
          ab       |
          abc      |
          abcd     ECHO; REJECT;
          .|\n     /* eat up any unmatched character */  
        
5).unput(c):
c重新放到輸入流。

6).input(): 讀取輸入流下一個字符

7).yyrestart(): 該函數迫使yylex重新解析。yyrestart有個函數指針流,可以再打開之后,重新使用yyrestart().


3.
解析源管理:
    1).
默認是從yyin獲取,而yyin則是stdout,也可以是其它文件。
        if ( ! yyin )
         yyin = stdin;
       
        if ( ! yyout )
         yyout = stdout;
   
    2).
如果你打開了一個文件,并把yyin指向此文件,則從該文件中讀取.比如:
   
main中:
     FILE* fp = NULL;
     fp = fopen("hell.txt", "r");
     yyin = fp;
    
之后再使用 yylex()
   
flexhell.txt中讀取信息并解析.
   
    3).
從字符串中解析
       
先使用下列函數,轉化緩沖,之后再使用 yylex()
       a. yy_scan_string(char*).
使用了yy_scan_string(char*)之后,flex會把char*放到yy的輸入緩沖中(會調用到yy_switch_to_buffer.)
       b. yy_scan_bytes(const char *base, int len);
       c. yy_scan_buffer(char *base, yy_size_t size)
      
這幾個函數內部都使用的是緩沖切換的創建等函數,見后面的章節.

    4).利用EOF內置規則,重新打開多個文件輸入:  
   
比如:
     <<EOF>>  {
          if ( *++filelist )
              yyin = fopen( *filelist, "r" );
          else
             yyterminate();
          }
    5).
多緩沖問題:
        a.
此問題可以按上面的 <<EOF>>或者 yywrap解決。
        b.
另外一種形式,比如:#include <iostream>或者類似于這種,這種形式的話,則不能使用yywrap,<<EOF>>來解決了。
          
這就需要用到在flex動作中手動切換緩沖。flex對每個緩沖有個緩沖輸入流指針,指向當前位置,各個被切換的緩沖互不相干擾,這恰好很好地解決了文件包含另外一個文件,而子文件也許要yylex的這種場合.
          
這就需要使用到flex底層的緩沖管理了.見下節
   

4. flex的緩沖管理:
    flex
本質上都是對緩沖輸入流進行yylex詞法分析. 緩沖是個結構體,每個緩沖有個緩沖輸入流指針,指向當前位置,各個被切換的緩沖互不相干擾,而相關yyin,yyrestart,yy_create_buffer,yy_scan_string系列函數都是操縱flex底層緩沖的.
    flex
緩沖是一個結構體:   
我們以下面的詞法規則為例子:(來自flex官方網站的注解)
     /* the "incl" state is used 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;
    
     <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( ... );
    
             yy_switch_to_buffer(
                 yy_create_buffer( yyin, YY_BUF_SIZE ) );
    
             BEGIN(INITIAL);
             }
    
     <<EOF>> {
             if ( --include_stack_ptr < 0 )
                 {
                 yyterminate();
                 }
    
             else
                 {
                 yy_delete_buffer( YY_CURRENT_BUFFER );
                 yy_switch_to_buffer(
                      include_stack[include_stack_ptr] );
                 }
             }   
    YY_BUFFER_STATE
就是一個緩沖。該lex文法使用到了<incl>,這個是狀態,見4節的flex的狀態管理.目前只需要知道它是個狀態即可.incl狀態下才進行[ \t]*的規則匹配.
    <<EOF>>
見上面的描述,指某個輸入流到了末尾則到了這個狀態.

    BEGIN(INITIAL)類似于BEGIN(0),表示狀態從開頭解析(0表示不帶狀態的解析,也就說規則前沒有<>這個標記的狀態.


   
上面的文法可以知道:
    a.
在遇到include之后,跳到incl狀態。
    b.
incl狀態中,跳過空白的字符,得到文件名(include file),先把當前的flexBuffer保存到數組棧,然后打開新的文件,并把flex的當前輸入流切換到剛打開的新文件的輸入流.
    c.
切換到INITIAL狀態(沒有<>在規則前的默認的狀態)
    d.
這里用到了幾個宏或者函數: yy_switch_to_buffer, yy_create_buffer,YY_CURRENT_BUFFERyy_delete_buffer.
   
這些函數看名字就應該知道其作用了。 
       
4. flex
的狀態(Start conditions).
   
上面的緩沖管理已經涉及到狀態管理了。flex的狀態管理相當于普通詞法的擴展。通過flex的狀態,大大擴充了詞法分析本身的功能。
   
比如:
     a.    <STRING>[^"]*        { /* eat up the string body ... */
                 ...
                 }
    
表示在STRING狀態下才進行   [^"]*匹配。
     b.      <INITIAL,STRING,QUOTE>\.        { /* handle an escape ... */
                 ...
                 }
    
表示在INITIAL,STRING,QUOTE才匹配。\.  
     flex
的狀態怎么使用呢?
     a.
首先定義:%開頭(flex的申明本質上所有的都是以%開頭)定義,2: %s,%x,其中%s = %x+INITIAL,也就說是%s的狀態為%x定義的+INITIAL狀態
     b.
在規則域中,使用<狀態>規則,比如 comment是個狀態,則有 <comment>.\,其中.\是個lex規則文法,comment則就是一個狀態了.
     c.
有幾個特殊內置的狀態。INITIAL,*.比如: <*>規則,則表示這個規則在任何狀態下有效. <INITIAL>是個默認狀態。
     d.
某個規則可以支持多個狀態,使用,隔開。比如<INITIAL,STRING,QUOTE>規則.如果和<<EOF>>重用一個規則的話,則是<quote><<EOF>>。
     e.flex
還提供了一套相關函數:
     yy_push_state, yy_pop_state, yy_top_state, BEGIN()    
    
可以說有了狀態的支持,flex的功能更加強大了,簡單的文法分析甚至可以不借助于yacc/bison來做了。
    
   
一個完整的例子:
     %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++;
             }
   
   
5. flex C++
的支持
   
編譯時,使用flex -+ 文件,就可以得到.cc的文件,而且flex也會生成C++相關類,對應的類和方法有:
    FlexLexer:
成員方法有:
        a. yylex(), YYText(), YYLeng(),lineno(), set_debug(),debug(),
        b.
構造函數yyFlexLexer( istream* arg_yyin = 0, ostream* arg_yyout = 0 )
        c.
緩沖:switch_streams(istream* new_in = 0, ostream* new_out = 0),yylex( istream* new_in = 0, ostream* new_out = 0 )
       
       
等等。
  
例子:
         // An example of using the flex C++ scanner class.
    
     %{
     int mylineno = 0;
     %}
    
     string  \"[^\n"]+\"
    
     ws      [ \t]+
    
     alpha   [A-Za-z]
     dig     [0-9]
     name    ({alpha}|{dig}|\$)({alpha}|{dig}|[_.\-/$])*
     num1    [-+]?{dig}+\.?([eE][-+]?{dig}+)?
     num2    [-+]?{dig}*\.{dig}+([eE][-+]?{dig}+)?
     number  {num1}|{num2}
    
     %%
    
     {ws}    /* skip blanks and tabs */
    
     "/*"    {
             int c;
    
             while((c = yyinput()) != 0)
                 {
                 if(c == '\n')
                     ++mylineno;
    
                 else if(c == '*')
                     {
                     if((c = yyinput()) == '/')
                         break;
                     else
                         unput(c);
                     }
                 }
             }
    
     {number}  cout << "number " << YYText() << '\n';
    
     \n        mylineno++;
    
     {name}    cout << "name " << YYText() << '\n';
    
     {string}  cout << "string " << YYText() << '\n';
    
     %%
    
     Version 2.5               December 1994                      
    
     int main( int /* argc */, char** /* argv */ )
         {
         FlexLexer* lexer = new yyFlexLexer;
         while(lexer->yylex() != 0)
             ;
         return 0;
         }    

posted on 2008-11-23 00:54 肥仔 閱讀(8184) 評論(2)  編輯 收藏 引用 所屬分類: LEX & YACC

評論

# re: flex詳解  回復  更多評論   

flex也就是幫你詞法之后將剩下的事情全部丟給你了。因為“剩下的事情”用的是C/C++,所以從各種意義上來看flex不僅僅是type 3 grammar,但是這是借助其他工具完成的,譬如說C/C++。
2008-11-23 16:31 | 陳梓瀚(vczh)

# re: flex詳解  回復  更多評論   

從各種意義上來看flex不僅僅是type 3 grammar,
http://www.uggeinkaufenboots.com/
2010-10-26 17:09 | ugg boots buy
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            女同一区二区| 欧美亚洲一区| 亚洲女优在线| 一本一本久久a久久精品牛牛影视| 国产日韩精品在线播放| 国产酒店精品激情| 国产日韩欧美综合| 激情一区二区| 亚洲国产另类 国产精品国产免费| 一区二区三区导航| 亚洲桃花岛网站| 亚洲免费电影在线| 老牛影视一区二区三区| 国产精品男gay被猛男狂揉视频| 欧美人与禽性xxxxx杂性| 欧美视频四区| 国产亚洲精品高潮| 亚洲区第一页| 一区二区免费在线播放| 欧美一级久久久久久久大片| 久久美女性网| 亚洲激情偷拍| 亚洲视频欧洲视频| 久久精品亚洲精品| 欧美日本三区| 国产一区自拍视频| 亚洲精品国产拍免费91在线| 欧美精品一区二区三区在线播放 | 国产精品日韩一区二区| 国产精品热久久久久夜色精品三区 | aa亚洲婷婷| 性久久久久久久| 亚洲第一天堂av| 亚洲欧美成人综合| 欧美成人第一页| 亚洲福利电影| 亚洲裸体视频| 免费观看成人www动漫视频| 久久字幕精品一区| 99视频国产精品免费观看| 免费观看亚洲视频大全| 欧美一区二区三区免费视| 美国成人直播| 一区二区三区**美女毛片| 久久一区二区三区四区| 国产精品网站在线| 一区二区欧美视频| 欧美福利视频在线| 欧美专区中文字幕| 国产精品久久久久久久免费软件 | 久热精品在线视频| 国产午夜精品一区二区三区欧美| 久久精品国产91精品亚洲| 午夜久久一区| 亚洲精品久久久久中文字幕欢迎你| 午夜精品久久久久久久| 亚洲美女中文字幕| 免费成人av在线看| 在线免费一区三区| 另类综合日韩欧美亚洲| 午夜欧美不卡精品aaaaa| 国产精品国产三级国产aⅴ无密码 国产精品国产三级国产aⅴ入口 | 久久网站免费| 国内精品**久久毛片app| 久久成人免费日本黄色| 午夜精品久久久久久久男人的天堂 | 国产九区一区在线| 午夜精品免费视频| 亚洲综合电影一区二区三区| 国产精品久久久久久久免费软件| 亚洲私人影院在线观看| 欧美性大战久久久久久久蜜臀 | 蜜臀久久99精品久久久画质超高清| 亚洲成人资源网| 欧美在线亚洲| 激情一区二区| 亚洲电影欧美电影有声小说| 久久免费视频网| 亚洲国产日本| 亚洲国产1区| 欧美日韩不卡视频| 亚洲欧美视频| 欧美自拍偷拍| 亚洲欧洲日韩在线| 亚洲乱码国产乱码精品精天堂 | 国产在线拍揄自揄视频不卡99| 欧美日韩高清不卡| 精品成人在线| 亚洲福利av| 久久在线免费观看| 亚洲国产欧美一区| 免费看成人av| 亚洲精品美女久久久久| 亚洲精品五月天| 国产精品一区亚洲| 欧美~级网站不卡| 欧美成人国产va精品日本一级| 一区二区三区免费网站| 欧美一区二区大片| 亚洲精品在线一区二区| 亚洲综合视频一区| 国产欧美日韩另类一区| 亚洲字幕一区二区| 久久综合五月| 欧美日本一区二区高清播放视频| 亚洲综合国产精品| 久久精品理论片| 宅男噜噜噜66一区二区66| 欧美一级视频免费在线观看| 99视频在线观看一区三区| 欧美一区二区三区视频在线 | 国产精品久久久久久久久久直播| 久久亚洲精品一区| 国产精品久久久| 亚洲国产成人av在线| 国产视频精品xxxx| 在线亚洲欧美专区二区| 亚洲人成在线播放| 国产精品影片在线观看| 欧美一区二区免费视频| 欧美激情一区在线| 麻豆亚洲精品| 国产精品对白刺激久久久| 国产精品久久久久婷婷| 欧美成人在线免费视频| 国产毛片久久| 99re6这里只有精品| 激情综合色综合久久综合| 亚洲中午字幕| 在线亚洲成人| 免费欧美高清视频| 久久精品一二三区| 国产精品青草综合久久久久99| 91久久一区二区| 亚洲国产欧美日韩精品| 久久久久成人精品| 欧美视频在线一区二区三区| 99视频一区二区| 久久精品中文字幕一区二区三区| 亚洲一区国产一区| 欧美视频二区36p| 亚洲毛片视频| 亚洲视频精品| 欧美日韩国产免费观看| 亚洲激情视频在线| 亚洲精品乱码久久久久久蜜桃91| 久久综合狠狠综合久久综合88| 久久美女性网| 午夜精品电影| 国产亚洲精品bv在线观看| 亚洲免费在线精品一区| 亚洲欧美日韩精品| 国产精品入口| 欧美亚洲视频在线观看| 久久狠狠久久综合桃花| 国产专区欧美精品| 久久性天堂网| 亚洲欧洲美洲综合色网| 一区二区三区成人精品| 国产精品久久久久av免费| 亚洲尤物视频在线| 久久偷看各类wc女厕嘘嘘偷窃| 一区二区在线看| 欧美福利视频| 亚洲香蕉视频| 欧美激情第二页| 午夜精品999| 久久视频在线看| 国产伊人精品| 免费国产一区二区| 日韩小视频在线观看专区| 午夜精品影院| 精品av久久707| 欧美精品99| 亚洲一区二区三区欧美| 可以免费看不卡的av网站| av成人黄色| 国产午夜精品视频| 欧美精品亚洲一区二区在线播放| 亚洲视频在线免费观看| 欧美成年人网站| 亚洲免费在线观看视频| 亚洲高清色综合| 国产精品九九| 欧美激情aⅴ一区二区三区| 亚洲欧美日韩在线高清直播| 亚洲国产人成综合网站| 性欧美暴力猛交69hd| 欧美二区乱c少妇| 欧美激情一区二区三区在线视频观看 | 亚洲国产视频一区| 中日韩高清电影网| 国际精品欧美精品| 欧美日韩亚洲三区| 久久婷婷国产综合尤物精品| 夜夜精品视频一区二区| 欧美成人小视频| 久久xxxx精品视频| 一区二区三区精品| 亚洲国产精品久久久久秋霞不卡 |