日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BISON

發(fā)布時間:2024/3/26 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BISON 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 工作原理
    • .y文件結(jié)構(gòu)
    • 原理
    • 編譯運(yùn)行
    • 語義 (語義值類型,語義動作)
    • 聲明部分(終結(jié)符,編碼,結(jié)合律,優(yōu)先級)
    • 優(yōu)先級和結(jié)合律
    • bison 無法處理的語法
  • 語法與內(nèi)置函數(shù)
  • 編譯選項
  • 沖突與出錯處理
    • 沖突
    • 出錯處理
    • 跟蹤分析過程
  • flex & bison
    • 原理
    • 例子(后綴表達(dá)式的計算):

工作原理

.y文件結(jié)構(gòu)

  • YYSTYPE 語義值類型
  • %token NUM ?定義終結(jié)符NUM
  • yyerror 必須用戶自己提供
  • int yylex() ? 這個例子中使用自己編寫的yylex,實際會使用flex編譯的文件所提供的yylex
  • 產(chǎn)生式右邊為空表示 ?\epsilon?
  • 產(chǎn)生式后面的c語言代碼稱為語義動作
  • $$ 表示產(chǎn)生式左部的語義值
  • $1,$2,…分別表示右邊第一,第二個符號的語義值
  • yylval 是全局變量,表示當(dāng)前所識別的詞形的語義值。
