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

woaidongmao

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

詞法分析器生成工具FLEX簡介

1FLEX簡介

   單詞的描述稱為模式(Lexical Pattern),模式一般用正規表達式進行精確描述。FLEX通過讀取一個有規定格式的文本文件,輸出一個如下所示的C語言源程序。

clip_image001

   FLEX的輸入文件稱為LEX源文件,它內含正規表達式和對相應模式處理的C語言代碼。LEX源文件的擴展名習慣上用.l表示。FLEX通過對源文件的掃描自動生成相應的詞法分析函數 int yylex(),并將之輸出到名規定為lex.yy.c的文件中。實用時,可將其改名為lexyy.c。該文件即為LEX的輸出文件或輸出的詞法分析器。也可將 int yylex()加入自已的工程文件中使用。

2. 模式簡介

   LEX的模式的格式(也稱為規則)是機器可讀的正規表達式,正規表達工是用連接、并、閉包運算遞歸生成的。為了方便處理,LEX在此基礎上增加了一些運算。下列是按運算優先級由高往低排列的LEX的正規表達式的運算符。

“\[]^-?.*+|()/${}%<>

   關于LEX的模式定義,可參見下頁附表1.1

3LEX源文件格式

   LEX對源文件的格式要求非常嚴格,比如若將要求頂行書寫的語句變成非頂行書寫就會產生致命錯誤。而LEX本身的查錯能力很弱,所以書寫時一定要注意。

   LEX的源文件由三個部份組成,每個部分之間用頂行的“%%”分割,其格式如下:

   定義部份

   %%

   規則部份 

   %%

   用戶附加C語言部份

3.1定義部份

   定義部份由C語言代碼、模式的宏定義、條件模式的開始條件說明三部份組成。

   其中,C代碼部份由頂行的%{}%引入,LEX掃描源文件時將%{}%之間的部分原封不動的拷貝到輸出文件lex.yy.c.

附表1.1 LEX 的模式定義

模 式

解 釋

X

匹配單個字符x(也可將模式寫為”x”)

.

匹配除換行符’\n’之外的任意字符

[xyz]

匹配x、yz

[abj-oZ]

匹配字符集:a、b、Z以及jo之間的字母(包括jo)

[^A-Z]

匹配字符集AZ之間字符集的補集。即除大寫字母的其它字符

[^A-Z\n]

匹配除大寫字母和換行符之外的其它字符

r*

R是正規表達式,r*匹配0個或多個r

r+

R是正規表達式,r+匹配1個或多個r

r?

R是正規表達式,r?匹配0個或1r

r{2,5}

R是正規表達式,r{2,5}匹配2個到5r

r{2,}

R是正規表達式,r{2,}匹配2個或以上r

r{4}

R是正規表達式,r{4}匹配4r

{name}

name是在定義部份出現的模式宏名,在規則部份將之替換為模式

“[xyz]\”foo”

匹配字符串[xyz]”foo

\x

x’a’、’b’、’f’’n’’r’’t’,\x為轉義字符,定義同ANSI C,否則,匹配字符x.此方法用于匹配正規表達式的運算符

\123

匹配八進制ASCII碼為123的字符

\x2a

匹配十六進制ASCII碼為2a的字符

(r)

匹配r,優先運算正規式r

Rs

匹配正規式rs的連接

r|s

匹配正規式rs

r/s

匹配正規式r,但是,r之后一定要出現正規式s。稱sr的尾部條件

^r

匹配正規式r,但是,r一定要出現在行首

r$

匹配正規式r,但是,r一定要出現在行尾

<s>r

匹配正規表達式r,但是一定要在開始條件s激活之后

<<EOF>>

匹配文件結束標志

   模式的宏定義部份如同C語言中的宏定義,通過宏名定義一個模式,這樣,可以簡化在源文件中多次出現的正規表達式的書寫。格式為:

   宏名1 宏定義1

   宏名2 宏定義2 

   ……

   例如:

   DIGIT [0-9]

   ID [A-Za-z][A-Za-z0-9_]*

   宏名是以字母和下劃線”_”開始,以字母、數字和下劃線組成的字符串,且大小寫敏感。宏名必須頂行寫,宏名和宏定義必須寫在同一行上。宏名和宏定義之間以不包括換行符的白字符(空格符、TAB符、換行符)隔開。

   條件模式的開始條件說明格式如下:

   start s1 s2 s3

   其中,s1s2、s3為條件名。必須為大小寫敏感的標識符。關于條件模式的使用,我們將在后面作說明。

