精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

自頂向下的語法分析器—采用遞歸下降方法

冬至子 ? 來源:趙同學的代碼時間 ? 作者:Jun. ? 2023-05-23 11:24 ? 次閱讀

在之前已經通過手寫的方式實現了一個詞法分析器,現在,我將利用之前手寫的詞法分析器,使用遞歸下降的方式,實現一個簡單的語法分析器。

首先看看實驗要求:

遞歸下降法編寫一個語法分析程序,使之與詞法分析器結合,能夠根據語言的上下文無關文法,識別輸入的單詞序列是否文法的句子。

為減輕實驗編程負擔,這里只要求實現部分產生式,文法的開始符號為 program

圖片

第一步,消除左遞歸。觀察上面各個產生式,出現左遞歸的地方有expr和term。

圖片

針對以上式子,首先提取左因子:

圖片

消除左遞歸:

圖片

觀察到 在if語句處也存在左公因子,一并提取,最終文法定義為:

圖片

定義好文法后,考慮詞法分析與語法分析的接口,由于采用遞歸下降的分析過程中,存在對token的回溯操作,因此,每次逐個獲取詞法單元并不容易實現,考慮將token對應的標志和內容使用pair的數組保存下來。

pair<int, string> tokens[10000];
int cursor_;
int tokens_size_;

并使用cursor_記錄當前準備分析的位置,通過移動cursor_實現對token串的回溯過程。然后根據每一條語句,寫出對應的梯度下降遞歸函數,就可以完成本實驗,使用yylex自動生成的方法也類似,只需要維護tokens數組即可。

// 工具函數:獲得一個向前看,但并不移動指針
pair<int, string> get_ahead(){
    return tokens[cursor_];
}


// 工具函數:嘗試匹配一個類型,匹配返回真
bool match(int type){
    if(cursor_ >= tokens_size_) return false;
    if(tokens[cursor_].first == type)
    {
        cursor_ ++;
        return true;
    }
    return false;
}


// 工具函數:嘗試匹配一個類型和字符串,都匹配返回真
bool match(int type, string target){
    if(tokens[cursor_].first == type && tokens[cursor_].second == target)
    {
        cursor_ ++;
        return true;
    }
    return false;
}


bool factor(){
    cout << "Try to match factor" << endl;
    if(match(IDENTITY)) return true;
    if(match(DIGIT)) return true;
    return match(SYMBOL, "(") && expr() && match(SYMBOL, ")");
}


bool B3(){
    cout << "Try to match B3" << endl;
    return match(SYMBOL, "%") && factor();
}


bool B2(){
    cout << "Try to match B2" << endl;
    return match(SYMBOL, "/") && factor();
}


bool B1(){
    cout << "Try to match B1" << endl;
    return match(SYMBOL, "*") && factor();
}


bool B(){
    cout << "Try to match B" << endl;
    int backup_cursor = cursor_;
    if(B1()) return true;
    cursor_ = backup_cursor;
    if(B2()) return true;
    cursor_ = backup_cursor;
    if(B3()) return true;
    cursor_ = backup_cursor;
    return false;
}


bool D(){
    cout << "Try to match D" << endl;
    pair<int, string> ahead = get_ahead();
    if(ahead.first == SYMBOL && (ahead.second == "*" || ahead.second == "/" || ahead.second == "%")) return B() && D();
    return true;
}


bool term(){
    cout << "Try to match term" << endl;
    return factor() && D();
}


bool A2(){
    cout << "Try to match A2" << endl;
    return match(SYMBOL, "-") && term();
}


bool A1(){
    cout << "Try to match A1" << endl;
    return match(SYMBOL, "+") && term();
}


bool A(){
    cout << "Try to match A" << endl;
    int backup_cursor = cursor_;
    if(A1()) return true;
    cursor_ = backup_cursor;
    if(A2()) return true;
    cursor_ = backup_cursor;
    return false;
}


bool C(){
    cout << "Try to match C" << endl;
    pair<int, string> ahead = get_ahead();
    if(ahead.first == SYMBOL && (ahead.second == "+" || ahead.second == "-")) return A() && C();
    return true;
}


bool expr(){
    cout << "Try to match expr" << endl;
    return term() && C();
}


bool F(){
    cout << "Try to match F" << endl;
    pair<int, string> ahead = get_ahead();
    if(ahead.first == RELOP) return match(RELOP) && expr();
    return true;
}


bool bool_(){
    cout << "Try to match bool" << endl;
    return expr() && F();
}


bool E(){
    cout << "Try to match E" << endl;
    pair<int, string> ahead = get_ahead();
    if(ahead.first == KEYWORD && ahead.second == "else") return match(KEYWORD, "else") && stmt();
    return true;
}