%{ c 語言說明部分,定義語義動作中需要的全局變量,語義值類型,以及頭文件等 // 逆波蘭表達(dá)式的計算 #define YYSTYPE int #include <ctype.h> #include<stdio.h> void yyerror(char*); int yylex(); %}聲明部分 定義終結(jié)符, 規(guī)定非終結(jié)符語義值類型,規(guī)定運(yùn)算優(yōu)先級,規(guī)定文法形態(tài)等 %token NUM%% 語法規(guī)則部分,定義產(chǎn)生式和語義動作 input: /*empty equal to epsilon*/| input line; line: '\n'|exp '\n' {printf("\%.d\n",$1);}; exp: NUM {$$ = $1;}| exp exp '+' {$$ = $1+$2;}| exp exp '-' {$$ = $1-$2;}| exp exp '*' {$$ = $1*$2;}| exp exp '/' {$$ = $1 / $2;}| exp 'n' {$$ = -$1; }; %% // 附加c語言代碼: bison直接拷貝到.tab.c文件的尾部,用戶再次可定義接口函數(shù),也可由其它文件提供再鏈接。 int yylex(){int c;/*skip white space*/while((c=getchar())==' '||c=='\t');/*process numbers*/if(isdigit(c)){ungetc(c, stdin);scanf("%d",&yylval);return NUM;}if(c==EOF) return 0;return c; }int main(void){return yyparse(); }void yyerror(char*s){printf("%s\n",s); }

原理

  • 對輸入.y文件中的形式文法構(gòu)架LALR分析表,并生成基于該分析表的語法分析器C語言源程序.tab.c。
  • bison 通過 int yylex() 的返回值獲得單詞的編碼;通過全局變量YYSTYPE yylval獲得當(dāng)前單詞的語義值.
  • 分析方法采用自頂向上的移進(jìn)/規(guī)約法,完成規(guī)約時,yyparse()將執(zhí)行bison源文件對應(yīng)產(chǎn)生式的語義動作。
  • 必要的語法環(huán)境:yylex(),main(), yyerror(), 其中yylex可由用戶提供,也可由flex源程序提供,然后和bison源程序一起連接成可執(zhí)行文件

編譯運(yùn)行

  • bision rpcalc.y
  • gcc -o rpcalc rpcalc.tab.c
  • rpcalc (啟動程序)

語義 (語義值類型,語義動作)

語義值類型

  • 由于在移進(jìn)、規(guī)約的時候是拷貝進(jìn)棧,所以當(dāng)語義值的類型是指針時,所指的地址一定不能是局部變量。安全的做法是:生命周期開始時通過動態(tài)申請內(nèi)存所指的值保存,生命周期結(jié)束時釋放該內(nèi)存(動態(tài)內(nèi)存分配)
  • 通過%union 在聲明部分講YYSTYPE定義為C語言的union結(jié)構(gòu)。
    • 對于非終結(jié)符,通過 %type \<union 分量名> 非終結(jié)符名 來規(guī)定語義動作中以何種方式訪問語義值對應(yīng)的類型。
    • 對于非終結(jié)符,使用 %token \<union 分量名> 終結(jié)符名,或者%type規(guī)定。
    • 在語義動作中,使用$<comp_name>m訪問
%union { double val; /* 表達(dá)式的語義值 */ SYMREC *tptr; /* 變量和函數(shù)的語義值是符號表元素指針 */ } %token<val> NUM /* 語義值的類型是雙精度浮點數(shù) */ %token<tptr> VAR FNCT /* 語義值的類型是符號表元素指針 */ %type<val> exp

語義值聲明周期

  • 在語義棧中存在的時間
  • 比如 NUM的生命周期從yylex()通過scanf("%d",&yylval)創(chuàng)建,然后壓入語義棧中,隨后規(guī)約exp:NUM {$$=$1}, NUM的語義值從棧中退出,exp的語義值壓入。

語義動作的翻譯

源文件中的

exp: exp exp '\' {$$ = $1 \ $2;}

會被翻譯為:
(yyval)=(yyvsp[(1)?(3)])/(yyvsp[(2)?(3)]);(yyval) = (yyvsp[(1) - (3)]) / (yyvsp[(2) - (3)]);(yyval)=(yyvsp[(1)?(3)])/(yyvsp[(2)?(3)]);
yyvsp 是一個棧棧頂是yyvasp[0], 越往棧底走,索引依此減1,這個例子的存儲數(shù)據(jù)為:
(棧頂)’\’ $2 $1

語義動作

  • 尾部語義動作
    產(chǎn)生式尾部的語義動作在發(fā)現(xiàn)該產(chǎn)生式句柄時已經(jīng)在棧頂形成,需要對該產(chǎn)生式進(jìn)行規(guī)約時進(jìn)行。語義動作包括計算綜合屬性(S屬性)和產(chǎn)生副作用

每個產(chǎn)生式有一個默認(rèn)動作 {$$=$1;}

  • 產(chǎn)生式中間語義動作
    用來解決**繼承屬性(L屬性)**的計算



    在這里插入圖片描述

聲明部分(終結(jié)符,編碼,結(jié)合律,優(yōu)先級)

bison將終結(jié)符分為兩類:字符(Symbol)和單詞(Token). Token需要聲明,字符在產(chǎn)生式(語法規(guī)則)中直接用字符常量,注意加引號’ '。如 exp: exp exp + 是錯的

  • token對終結(jié)符的編碼規(guī)則
    • 0或負(fù)數(shù): 文件結(jié)束標(biāo)記
    • 字符單詞:對應(yīng)的ASCII碼
    • error: 256
    • 非字符單詞從258開始順序編碼, 在.tab.c中可以找到具體定義

在使用單獨的詞法分析模塊的時候,需要bison需要使用 -d 選項,這樣講token的宏定義等輸出到.tab.h 文件中,這樣詞法分析模塊可以include此頭文件來使用宏定義的token。

  • 規(guī)定結(jié)合律
    %left ‘+’ ‘-’

優(yōu)先級和結(jié)合律

%left '+' '-' %left '*' '/' %left UMINUS %% exp : exp '+' exp | exp '-' exp | exp '*' exp | exp '/' exp | '-' exp %prec UMINUS;
  • 結(jié)合性:%left 左結(jié)合; %right 右結(jié)合;%nonassoc 不能結(jié)合;
  • 出現(xiàn)在同一個%left后的單詞優(yōu)先級相同
  • 優(yōu)先級:出現(xiàn)在不同 “%left” 的終結(jié)符,其運(yùn)算優(yōu)先級別按照 “%left” 在源文件中出現(xiàn) 的先后次序由低到高排列, 即:UMINUS的優(yōu)先級最高,乘法和除法次之,加法和 減法最低.
  • 由于一元減和二元減的運(yùn)算符相同,在語法中出現(xiàn)一元減的產(chǎn)生式通過%prec UNIMUS設(shè)定一元減和UMINUS具有相同的優(yōu)先級.

bison 無法處理的語法

?bison語法分析器可以使用兩種分析方法,一種是LALR(1), 另一種是GLR(通用的自左向右)。GLR更強(qiáng)大但更麻煩。
? LALR(1)不能處理的語法有:

  • 有歧義的語法
  • 需要向前查看超過1個記號才能確定是否匹配的語法。

語法與內(nèi)置函數(shù)

變量說明
yylval當(dāng)前終結(jié)符語義值的全局變量
YYSTYPE語義值數(shù)據(jù)類型

編譯選項

選項說明
-d輸出文件 .tab.h
-v輸出分析表文件 name.output
-t在輸出文件(.tab.c)中設(shè)置宏YYDEBUG 為1, 從而打開分析器的調(diào)試代碼,使得最后生成的分析器文件能夠?qū)Ψ治鲞^程進(jìn)行追蹤。

沖突與出錯處理

