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

woaidongmao

文章均收錄自他人博客,但不喜標(biāo)題前加-[轉(zhuǎn)貼],因其丑陋,見諒!~
隨筆 - 1469, 文章 - 0, 評(píng)論 - 661, 引用 - 0
數(shù)據(jù)加載中……

yacc / lex 在linux 下 使用指南

    Lex 和 Yacc 是 Unix 和Linux 下詞法和語法的分析,解析工具,有了這兩個(gè)工具,你可以自己制作想要的編譯器,也可以重新制作已有程序語言的解析器。需要注意的是linux下的這兩個(gè)工具生成的程序源碼只能是C和C++語言,當(dāng)然現(xiàn)在早已有類似可以生成Java源碼的語法分析器,如較常用的JavaCC(Java Compiler Compiler),相關(guān)內(nèi)容可以去網(wǎng)上搜索。Lex和Yacc已被移植到windows下,現(xiàn)在常用的工具有Parser Generator。本文只介紹Linux 下Lex和Yacc的使用方法。


Lex介紹

Lex 通過對(duì).lex或.l文件定義的格式生成一個(gè)C語言源碼文件,通過編譯這個(gè)源碼,就生成了.lex文件或.l文件定義的編譯器。.lex或.l文件的格式分三段:

1.全局變量聲明部分
2.詞法規(guī)則部分
3.函數(shù)定義部分

以下是一個(gè)簡單的例子:lex_example.l文件

%{            //全局聲明部分
/*林木100 linux
www.linmu100.com
*/
#include <stdio.h>  

extern char *yytext;
extern FILE *yyin;
int sem_count = 0;

%}

//規(guī)則定義部分,
%%
[a-zA-Z][a-zA-Z0-9]*    {printf("WORD[%s] ", yytext);}
[a-zA-Z0-9\/.-]+        printf("FILENAME ");
\"                      printf("QUOTE ");
\{                      printf("OBRACE ");
\}                      printf("EBRACE ");
;                       {sem_count++; printf("SEMICOLON ");}
\n                      printf("\n");
[ \t]+                  /* ignore whitespace */;
%%

//以下為函數(shù)定義部分
int main(int avgs, char *avgr[]) 
{
    yyin = fopen(avgr[1], "r");
    if (!yyin)
    {
        return 0;
    }
    yylex();
    printf("sem_count : %d\n", sem_count);
    fclose(yyin);

    return 1;
}

Lex 常用格式如下表,常規(guī)表達(dá)式:

字符

含義

A-Z, 0-9, a-z

構(gòu)成了部分模式的字符和數(shù)字。

.

匹配任意字符,除了 \n。

-

用來指定范圍。例如:A-Z 指從 A 到 Z 之間的所有字符。

[ ]

一個(gè)字符集合。匹配括號(hào)內(nèi)的任意 字符。如果第一個(gè)字符是 ^ 那么它表示否定模式。例如: [abC] 匹配 a, b, 和 C中的任何一個(gè)。

*

匹配0個(gè)或者多個(gè)上述的模式。

+

匹配1個(gè)或者多個(gè)上述模式。

?

匹配0個(gè)或1個(gè)上述模式。

$

作為模式的最后一個(gè)字符匹配一行的結(jié)尾。

{ }

指出一個(gè)模式可能出現(xiàn)的次數(shù)。 例如: A{1,3} 表示 A 可能出現(xiàn)1次或3次。

\

用來轉(zhuǎn)義元字符。同樣用來覆蓋字符在此表中定義的特殊意義,只取字符的本意。

^

否定。

|

表達(dá)式間的邏輯或。

"<一些符號(hào)>"

字符的字面含義。元字符具有。

/

向前匹配。如果在匹配的模版中的“/”后跟有后續(xù)表達(dá)式,只匹配模版中“/”前面的部分。如:如果輸入 A01,那么在模版 A0/1 中的 A0 是匹配的。

( )

將一系列常規(guī)表達(dá)式分組。


常規(guī)表達(dá)式舉例

常規(guī)表達(dá)式

含義

joke[rs]

匹配 jokes 或 joker。

A{1,2}shis+

匹配 AAshis, Ashis, AAshi, Ashi。

(A[b-e])+

匹配在 A 出現(xiàn)位置后跟隨的從 b 到 e 的所有字符中的 0 個(gè)或 1個(gè)。