3.2 規則部份

   規則部份是LEX源文件的核心部份,它包括一組模式和在生成分析器識別相應模式后對相應模式進行處理的C語言動作(Action)。格式如下

   C語言代碼

   模式1 動作1

   模式2 |

   模式3 動作3

   ……

   同定義部分一樣,C語言代碼必須出現在第一個模式之前,包括在%{}%之中,且%{必須頂行書寫。%{}%之間的代碼部份可用來定義yylex()用到的局部變量。

   模式必須頂行書寫。模式可為正規式或用{}括起且在定義部份定義過的宏名。動作為用{}括起的C代碼。且開始括號{與模式之間用白字符隔開,且須和模式在同一行上。注意,在模式后加一|表示模式23采用同一動作3.|和模式2以白字符隔開。

3.3用戶附加C語言部份

   LEX對此部份不作任何處理,僅僅將之直接拷貝到輸出文件lex.yy.c的尾部。在些部份,可定義對模式進行處理的C語言函數、主函數和yylex要調用的函數yywrap()等。如果用戶在其它C模塊中提供這些函數,用戶代碼部份可以省略。

3.4 源文件格式小結

  綜上所述,LEX源文件詳細格式如下:

 %{

   /*此模塊為定義模塊中C語言代碼部份,在下面填入相應C代碼*/

   }%

   模式宏名1 模式1

   模式宏名2 模式2

   ……

   %start s1 s2 s3

   %%

   %{

   /*此模塊為規則模塊中C語言代碼部份,在下面填入相應C代碼*/

   }%

   模式1 動作1

   模式2 動作2

   ……

   %%

   /*此模塊為用戶附加C語言部份,在下面填入相應C代碼*/

   注意:以上三部份及其中任何一子部份,均可省去。且如無第三部分,第二個%%也可省去,但第一個%%決不可省。

4.LEX的工作原理

   LEX通過對源文件的掃描,經過宏替換后,將規則部份的正規表達式轉換成與之相應的DFA,并由之產生一個名為int yylex()的詞法分析函數,將之拷貝到輸出文件lex.yy.c中。由于考慮到C代碼的可移植性和運行效率問題,lex.yy.c中大量使用了宏定義,且文件較大(30-50kb)。因此,幾乎是不可讀的。但是,其可移植性相當好。

   lex.yy.c中定義了很多用戶可定義的全局變量,以及在LEX源文件的動作中可調用的函數和宏。但是,由于lex.yy.c太過復雜,建議初學者不要隨意修改它。用戶在了解其的前提下,可在其它C模塊中引用之。

5.二義性問題的解決

   yylex()函數被調用之后,它首先檢查全局文件指針變量yyin是否有定義,如有,則將之設置為將要掃描的文件指針。如無,則設置為標準輸入文件stdin.同理,如全局文件指針變量yyout無定義,則將之設置為標準輸出文件stdout

   若有多個模式與被掃描文件中的字符串相匹配,則yylex()執行能匹配最長字符串的模式,稱為最長匹配原則;若還有多個模式匹配長度相同的字符串,則yylex()選擇在LEX源文件中排列最前面的模式進行匹配,稱為最先匹配原則。yylex()常通過超前搜索一個字符來實現這樣的原則,如果使用超前搜索匹配了某一模式,則yylex()在進行下一次分析前,將回退一個字符。見下例:

   %%

   program {printf(“keyword:%s!\n”,yytext); /*模式一*/}

   procedure {printf(“keyword:%s!\n”,yytext); /*模式二*/}

   [a-z][a-z0-9]* {printf(“identifier:%s!\n”,yytext); /*模式三*/}

   %%

   如輸入串為”programming”,yylex()分析到子串”program”時,有模式一和三可以匹配,但根據最長搜索原則,發現在繼續讀入輸入串時,還可匹配模式三。這樣,將輸出”identifier:programming!”。如輸入串為”program”,則按最先匹配原則,模式一與之匹配,輸出”keyword:program!”。注意,若將模式一和模式三在源文件中次序弄反,則模式一永遠也得不到匹配。若無模式可匹配輸入串,則使用缺省規則,即將輸入串原樣拷貝至輸出文件yyout中。

6.常用全局變量和宏

   lex.yy.c中常用全局變量、函數和宏很多,在此僅指出一些最常用的,若需要更詳細信息,請閱讀源文件。

   (1) FILE *yyin,*yyout:為指向字符輸入和結果輸出文件的指針。如用戶未對其定義,則設為標準輸入文件stdinstdout。

   (2) int yylex():為詞法分析程序,它自動移動文件指針yyinyyout。在定義模式動作時,用戶可用return語句結束yylex(),return 必須返回一整數。由于yylex()的運行環境都是以全局變量的方式保存,因此,在下一次調用yylex()時,yylex()可從上次掃描的斷點處繼續掃描,在語法分析時,可利用這一特性。若用戶未定義相應的return語句,則yylex()繼續分析被掃描的文件,直到碰到文件結束標志EOF。在讀到EOF時,yylex()調用int yywrap()函數(該函數用戶必須提供),若該函數返回非0值,則yylex()返回0而結束。否則,yylex()繼續對yyin指向的文件掃描。

   (3) char *yytext:存放當前被識別的詞形。

   (4) int yyleng:存放字符串yytext的長度。

   (5) int yywrap():參見(2)

   (6) yymore():將當前識別的詞形保留在yytext中,分析器下次掃描時的詞形將加追加在yytext中。例模式定義如下

   ……

   hello {printf(“%s!”,yytext);yymore();}

   world {printf(“%s!”,yytext);}

   ……

   當輸入串為”helloworld”時,將輸出”hello!helloworld!”

   (7) yyless(int n):回退當前識別的詞形中n個字符到輸入中

   (8) unput(char c):回退字符c到輸入,它將作為下一次掃描的開始字符

   (9) input():讓分析器從輸入緩沖區中讀取當前字符,并將yyin指向下一字符

   (10)yyterminate():中斷對當前文件的分析,將yyin指向EOF。

   (11)yyrestart(FILE * file):重新設置分析器的掃描文件為file

   (12)ECHO:將當前識別的字符串拷貝到yyout

   (13)BEGIN:激活開始條件對應的模式

   (14)REJECT:放棄當前匹配的字符串和當前的模式,讓分析器重新掃描當前的字符串,并選擇另一個最佳的模式再次進行匹配。

7.條件模式

   LEX提供控制模式在一定狀態下使用的功能,稱為條件模式。LEX首先在定義部份通過%start來定義條件句。在規則部份可通過宏

   BEGIN 條件名 來激活條件。BEGIN INITIALBEGIN 0將休眠所有的條件模式,使分析器回到開始狀態。

   例:將輸入文件中的單詞”magic” 作如下處理:識別”magic”時,如”magic”所在行行首為字符’a’,則輸出”first”;若為’b’,則輸出”second”;否則,輸出”magic”。如不用條件模式,LEX源文件可這樣寫:

   %{int flag;}%

   %%

   ^a {flag=’a’;ECHO;}

   ^b {flag=’b’;ECHO;}

   \n {flag=0;ECHO;}

   magic {

   switch(flag)

   {

   case ‘a’:printf(“first”);break;

   case ‘b’:printf(“second”);break;

   default :ECHO;break;

   }

   }

   %%

   如使用條件模式,則上述源文件可簡化為 %start AA BB CC

   %%

   ^a {ECHO;BEGIN AA;}

   ^b {ECHO;BEGIN BB;}

   \n {ECHO;BEGIN 0;}

   <AA>magic {printf(“first”);}

   <BB>magic {printf(“second”);}

   %%

8. 示例

   例一:編制LEX源程序,分別統計文本文件a.txt中出現的標識符和整數個數,并顯示之。標識符定義為字母開頭,后跟若干個字母,數字或下劃線。整數可以帶+-號,也可不帶,且不以0開頭。非單詞和非整數則忽略不記,將之濾掉不顯示。

   LEX源文件名為count.l.文件內容如下

   %{

   #include "stdio.h"

   #include "stdlib.h"

   int num_num=0,num_id=0;

   %}

   INTEGER [-+]?[1-9][0-9]*

   ID [a-zA-Z][a-zA-Z_0-9]*

   SPACE [ \n\t]

   %%

   {INTEGER} { num_num++;

   printf("(num=%d)",atoi(yytext));//打印數字值

   /*數字數加一*/

   }

   {ID} {

   num_id++;

   printf("(id=%s)",yytext);

   }

    {SPACE} |

   . {

   //什么也不做,濾掉白字符和其它字符

   }

   %%

   void main()

   {

   yylex();

   printf("num=%d,id=%d",num_num,num_id);

   }

   int yywrap()//此函數必須由用戶提供

   {return 1;}

   count.l所在目錄為c:\test,且已用path命令指定flex.exe所在目錄。則調用命令

   c:\test> flex count.l后可在c:\test目錄下得到一文件lex.yy.c,打開C環境,新建工程文件my.prj(TURBOC BORLAND C下后綴為.prj,VC下后綴為.dsw),lex.yy.c加入工程文件中,編譯運行可得可執行文件my.exe.若需分析從標準輸入中輸入的字符串,運行my.exe即可.若需分析放在其它文件中的串,如設在文件hello.txt,則運行my.exe<hello.txt即可.

   2:編制一LEX源程序,分別求出文件hh.c中字母,數字,回車符的個數.源程序如下:

   %{

   #include "stdio.h"

   #include "stdlib.h"

   int num_digit=0,num_letter=0,num_enter=0;

   %}

   DIGIT [0-9]

   LETTER [A-Za-z]

   %%

   {DIGIT} {num_digit++;}

   {LETTER} {num_letter++;}

   \n {num_enter++;}

   . {/*其它字符不作處理*/}

   %%

   void main()

   {

   yyin=fopen(”hh.c”,r);

   yylex();

   printf("num=%d,letter=%d,enter=%d",

   num_digit,num_letter,num_enter);

   }

   int yywrap()//此函數必須由用戶提供

   { 

  return 1;

   }

 

posted on 2008-11-30 19:54 肥仔 閱讀(10175) 評論(1)  編輯 收藏 引用 所屬分類: LEX & YACC

評論

# re: 詞法分析器生成工具FLEX簡介[未登錄]  回復  更多評論   

yywrap()函數果真一定要用戶提供嗎?我自己寫的例子就沒有提供,照樣運行的好好的。
2015-06-26 10:21 | 路人甲
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美亚洲动漫精品| 99这里只有久久精品视频| 亚洲人成亚洲人成在线观看| 影音先锋在线一区| 亚洲国产专区| 亚洲免费观看高清完整版在线观看| 亚洲欧洲精品一区二区精品久久久| 亚洲精品精选| 亚洲综合精品四区| 欧美一乱一性一交一视频| 久久欧美肥婆一二区| 欧美激情麻豆| 亚洲午夜电影网| 久久成人免费日本黄色| 美女尤物久久精品| 欧美日韩国产探花| 国语自产精品视频在线看一大j8 | 国产日韩三区| 精品999在线播放| 99精品视频免费在线观看| 亚洲欧美不卡| 久久综合伊人77777尤物| 最新日韩中文字幕| 国产精品99久久久久久有的能看| 欧美中文字幕不卡| 奶水喷射视频一区| 亚洲美女在线观看| 欧美在线一区二区三区| 欧美精品一区在线观看| 国产在线乱码一区二区三区| 一区二区三区欧美成人| 快she精品国产999| 亚洲婷婷综合色高清在线| 麻豆成人av| 国产亚洲欧美日韩精品| 亚洲一二区在线| 亚洲国产电影| 欧美在线亚洲| 国产精品腿扒开做爽爽爽挤奶网站| 亚洲高清自拍| 欧美一区二区三区视频| 亚洲毛片在线观看| 免费在线视频一区| 伊大人香蕉综合8在线视| 午夜亚洲伦理| 在线亚洲伦理| 欧美日韩久久不卡| 亚洲日韩欧美视频| 免费亚洲一区二区| 欧美一级在线视频| 国产亚洲一本大道中文在线| 亚洲欧美日韩系列| 一区二区三欧美| 欧美日韩精品免费| 一区二区欧美视频| 亚洲乱码日产精品bd| 欧美激情一区二区三区全黄| 亚洲高清资源| 亚洲国产cao| 欧美成人在线免费观看| 亚洲电影中文字幕| 欧美国产专区| 欧美福利在线观看| a91a精品视频在线观看| 91久久精品一区二区别| 欧美精品一区二区在线观看| 日韩天堂av| 9久re热视频在线精品| 欧美午夜久久| 欧美在线亚洲一区| 久久国产精品久久久久久| 在线观看的日韩av| 亚洲福利电影| 欧美日韩国产综合视频在线观看中文 | 亚洲国产婷婷香蕉久久久久久| 欧美凹凸一区二区三区视频| 玖玖精品视频| 亚洲美女淫视频| 99视频在线观看一区三区| 国产精品a级| 韩国欧美国产1区| 免费h精品视频在线播放| 欧美成人国产一区二区| 宅男噜噜噜66国产日韩在线观看| 亚洲视频中文字幕| 狠狠色综合网| 日韩一本二本av| 国产欧美va欧美va香蕉在| 老司机精品福利视频| 欧美激情一区二区三区不卡| 性久久久久久久| 免费欧美网站| 午夜精品一区二区三区在线| 久久男人av资源网站| 亚洲一区视频在线观看视频| 久久久国产精品一区二区中文| 日韩一区二区精品在线观看| 香蕉久久夜色精品国产| 99亚洲视频| 久久精品综合| 亚洲一区二区三区影院| 久久三级视频| 欧美一级播放| 欧美日韩高清在线| 免费亚洲电影| 国产麻豆综合| 一本色道久久88亚洲综合88| 亚洲国产免费看| 性久久久久久久久| 亚洲一区二区成人| 欧美99久久| 久久午夜羞羞影院免费观看| 国产精品毛片va一区二区三区 | 国产精品久久国产三级国电话系列 | 1024国产精品| 午夜视频一区二区| 亚洲一区二区3| 欧美护士18xxxxhd| 免费欧美日韩国产三级电影| 国产精品一页| 在线亚洲自拍| 亚洲视频精选在线| 欧美另类高清视频在线| 欧美激情精品久久久六区热门| 韩国av一区| 久久久999国产| 久久久久久久久久久久久久一区 | 亚洲国产一区二区精品专区| 在线观看视频亚洲| 久久久久久久久一区二区| 久久久精品国产免费观看同学| 国产精品视频精品| 亚洲自拍偷拍色片视频| 午夜影院日韩| 国产精品无码专区在线观看| 亚洲影音一区| 欧美一级视频精品观看| 亚洲欧美日本国产专区一区| 先锋影音久久| 国产综合久久久久久鬼色| 性高湖久久久久久久久| 久久精品二区| 激情五月婷婷综合| 久久婷婷久久一区二区三区| 欧美大片专区| 日韩视频免费观看高清在线视频 | 欧美a级一区| 欧美激情一区在线| aa级大片欧美三级| 欧美午夜精品久久久久久孕妇| 亚洲网站在线| 久久亚洲综合色| 亚洲美女在线看| 国产精品黄色在线观看| 欧美在线免费观看| 欧美激情精品久久久久久黑人 | 亚洲一区二区成人在线观看| 国产精品试看| 久久久久国产精品一区二区| 亚洲国产精品v| 亚洲欧美日韩国产一区二区| 国产网站欧美日韩免费精品在线观看| 久久精彩视频| 99精品欧美一区| 久久视频精品在线| 亚洲免费av观看| 国产欧美日韩视频一区二区| 久久综合国产精品| 亚洲少妇自拍| 欧美国产精品va在线观看| 亚洲一卡久久| 亚洲国产精品悠悠久久琪琪| 欧美亚州在线观看| 美女精品国产| 亚洲欧美三级伦理| 亚洲国产另类精品专区| 久久国产手机看片| 中文国产成人精品久久一| 一区二区三区在线高清| 国产精品高潮视频| 欧美电影资源| 久久精品五月| 亚洲欧美国产精品va在线观看 | 在线播放视频一区| 欧美亚州韩日在线看免费版国语版| 久久国产精品久久久久久久久久 | 狼狼综合久久久久综合网| 亚洲一级二级在线| 亚洲国产日韩欧美在线99| 久久国产一区二区| 亚洲午夜免费视频| 最新国产成人av网站网址麻豆| 国产欧美欧美| 欧美视频中文在线看| 欧美大片在线观看一区二区| 久久人人爽爽爽人久久久| 欧美一区二区三区在| 亚洲午夜精品久久久久久app| 亚洲精品网址在线观看| 精品二区久久|