沖突

  • 輸出沖突的報警信息:打開-t選項,在LALR(1)分析表文件.output文件中指出沖突所在
  • 如果是S/R沖突,優(yōu)先S
  • 如果是RR沖突,排列在前者優(yōu)先。

出錯處理

  • 如果在 bison 輸入文件中沒有任何提供任何出錯處理,輸出分析器在工作時,如果發(fā)現(xiàn)語法錯誤 (即在當(dāng)前狀態(tài)下面對當(dāng)前的終結(jié)符不能進(jìn)行任何移進(jìn)或歸約 操作), yyparse()在傳參 “syntax error” 調(diào)用用戶提供的void yyerror(char const *)函數(shù)后,返回1退出yyparse().
  • 通常yyerror可定義如下:
void yyerror(char const *s) { fprintf(stderr, "%s\n", s); }
  • bison 通過預(yù)留的終結(jié)符 error 提供從出錯狀態(tài)恢復(fù)分析的機(jī)制, 如:
    stmnts:/?emptystring?/stmnts: /* empty\ string */ stmnts:/?empty?string?/ ∣stmnts′\n′| stmnts\ \ '\backslash n'stmnts??\n ∣stmntsexp′\n′| stmnts\ \ exp \ \ '\backslash n'stmnts??exp??\n ∣stmntserror′\n′| stmnts\ \ error\ \ '\backslash n'stmnts??error??\n
    在產(chǎn)生式右邊有保留終結(jié)符 error 的規(guī)則稱為錯誤恢復(fù)規(guī)則,輸出分析器在一 個含有錯誤恢復(fù)規(guī)則的狀態(tài)出錯時,首先從分析棧中彈出語法符號直到能 將 error 移進(jìn),在棧頂形成錯誤恢復(fù)規(guī)則中 error 前的句型為止,如上例中在 分析exp 時出錯,將彈出所有的已分析的表達(dá)式成分,將 error 壓棧到項目, 此時棧中符號為:{stnmts error . ‘\n’}; 然后,跳過所有的輸入直到遇到錯誤恢 復(fù)規(guī)則規(guī)中error的后隨符號為止. 如上例中將跳過所有的輸入直到’\n’ 才恢 復(fù)分析.
  • 在錯誤恢復(fù)規(guī)則中可以像其他規(guī)則一樣有語義動作,但是不能引用終結(jié) 符error的語義值.
  • 在某一錯誤恢復(fù)規(guī)則起作用時,為了防止分析器頻繁報錯,輸出分析器規(guī)定只 有在連續(xù)移進(jìn)三個單詞后才恢復(fù)報錯,在錯誤恢復(fù)規(guī)則語義動作中,可以使用 bison 提供的 C 語言宏 “yyerrok;” 解消上述限定,即刻恢復(fù)報錯機(jī)制.
  • 在激活錯誤恢復(fù)規(guī)則后,當(dāng)前向前查看的單詞將會繼續(xù)作為向前查看符號進(jìn)行 分析,如果用戶希望跳過該單詞,可在語義動作中用 bison 提供的宏 “yyclearin;” 跳過當(dāng)前單詞. 但是由于該操作是在歸約出錯產(chǎn)生式時才起作用, 因此如果錯誤恢復(fù)規(guī)則中error 之后還有終結(jié)符,只有移進(jìn)該終結(jié)符才能有語 義動作,因此 “yyclearin;” 將無任何效果. “yyclearin;” 有效當(dāng)且僅當(dāng)它是 在緊隨error之后的動作中

跟蹤分析過程

調(diào)用yyparse()前,置yydebug非零,如下的main.c

main() { extern int yydebug;yydebug = 1;yyparse(); }

flex & bison

原理

?ex 輸出的單詞掃描程序正是int yylex(), 為了讓 bison 輸出的語法分析源程序能與 ?ex 輸出的詞法分析源程序協(xié)同工作,必須保證單詞編碼的一致,以及 語義值數(shù)據(jù)類型的一致, 這要求在 ?ex 源程序中:

  • 1 定義部分包含 bison 輸出的頭文件.tab.h
  • 2 根據(jù)語法規(guī)則中的單詞設(shè)計匹配單詞的正規(guī)表達(dá)式,及需要過濾的白字符 (white space) 和注釋, 如: ‘\n’ 如果是語義規(guī)則所需的單詞,就不能冒然 過濾掉
  • 3 在識別單詞的 C 語言動作中,如果該單詞有語義值,應(yīng)先計算其語義值并 賦值到全局變量yylval,如果是字符單詞,return yytext[0];,否 則return 單詞名;
  • 4 為了保證詞法分析能處理所有的字符,對語法分析不支持的字符的的動作報錯并過濾
  • 5 bison 使用的單詞名不能與 ?ex 中自帶的宏名有沖突. 如: BEGIN不能作為 單詞名, 否則return BEGIN;將調(diào)用 ?ex 預(yù)置的宏BEGIN, 而不能返回期望的單 詞編碼, 可修改單詞名為SBEGIN來避免沖突.