bool stmt6(){
    cout << "Try to match stmt choice 6" << endl;
    return block();
}


bool stmt5(){
    cout << "Try to match stmt choice 5" << endl;
    return match(KEYWORD, "break") && match(SYMBOL, ";");
}


bool stmt4(){
    cout << "Try to match stmt choice 4" << endl;
    return match(KEYWORD, "do") && stmt() && match(KEYWORD, "while") && match(SYMBOL, "(") && bool_() && match(SYMBOL, ")") && match(SYMBOL, ";");
}


bool stmt3(){
    cout << "Try to match stmt choice 3" << endl;
    return match(KEYWORD, "while") && match(SYMBOL, "(") && bool_() && match(SYMBOL, ")") && stmt();
}


bool stmt2(){
    cout << "Try to match stmt choice 2" << endl;
    return match(KEYWORD, "if") && match(SYMBOL, "(") && bool_() && match(SYMBOL, ")") && stmt() && E();
}


bool stmt1(){
    cout << "Try to match stmt choice 1" << endl;
    return match(IDENTITY) && match(SYMBOL, "=") && expr() && match(SYMBOL, ";");
}


bool stmt(){
    cout << "Try to match stmt" << endl;
    int backup_cursor = cursor_; // 指針的回溯
    if(stmt1()) return true;
    cursor_ = backup_cursor;
    if(stmt2()) return true;
    cursor_ = backup_cursor;
    if(stmt3()) return true;
    cursor_ = backup_cursor;
    if(stmt4()) return true;
    cursor_ = backup_cursor;
    if(stmt5()) return true;
    cursor_ = backup_cursor;
    if(stmt6()) return true;
    cursor_ = backup_cursor;
    return false;
}


bool stmts(){
    cout << "Try to match stmts" << endl;
    pair<int, string> ahead = get_ahead();
    if(ahead.first == SYMBOL && ahead.second == "}") return true;
    else return stmt() && stmts();
}


bool block(){
    cout << "Try to match block" << endl;
    return match(SYMBOL, "{") && stmts() && match(SYMBOL, "}");
}


bool program(){
    cout << "Try to match program" << endl;
    return block();
}

由于已經高度模塊化,main函數很簡單:

int main()
{
    if(!DFA()) return 0; // 詞法分析
    tokens_size_ = cursor_; 
    cursor_ = 0; // 初始化指針
    if(program()) cout << "ACCEPT !" << endl;
    else cout << "ERROR !" << endl;
}

測試:

使用實驗指導代碼測試:

input:
{
i = 2;
   sum = 0;
     while (i <=100)   {
          sum = sum + i;
       i = i + 2;
          if(i%5==0) break;
     }
}


output:
SYMBOL : {
i = 2;
IDENTITY : i
SYMBOL : =
DIGIT : 2
SYMBOL : ;
   sum = 0;
IDENTITY : sum
SYMBOL : =
DIGIT : 0
SYMBOL : ;
KEYWORD : while
SYMBOL : (
IDENTITY : i
RELOP : <=
DIGIT : 100
SYMBOL : )
SYMBOL : {
IDENTITY : sum
SYMBOL : =
IDENTITY : sum
SYMBOL : +
IDENTITY : i
SYMBOL : ;
IDENTITY : i
SYMBOL : =
IDENTITY : i
SYMBOL : +
DIGIT : 2
SYMBOL : ;
KEYWORD : if
SYMBOL : (
IDENTITY : i
SYMBOL : %
DIGIT : 5
RELOP : ==
DIGIT : 0
SYMBOL : )
KEYWORD : break
SYMBOL : ;
SYMBOL : }
SYMBOL : }
Try to match program
Try to match block
Try to match stmts
Try to match stmt
Try to match stmt choice 1
Try to match expr
Try to match term
Try to match factor
Try to match D
Try to match C
Try to match stmts
Try to match stmt
Try to match stmt choice 1
Try to match expr
Try to match term
Try to match factor
Try to match D
Try to match C
Try to match stmts
Try to match stmt
Try to match stmt choice 1
Try to match stmt choice 2
Try to match stmt choice 3
Try to match bool
Try to match expr
Try to match term
Try to match factor
Try to match D
Try to match C
Try to match F
Try to match expr
Try to match term
Try to match factor
Try to match D
Try to match C
Try to match stmt
Try to match stmt choice 1
Try to match stmt choice 2
Try to match stmt choice 3
Try to match stmt choice 4
Try to match stmt choice 5
Try to match stmt choice 6
Try to match block
Try to match stmts
Try to match stmt
Try to match stmt choice 1
Try to match expr
Try to match term
Try to match factor
Try to match D
Try to match C
Try to match A
Try to match A1
Try to match term
Try to match factor
Try to match D
Try to match C
Try to match stmts
Try to match stmt
Try to match stmt choice 1
Try to match expr
Try to match term
Try to match factor
Try to match D
Try to match C
Try to match A
Try to match A1
Try to match term
Try to match factor
Try to match D
Try to match E
Try to match stmts
Try to match stmts
ACCEPT !