使用lex掃描上述舉例文件 lex_example.l:
lex lex_example.l
缺省會(huì)生成lex.yy.c文件,然后用gcc編譯這個(gè)文件,注意要有-ll選項(xiàng):
gcc lex.yy.c -o analyse -ll
這樣就生成了一個(gè)簡單的詞法分析器analyse,假設(shè)有文件demo,其內(nèi)容如下所示:
firstword;
secondword;
thirdword

fourthword{
fifthword
}
輸入命令:
./analyse demo
會(huì)有如下顯示:
WORD[firstword] SEMICOLON 
WORD[secondword] SEMICOLON 
WORD[thirdword] 

WORD[fourthword] OBRACE 
WORD[fifthword] 
EBRACE 
sem_count : 2

實(shí)際上,對(duì)于上述lex_example.l文件,函數(shù)定義部分可以完全省略,因?yàn)閘ex會(huì)自動(dòng)為你生成main函數(shù)。這時(shí)仍然按上述方法生成analyse,輸入命令:
./analse < demo
結(jié)果如下:
WORD[firstword] SEMICOLON 
WORD[secondword] SEMICOLON 
WORD[thirdword] 

WORD[fourthword] OBRACE 
WORD[fifthword] 
EBRACE 


在上述lex_example.l文件中我們還使用了兩個(gè)變量:
extern char *yytext;
extern FILE *yyin;
這兩個(gè)變量是lex提供的外部借口,用戶可以根據(jù)自己需要自己更改,lex提供了以下接口:

Lex 變量

yyin

FILE* 類型。 它指向 lexer 正在解析的當(dāng)前文件。

yyout

FILE* 類型。 它指向記錄 lexer 輸出的位置。 缺省情況下,yyin 和 yyout 都指向標(biāo)準(zhǔn)輸入和輸出。

yytext

匹配模式的文本存儲(chǔ)在這一變量中(char*)。

yyleng

給出匹配模式的長度。

yylineno

提供當(dāng)前的行數(shù)信息。(lexer不一定支持。)

Lex 函數(shù)

yylex()

這一函數(shù)開始分析。 它由 Lex 自動(dòng)生成。

yywrap()

這 一函數(shù)在文件(或輸入)的末尾調(diào)用。如果函數(shù)的返回值是1,就停止解析。 因此它可以用來解析多個(gè)文件。代碼可以寫在第三段,這就能夠解析多個(gè)文件。 方法是使用 yyin 文件指針(見上表)指向不同的文件,直到所有的文件都被解析。最后,yywrap() 可以返回 1 來表示解析的結(jié)束。

yyless(int n)

這一函數(shù)可以用來送回除了前憂? 個(gè)字符外的所有讀出標(biāo)記。

yymore()

這一函數(shù)告訴 Lexer 將下一個(gè)標(biāo)記附加到當(dāng)前標(biāo)記后。

以下是一個(gè)計(jì)算字符個(gè)數(shù)的.l文件內(nèi)容,有興趣的朋友可以編譯試試
%{ 
/*
林木100 linux
www.linmu100.com
*/
int wc = 0;        /* word count */ 
%} 
 
%% 
[a-zA-Z]+    { wc++; } 
\n|.        { /* gobble up */ } 
%% 
int main(void) 

    int n = yylex(); 
    return n; 

 
int yywrap(void) 

    printf("word count: %d\n", wc); 
    return 1; 
}

yacc介紹

Yacc 是 Yet Another Compiler Compiler的縮寫。 Yacc 的 GNU 版叫做 Bison。它是一種語法解析工具。它用巴科斯范式(BNF, Backus Naur Form)來書寫。按照慣例,Yacc 文件有 .y 后綴。
實(shí)際上,yacc才是真正分析語法的核心,.y文件格式和.l文件一樣分三段,但每一段的意義有所不同:
1.全局變量聲明,終結(jié)符號(hào)(終端符號(hào))聲明
2.語法定義
3.函數(shù)定義

以下是一個(gè)簡單的yacc_example.y文件,定義了一個(gè)簡單的計(jì)算器:
%{ 
//全局變量聲明 
#include <ctype.h> 
#include <stdio.h> 
#define YYSTYPE double /*double type for YACC stack; for yylval*/ 
 
/*林木100 www.linmu100.com */ 
 
void yyerror(const char *str) 

    fprintf(stderr, "error:%s\n", str ); 

%} 
//終結(jié)符聲明 
%token NUMBER 
 
