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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

3.03 bison移进/规约冲突和操作符优先级

發布時間:2024/3/26 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 3.03 bison移进/规约冲突和操作符优先级 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如果你已經儲備bison的相關基礎知識,閱讀理解下面的代碼會輕松得多。沒有bison基礎的同學請點擊查看bison基本的語法規則及相關介紹

移進/規約沖突一般是由文法二義性造成的,關于二義性可以看看這篇文章,以及這位中科院老師的講解。對于這種問題bison提供了一個聰明的方法,它可以在語法規則之外單獨描述優先級。這不僅消除了二義性,也使得語法分析器代碼變得短小而且易于維護。

bison操作符優先級的規則

bison操作符優先級的規則,使用%left,%right,%nonassoc或%precedence聲明記號并指定其優先級和結合性。它的語法與%token語法非常相似,如下:

%left symbols… %left <type> symbols…

以表達式“ x op y op z”為例,運算符op的關聯性決定了運算符嵌套,是通過先將x與y分組還是先將y與z分組來解析。

  • %left指定左相關性(將x與y優先分組)
  • %right指定右相關性(將y與z優先分組)
  • %nonassoc未指定結合性,這意味著“ x op y op z”被視為語法錯誤。
  • %precedence僅賦予符號優先級,并且根本不定義任何關聯性。使用此命令僅定義優先級,并保留由于啟用了結合性而引起的任何潛在沖突。
  • 運算符的優先級確定它如何與其他運算符嵌套。在單個優先級聲明中聲明的所有標記都具有相同的優先級,并根據它們的關聯性嵌套在一起。當在不同優先級聲明中聲明的兩個標記相關聯時,后一個聲明的標記具有更高的優先級,并且首先分組。

    結合下面的一個例子進一步學習bison操作符的優先級規則:

    %{enum Node_T{NT_UNDEF,NT_ADD,NT_SUB,NT_MUL,NT_DIV,NT_ABS,NT_NEG,};struct ASTNode *newast(int NodeType, struct ASTNode *Lft, struct ASTNode *Rht);struct ASTNode *newnum(double d); %}/* %union關鍵字聲明了語法規則中所有語法值可能會用到的數據類型的一個集合 */ %union{struct ASTNode *a; } /* 聲明的順序決定了優先級,越后聲明的優先級越高。bison遇到移進/規約沖突時,它將查詢優先級表,來解決沖突 */ %left '+' '-' %left '*' '/' %nonassoc '|' UMINUS // UMINUS為符號操作符的偽記號。使用%nonassoc來聲明'|'和UMINUS,表示這兩個操作符沒有結合性,并且它們具有最高的優先級。%type <a> exp%% ... exp: exp '+' exp { $$ = newast(NT_ADD, $1, $3); }| exp '-' exp { $$ = newast(NT_SUB, $1, $3); }| exp '*' exp { $$ = newast(NT_MUL, $1, $3); }| exp '/' exp { $$ = newast(NT_DIV, $1, $3); }| '|' exp { $$ = newast(NT_ABS, $2, NULL); }| '(' exp ')' { $$ = $2; }| '-' exp %prec UMINUS { $$ = newast(NT_NEG, NULL, $2); } // '-'原本聲明時的優先級要小于'*',使用%pre UMINUS,可以讓'-'擁有UMINUS的優先級。從而使得表達出"負號"的效果| NUMBER { $$ = newnum($1); } %%

    什么時候不應該使用優先級規則

    使用優先級規則解決移進/規約沖突時,有的時候會寫出讓人難以明白的語法規則。例如下面情況:表達式語法或解決在if/then/else語言結構的語法中的"dangling else"沖突,如下:

    一個經典的例子:
    Statement→if?Exprthen?Statementelse?Statement∣if?Exprthen?Statement∣Assignment∣...otherstatements...\begin{aligned} Statement \rightarrow&\ \text{if}\ Expr\ \text{then} \ Statement\ \text{else}\ Statement\\ &|\text{if}\ Expr\ \text{then} \ Statement\\ &|Assignment\\ &|\ \ ...other statements... \end{aligned} Statement??if?Expr?then?Statement?else?Statementif?Expr?then?StatementAssignment??...otherstatements...?
    從這個語法片段可以看出,else是可選的。不幸的是,下列代碼片段:

    if?Expr1then?if?Expr2then?Assignment1else?Assignment2\text{if}\ Expr1\ \text{then}\ \text{if}\ Expr2\ \text{then}\ Assignment1\ \text{else}\ Assignment2if?Expr1?then?if?Expr2?then?Assignment1?else?Assignment2

    這種語法的二義性,應該通過修正語法來解決沖突。引入新的規則來確定到底由哪個if來控制特定的else子句。應該將上面的語法規則修改為:
    Statement→if?Exprthen?Statement∣if?Exprthen?WithElseelse?Statement∣AssignmentWithElse→if?Exprthen?WithElseelse?WithElse∣Assignment\begin{aligned} Statement \rightarrow&\ \text{if}\ Expr\ \text{then} \ Statement\\ &|\text{if}\ Expr\ \text{then} \ WithElse\ \text{else}\ Statement\\ &|Assignment\\ WithElse \rightarrow&\ \text{if}\ Expr\ \text{then} \ WithElse\ \text{else}\ WithElse\\ &|Assignment\\ \end{aligned} StatementWithElse??if?Expr?then?Statementif?Expr?then?WithElse?else?StatementAssignment?if?Expr?then?WithElse?else?WithElseAssignment?
    通常出現二義性語法都可以通過引入新的規則來消除二義性,這樣做會增加語法樹的高度。

    總結

    以上是生活随笔為你收集整理的3.03 bison移进/规约冲突和操作符优先级的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。