最后發現梯度遞歸函數已經成功地接受了我們的輸入。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 分析器
    +關注

    關注

    0

    文章

    92

    瀏覽量

    12486
收藏 人收藏

    評論

    相關推薦

    [4.1.1]--向下語法分析及其面臨的問題

    編譯原理
    jf_60701476
    發布于 :2022年12月27日 11:27:59

    基于向下技術的工程機械Digital Prototyping設計方法及應用

    【作者】:劉雪冬【來源】:《華南理工大學》2009年【摘要】:向下的設計方法及裝配建模技術是在消費品行業應用比較成熟的一種設計方法和理論
    發表于 04-24 09:20

    postgreSQL命令的詞法分析語法分析

    PostgreSQL查詢SQL的語法分析(1)——詞法分析
    發表于 05-16 16:33

    如何實現擴頻通信調制向下的設計?

    如何實現擴頻通信調制向下的設計?如何實現擴頻通信調制的仿真測試?
    發表于 04-29 06:46

    一個高效的語法分析器生成工具

    VPGE(Visual Parser Generation Environment)是一個可視化語法分析器集成開發環境,除了具有良好的界面和強大的調試功能,其LALR(1)分析器的生成速度達到并超過公認的分析器生成速度最快
    發表于 08-29 10:04 ?16次下載

    YACC在ATLAS語言語法分析中的沖突消解研究

    對使用YACC工具進行ATLAS語言語法分析過程中出現的大量沖突進行了詳細的分類討論與研究,給出了實現過程中出現的主要沖突類型及相應解決方案:文法符號的不斷自身循環產生
    發表于 09-08 15:30 ?0次下載

    網絡分析器,網絡分析器原理是什么?

    網絡分析器,網絡分析器原理是什么? 網絡分析器   具有發現并解決各種故障特性的硬件或軟件設備
    發表于 03-22 11:25 ?1044次閱讀

    編譯原理實踐環節模擬試題

    1.為以下文法構造遞歸下降語法分析程序,并能對輸入串進行語法分析。 S aBc|bAB A aAb|b B b 2.試寫出簡單的詞法分析程序
    發表于 04-11 22:19 ?24次下載

    借助Lex和Yacc進行詞法語法分析

    實驗目的: 1.通過對實驗型程序設計語言C1的定義,掌握程序設計語言的基本語法和語義; 2.使用Lex及Yacc實現詞法分析語法分析
    發表于 04-18 23:04 ?30次下載

    交換機端口分析器

    本文將重點介紹“交換端口分析器(SPAN)”的工作原理及配置方法
    發表于 02-03 14:09 ?995次閱讀

    通過模塊之間的調用實現向下的設計

    通過模塊之間的調用實現向下的設計目的:學習狀態機的嵌套使用實現層次化、結構化設計。
    發表于 02-11 05:53 ?2441次閱讀
    通過模塊之間的調用實現<b class='flag-5'>自</b><b class='flag-5'>頂</b><b class='flag-5'>向下</b>的設計

    EDA設計一般采用向下的模塊化設計方法

    三方面的電子設計工作,即集成電路設計、電子電路設計以及PCB設計。總之,EDA技術的基本特征是采用具有系統仿真和綜合能力的高級語言描述。它一般采用
    發表于 01-21 16:50 ?9017次閱讀
    EDA設計一般<b class='flag-5'>采用</b><b class='flag-5'>自</b><b class='flag-5'>頂</b><b class='flag-5'>向下</b>的模塊化設計<b class='flag-5'>方法</b>

    開源L2C編譯前端語法分析器及驗證過程

    Jourdan等在其2012年發表的論文“ Validating Lr(1) Parsers”中提出了一種形式化驗證語法分析器方法,并將其成功地應用于 Compcert編譯(2.3以上版本
    發表于 05-19 10:55 ?5次下載

    計算機網絡:向下

    本文檔包含Jim Kurose和Keith Ross編寫的《計算機網絡:向下方法(第7版)》復習題和問題的參考答案。這些答案只對指導老師有效。請不要復制或者分發給其他人(即使是其他指導老師)。請
    發表于 03-13 14:23 ?0次下載

    eda向下的設計方法 eda自頂向下設計優點

    EDA(Electronic Design Automation,電子設計自動化)向下的設計方法是一種常見的電子電路設計方法。該
    發表于 04-10 16:49 ?3763次閱讀