%% 
lines    : lines expr '\n'            { printf("%g\n", $2); } 
        | lines '\n' 
        | /* e */ 
        | error '\n'                { yyerror("reenter last line:"); /*yyerrok(); */} 
        ; 
 
expr    : expr '+' term                { $$ = $1 + $3; } 
        | expr '-' term                { $$ = $1 - $3; } 
        | term 
        ; 
 
term    : term '*' factor            { $$ = $1 * $3; } 
        | term '/' factor            { $$ = $1 / $3; } 
        | factor 
        ; 
 
factor    : '(' expr ')'                { $$ = $2; } 
        | '(' expr error            { $$ = $2; yyerror("missing ')'"); /*yyerrok(); */} 
        | '-' factor                { $$ = -$2; } 
        | NUMBER 
        ; 
 
%% 
//以上部分為語法定義,以下部分為函數(shù)定義 
int main(void) 

    return yyparse(); 

 
int yylex(void) 

    int c; 
    while ((c = getchar()) == ' '); 
    if (c == '.' || isdigit(c)) { 
        ungetc(c, stdin); 
        scanf("%lf", &yylval); 
        return NUMBER; 
    } 
    return c; 


使用yacc掃描這個(gè)文件:
yacc yacc_example.y
缺省會(huì)生成一個(gè)y.tab.c文件,然后用gcc編譯這個(gè)文件,注意要有選項(xiàng) -ll 或 -ly:
gcc y.tab.c -o analyse -ll
運(yùn)行./analyse:結(jié)果如下圖所示:
clip_image001

現(xiàn)在對(duì)照yacc_example.y文件講解一下.y文件的規(guī)則:
1.在全局變量聲明部分,聲明了一個(gè)接口函數(shù)yyerror,這個(gè)函數(shù)是用來在出錯(cuò)時(shí)調(diào)用的。這一段主要是聲明一些變量,數(shù)據(jù)結(jié)構(gòu),函數(shù)用。
2.%token NUMBER則聲明了一個(gè)終端符(終結(jié)符),這個(gè)符號(hào)是由Lex返回的,會(huì)在yacc語法規(guī)則中用到。
3.語法規(guī)則部分則聲明了語法:
    3.1語法規(guī)則對(duì)外只有一個(gè)接口,這一點(diǎn)要注意,初學(xué)者常常會(huì)犯語法對(duì)外有多個(gè)接口的錯(cuò)誤。
    3.2無論是lex文件還是yacc文件都要注意最大可能性的詞法和語法規(guī)則要放在沖突規(guī)則的前面,這樣保證了最大可能規(guī)則會(huì)被最先匹配,比如lex文件中:
       temperator      return T1;
       temp             return T2;
        在yacc文件中,例子如下
            command:
                NUMBER CHAR
                |   NUMBER
               ;

對(duì)于.y文件還要注意全局語法,以及遞歸的調(diào)用。

初學(xué)者對(duì)于yacc文件規(guī)則可能會(huì)較為生疏,關(guān)鍵還要多做一些練習(xí)。


Lex 和 Yacc 的結(jié)合

lex和yacc結(jié)合時(shí)需要注意的是
lex文件頭要引用yacc生成的頭文件:"y.tab.h"

以下是一個(gè)lex和yacc結(jié)合的實(shí)例:
lex_yacc_exp.l文件:
%{
/*林木100
www.linmu100.com
*/
#include <stdio.h>
#include <string.h>
#include "y.tab.h"
extern char *yytext;
%}
%%
[0-9]+                  yylval.number=atoi(yytext); return NUMBER;
heater            return TOKHEATER;
heat                    return TOKHEAT;
on|off                  yylval.number=!strcmp(yytext,"on"); return STATE;
target                  return TOKTARGET;
temperature             return TOKTEMPERATURE;
[a-z0-9]+        yylval.string=strdup(yytext);return WORD;
\n                      /* ignore end of line */;
[ \t]+                  /* ignore whitespace */;
%%

lex_yacc_exp.y文件:
%{
/*林木100
www.linmu100.com
*/
#include <stdio.h>
#include <string.h>

void yyerror(const char *str)
{
    fprintf(stderr,"error: %s\n",str);
}

int yywrap()
{
    return 1;
}

main()
{
    yyparse();
}

char *heater="xl's test";

%}

