C語言的lex和yacc工具說明

2021-05-08 02:35:04 字數 3863 閱讀 8967

一,lex工具

----------------------

lex工具是一種詞法分析程式生成器,它可以根據詞法規則說明書的要求來生成單詞識別程式,由該程式識別出輸入文字中的各個單詞。

1、lex程式的結構

-定義部分

-規則部分 

-使用者子程式部分

其中規則部分是必須的,定義和使用者子程式部分是任選的。

(1) 定義部分 

定義部分起始於"%"符號,其間可以是包括include語句、宣告語句在內的c語句。 

%(2) 規則部分

規則部分起始於"%%"符號,終止於"%%"符號,其間則是詞法規則。詞法規則由模式和動作兩部分組成。模式部分可以由任意的正規表示式組成,動作部分是由c語言語句組成,這些語句用來對所匹配的模式進行相應處理。需要注意的是,lex將識別出來的單詞存放在yytext字元資料中,因此該陣列的內容就代表了所識別出來的單詞的內容。

%% [/t]

[0-9]+/.?|[0-9]*/.[0-9]+

/n

. %%

(3) 使用者子程式部分

使用者子程式部分可以包含用c語言編寫的子程式,而這些子程式可以用在前面的動作中,這樣就可以達到簡化程式設計的目的。下面是帶有使用者子程式的lex程式片段。

"/*" skipcmnts();

. /* rest of rules */

%% skipcmnts()

2、lex工具的使用方法

首先編寫乙個lex程式

vi lex.l

% %%

[/n] ;

[0-9]+ printf("interger: %s /n",yytext);

[0-9]*/.[0-9]+ printf("float: %s/n",yytext);

[a-za-z][a-za-z0-9]* printf("word:%s/n",yytext);

. printf("other symbol:%c/n",yytext[0]);

%% 然後使用lex將lex.l轉換成c語言程式

$lex lex.l

使用上述命令產生的c語言程式為lex.yy.c

然後使用c編譯程式將lex.yy.c編譯成可執行程式regn

$cc -c lex.yy.c

$cc lex.yy.o -ll -o regn

下面可以使用regn來識別單詞

$vi testfile

x=355

y=113

p=x/y

# ./regn < testfile

word:x

other symbol:=

interger: 355

word:y

other symbol:=

interger: 113

word:p

other symbol:=

word:x

other symbol:/

word:y

#二,yacc工具

-----------------------

yacc工具是一種語法分析程式生成器,它可以將有關某種語言的語法說明書轉換成相應的語法分析程式,由該程式完成對相應語言中語句的語法分析工作。

1、yacc程式結構

在使用yacc工具前,必須首先編寫yacc程式,因為有關語法分析程式是根據yacc程式生成的。yacc程式實際上是有關語法規則的說明書,它也是由定義部分、規則部分和子程式部分組成的。yacc程式的定義部分類似於lex程式的定義部分,只是在其後可帶有yacc宣告,其中包括詞法單詞、語法變數、優先順序和結合性資訊。yacc程式的規則部分由語法規則和相應的動作組成,子程式部分可以包括在前面規則部分用到的子程式定義。接下來是main主程式,它呼叫yyparse子程式來對輸入進行語法分析,而yyparse反覆地呼叫yylex子程式來獲得輸入單詞,在語法出錯時可通過yyerror子程式來處理。

2、yacc工具的使用方法

例項:我們將yacc程式分成片段,把這些片段組合在一起就是yacc程式。我們要使用的語法規則是乙個有關四則運算的語法規則,可用bnf正規化描述

list: expr /n

list expr /n

expr :number

expr + expr

expr - expr

expr * expr

expr / expr

(expr)

其含義是list是乙個表示式序列,每個後面帶有乙個新行。表示式是乙個數值,或是由運算子連起來的兩個表示式,以及用圓括號括起來的表示式。

下面是有關上述語法規則的yacc程式片段。

$vi hoc.y

% %token number

%left '+' '-'

%left '*' '/'

%% list:

| list '/n'

| list expr '/n'

; expr : number

| expr '+' expr

| expr '-' expr

| expr '*' expr

| expr '/' expr

| '('expr')'

%% 上述yacc程式片段實際上是它的定義部分和規則部分。在yacc宣告部分,%token number表明了number是乙個單詞符號,%left則表明了運算符號的左結合性,並且'*'和'/'和優先順序比'+'和'-'的優先順序高。在yacc程式的規則部分,備用規則是用'|'隔開的,規則中的動作實際上是c語句序列,其中$n(即$1,$2等)是用來引用規則中的第幾個成份,而$$則代表了整個規則的返回值。

下面的yacc程式片段是main主程式

#include

#include

char *progname;

int lineno=1;

main(argc,argv)

int argc;

char *argv;

main主程式呼叫yyparse子程式來處理來處理輸入,而yyparse又是通過yylex子程式來獲得輸入單詞並通過yyerror子程式來報告出錯資訊。下面是有關這兩個子程式的yacc程式片段

yylex()

if(c=='/n')

lineno++;

return c;

} yyerror(s)

char *s;

warning(s,t)

char *s,*t;

這樣就完成了整個yacc程式

接下來就使用 yacc將hoc.y轉換成c語言程式

$yacc hoc.y

使用上述命令產生的c語言程式為y.tab.c,這時可以使用c編譯程式將它編譯成可執行程式hoc.

$cc y.tab.c -o hoc

下面是使用hoc的例子

# ./hoc

4*3*2

24 (1+2)*(3+4)

21 1/2

0.5

355/133

2.6691729

-3-4

./hoc:syntax error near line 5

上述結果顯示中,分別表明了計算結果,最後一次計算出錯的原因是由於在規則定義中未來定義單目減運算符號。

Lex和yacc工具介紹

在編譯過程中,詞法分析和語法分析是兩個重要階段。lex和yacc是unix環境下非常著名的兩個工具,可以生成分別完成詞法分析和語法分析功能 的c 在學習編譯原理過程中,可以善加利用這兩個工具,加深對兩個階段的理解。在平時的工作中,這兩個工具也會起到重要的作用。lex是lexical compiler...

yacc 和 lex的上手 3

昨天看完了lex相關的例子,今天開始看yacc部分的例子 sample 4 乙個簡單的恆溫控制器 突然記起來大三時候做過的fuzzy logic的東東了 目標 我們有乙個恆溫器,想用簡單的語言來控制它,就像下面這樣 heat on heater on heat off heater off targ...

有用的C語言工具(Ubuntu Linux版本)

c專家程式設計 裡的第六章介紹了一些有趣 有用的c語言工具。可能因為此書寫成年代距今已遠且目標為sunos這個unix系統,有些工具在我的ubuntu中是無法使用的。因此我簡單測試了一下,總結了這些能在我的linux上用的工具。用於檢查源 的工具工具 位於何處 所做工作 indent sudo ap...