例子(后綴表達(dá)式的計算):

rpcacle.y:

%{ // 逆波蘭表達(dá)式的計算 // #define YYSTYPE int 默認(rèn)int #include<stdio.h>void yyerror(char*); int yylex(); %}%token NUM %token ADD SUB MUL DIV %token EOL%% input: /*empty equal to epsilon*/| input line; line: EOL| exp EOL {printf("\%d\n",$1);}; exp: NUM {$$ = $1;}| exp exp ADD {$$ = $1+$2;}| exp exp SUB {$$ = $1-$2;}| exp exp MUL {$$ = $1*$2;}| exp exp DIV {$$ = $1 / $2;}; %%int main(void){ int n=yyparse();printf("%d",n);return n; }void yyerror(char*s){printf("%s\n",s); }

rpcalc.l

%{ #include "rpcalc_fb.tab.h"%}%% "+" { return ADD; } "-" { return SUB; } "*" { return MUL; } "/" { return DIV; }[0-9]+ { yylval = atoi(yytext); return NUM; }\n { return EOL; } "//".* [ \t] { /* ignore white space */ } . { printf("Mystery character %c\n", *yytext); } %%

總結(jié)

以上是生活随笔為你收集整理的BISON的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 91福利片 | 黄色理伦 | 国产美女www爽爽爽视频 | 国产福利合集 | 国产日韩欧美综合在线 | 国产伦精品一区二区三区免.费 | 一区在线观看视频 | 天天干天天玩 | 免费看一级黄色大全 | 欧美精品在线观看 | 在线观看污污视频 | 老司机一区二区三区 | 草av在线 | av一级大片| 一区二区三区精品在线 | 97精品熟女少妇一区二区三区 | 特及毛片| 特黄a级片 | 一区二区在线看 | 4438全国成人免费 | 我们2018在线观看免费版高清 | 精品国产91久久久久久 | 国产激情一区二区三区四区 | 99热超碰在线 | 亚洲色图欧美日韩 | 影音先锋成人 | 99自拍 | 综合五月| 中日韩免费视频 | 日韩成人一区二区视频 | 欧美粗暴jizz性欧美20 | 日韩av高清在线观看 | 久久一二三区 | 中文字幕免 | 奇米在线观看 | 熟妇女人妻丰满少妇中文字幕 | 黄色com | 欧美爽妇 | 国产卡一卡二卡三无线乱码新区 | 日韩h在线观看 | 射射av| 欧美一区二区三区不卡视频 | 亚洲一区二区 | 偷偷久久 | 伊人久久精品视频 | 日韩资源在线 | 日韩欧美在线一区二区三区 | 香蕉视频911 | 另类av小说 | 91美女片黄 | 亚洲精品国产精品乱码 | www.自拍偷拍 | av丝袜在线| 国产wwwwww| 在线免费不卡视频 | 素人一区二区三区 | 成年人三级网站 | 中文字幕在线观看日韩 | 国产免费观看久久黄av片 | 成人性生活免费视频 | jzzijzzij亚洲成熟少妇在线播放 狠狠躁日日躁夜夜躁2022麻豆 | 亚洲视频在线一区 | 雪花飘电影在线观看免费高清 | 日本黄色一级视频 | 天堂视频在线观看免费 | 天天色天 | 午夜丰满寂寞少妇精品 | 国产九九 | 日本在线中文 | 伊人久久大香线蕉综合75 | 在线成人一区二区 | 麻豆精品国产 | mm1313亚洲精品 | 蜜美杏av | 东北少妇不带套对白 | 夜夜嗨网站 | 欧美一区二区国产 | 中文日韩字幕 | 欧美高清x | 日本一本久久 | 成人国产精品一区二区 | 日日摸日日碰 | 欧美日韩生活片 | 潘金莲一级淫片a.aaaaa播放 | 欧美亚洲一 | 日韩欧美卡一卡二 | 怡红院国产 | 美女网站全黄 | 巨胸大乳www视频免费观看 | 三日本三级少妇三级99 | 伊在线久久丫 | 少妇毛片一区二区三区粉嫩av | 高清无码视频直接看 | 亚洲少妇xxx| 免费激情视频网站 | 亚洲第一精品在线 | 日韩国产一级 | 亚州福利 | 91九色蝌蚪 |