%token TOKHEATER TOKHEAT TOKTARGET TOKTEMPERATURE

%union 
{
    int number;
    char *string;
}

%token <number> STATE
%token <number> NUMBER
%token <string> WORD

%%

commands:
    | commands command
    ;


command:
    heat_switch | target_set | heater_select

heat_switch:
    TOKHEAT STATE 
    {
        if($2)
            printf("\tHeater '%s' turned on\n", heater);
        else
            printf("\tHeat '%s' turned off\n", heater);
    }
    ;

target_set:
    TOKTARGET TOKTEMPERATURE NUMBER
    {
        printf("\tHeater '%s' temperature set to %d\n",heater, $3);
    }
    ;

heater_select:
    TOKHEATER WORD
    {
        printf("\tSelected heater '%s'\n",$2);
        heater=$2;
    }
    ;

輸入以下命令,分別生成lex.yy.c,y.tab.c,y.tab.h三個(gè)文件:
lex lex_yacc_exp.l
yacc -d lex_yacc_exp.y
gcc lex.yy.c y.tab.c -o analyse -ll

創(chuàng)建一個(gè)語法用例demo,內(nèi)容如下:
heat on
target temperature 99
heater asdfsieiwef99adsf

輸入./analyse <demo分析demo文件,會(huì)得到以下結(jié)果:
clip_image002 


結(jié)語:
Lex 和 Yacc 是很強(qiáng)大的工具,這里只簡單介紹了一些入門知識(shí)。
The Lex & Yacc Page 中有很多有趣的歷史參考,以及 非常好的 lex 和 yacc 文檔。 

參考文檔:
http://www.ibm.com/developerworks/cn/linux/l-lexyac.html
http://blog.csdn.net/ThinkinginLinux/archive/2005/03/19/323379.aspx

/
/*-----Lex & Yacc ----www.linmu100.com ----*/
/
/*-----linux工具,Lex & Yacc,基本操作----*/
/
/*-----linux配置,UNIX,開源軟件,linux技術(shù),makefile----*/
/
/*----------------------@xiaolin--------------------*/
/

 

posted on 2008-09-19 18:01 肥仔 閱讀(2070) 評(píng)論(0)  編輯 收藏 引用 所屬分類: LEX & YACC

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            一区二区三区四区五区精品| 久久三级福利| 亚洲尤物视频网| 亚洲视频在线二区| 亚洲电影免费在线| 欧美中文在线观看| 国产欧美日本一区二区三区| 久热国产精品视频| 亚洲午夜av| 欧美怡红院视频| 国产精品日日摸夜夜摸av| 欧美1区免费| 噜噜噜在线观看免费视频日韩| 欧美一区三区三区高中清蜜桃| 欧美亚日韩国产aⅴ精品中极品| 亚洲国产导航| 日韩视频一区| 欧美二区不卡| 一区二区高清视频| 精品1区2区3区4区| 蜜臀99久久精品久久久久久软件| 欧美国产一区二区在线观看| 亚洲黄色天堂| 一区二区三区精品国产| 亚洲欧美经典视频| 欧美成人a视频| 国产亚洲欧美一区| 在线视频一区二区| 久久久精品久久久久| 亚洲破处大片| 午夜在线电影亚洲一区| 欧美激情亚洲国产| 精品成人在线观看| 亚洲女人小视频在线观看| 欧美韩日一区二区| 国语自产精品视频在线看| 日韩视频免费在线观看| 欧美www视频在线观看| 亚洲自拍三区| 国产精品无码永久免费888| 亚洲国产精品一区二区www| 亚洲夜间福利| 亚洲亚洲精品三区日韩精品在线视频| 夜夜爽夜夜爽精品视频| 久久久国产91| 欧美亚洲免费电影| 国外成人性视频| 久久视频这里只有精品| 欧美影院成人| 国产精品五区| 久久国产精品毛片| 久久国产欧美| 日韩五码在线| 久久精品国产欧美激情| 亚洲高清色综合| 一区二区久久久久久| 国产欧美韩国高清| 久久精品国产欧美激情| 一本色道久久加勒比88综合| 韩国av一区| 欧美激情视频在线播放| 欧美精彩视频一区二区三区| 亚洲理论电影网| 亚洲欧美日韩久久精品| 亚洲人成绝费网站色www| 亚洲欧洲日本专区| 欧美三级在线| 美女视频黄a大片欧美| 麻豆国产精品777777在线| 黄色日韩网站| 妖精视频成人观看www| 国产精品亚洲精品| 女仆av观看一区| 欧美午夜精品电影| 欧美成人首页| 精品电影一区| 久久亚裔精品欧美| 午夜亚洲影视| 国产精品日日摸夜夜摸av| 亚洲欧美日韩精品一区二区| 亚洲美女视频在线免费观看| 午夜精品久久久久| 欧美在线三级| 国内精品久久久久久久影视麻豆| 中文精品视频一区二区在线观看| 亚洲欧洲日本专区| 免费91麻豆精品国产自产在线观看| 久久精品中文字幕一区二区三区| 国产精品视频最多的网站| 在线亚洲精品| 欧美一区成人| 91久久精品网| 国产精品乱码一区二三区小蝌蚪| 一区二区三区日韩精品| 亚洲欧美制服另类日韩| 国产一区二区三区久久久久久久久| 亚洲综合日韩中文字幕v在线| 久久国产精品亚洲77777| 尤物精品国产第一福利三区| 欧美电影打屁股sp| 午夜精品久久久久久久蜜桃app| 久久久久青草大香线综合精品| 亚洲高清毛片| 噜噜爱69成人精品| 欧美精品一区二区久久婷婷| 亚洲国产精选| 亚洲一区二区精品视频| 在线观看成人网| 国产精品美女999| 欧美精品一区二区三区久久久竹菊 | 欧美精品18+| 亚洲一区在线观看视频| 免费观看在线综合| 久久精品国产v日韩v亚洲| 久久久在线视频| 99国产欧美久久久精品| 亚洲人成在线观看一区二区| 麻豆91精品| 免费观看在线综合色| 久久综合一区二区| 久热成人在线视频| 欧美一区二粉嫩精品国产一线天| 国产日韩在线一区二区三区| 国产精品捆绑调教| 欧美日韩成人在线播放| 欧美国产日韩精品免费观看| 久久亚洲一区二区三区四区| 久久久久se| 免费观看日韩av| 欧美日韩三级电影在线| 欧美日韩精品欧美日韩精品一 | 欧美一区二区三区四区在线观看地址| 亚洲国产精品久久久久婷婷884| 激情六月婷婷久久| 亚洲国产色一区| 99国产精品久久久久久久久久| 亚洲欧洲综合| 性亚洲最疯狂xxxx高清| 久久精品国产欧美激情| 久久久久久久综合日本| 欧美成人一区二免费视频软件| 亚洲国产一区二区三区高清| 亚洲视频你懂的| 美国十次成人| 国产日韩欧美黄色| 夜夜嗨av一区二区三区网站四季av| 亚洲专区一区二区三区| 老巨人导航500精品| 亚洲最新中文字幕| av成人手机在线| 可以看av的网站久久看| 久久人人九九| 亚洲欧美中日韩| 欧美日韩中文在线| 亚洲综合电影| 欧美三级在线视频| 在线亚洲国产精品网站| 亚洲激情av| 欧美成人亚洲成人| 91久久精品国产91性色tv| 久久午夜精品| 久久久福利视频| 伊人久久久大香线蕉综合直播 | 久久精品99国产精品日本| 欧美日韩免费| 亚洲九九爱视频| 一本久道久久综合婷婷鲸鱼| 亚洲欧美精品在线观看| 国产欧美日本在线| 老司机免费视频一区二区三区| 亚洲欧美日韩一区二区| 国产一区二区三区在线观看免费视频 | 欧美sm重口味系列视频在线观看| 这里只有精品电影| 狠久久av成人天堂| 亚洲精品老司机| 国产亚洲在线观看| 欧美护士18xxxxhd| 欧美色视频在线| 米奇777在线欧美播放| 欧美激情久久久久久| 香蕉乱码成人久久天堂爱免费 | 亚洲最新在线| 亚洲黄色在线| 性色av一区二区三区在线观看| 亚洲第一福利视频| 欧美亚洲免费高清在线观看| 夜夜躁日日躁狠狠久久88av| 欧美在线观看你懂的| 日韩视频久久| 欧美jizz19性欧美| 韩国精品一区二区三区| 亚洲私人影院| 欧美成人精品激情在线观看| 亚洲综合视频1区| 国产精品vvv| 亚洲一区二区三区中文字幕| 99精品视频免费| 欧美黑人一区二区三区| 欧美ed2k|