編譯原理--期末復習

本文是我學習以下博主視頻所作的筆記,寫的不夠清晰,建議大家直接去看這些博主的視頻,他/她們講得非常好:

基礎知識+概念:
1.【【編譯原理】期末復習 零基礎自學】,資料

2.【編譯原理—混子速成期末保過】,評論區樓主筆記

注重題型+解法:

1.【1編譯原理求語法樹的短語直接短語等等】, 對應的資料:鏈接,提取碼:ozz4

2.【編譯原理根據正規表達式構造NFA,到DFA,以及最后的DFA化簡/最小化】,對應的資料:鏈接,提取碼:uwud

在此對上述博主的產出表示感謝,也希望大家都能高分通過期末考試~


引論

一、高級語言與低級語言的定義

1. 高級語言(High-Level Language)
  • 定義
    高級語言是一種接近人類自然語言(如英語)和數學表達式的編程語言,屏蔽了計算機硬件細節(如內存地址、寄存器操作),使用更抽象的語法(如函數、類、循環)描述邏輯。
    • 例子:Python、Java、C++、C#、JavaScript、Go 等。
  • 特點
    • 可讀性強:語法接近自然語言,易于理解和維護(如 if (x > 0) { ... })。
    • 平臺無關性:代碼可在不同操作系統(Windows/Linux/macOS)和硬件架構上移植,無需針對底層硬件重寫。
    • 抽象程度高:提供內置數據結構(數組、對象)、內存管理(自動垃圾回收)、高級控制結構(循環、遞歸)等。
2. 低級語言(Low-Level Language)
  • 定義
    低級語言是直接面向計算機硬件(CPU、內存、寄存器)的編程語言,貼近機器指令格式,需手動處理底層細節。
    • 分類
      • 機器語言:由二進制指令(0/1序列)組成,是CPU唯一能直接執行的語言(如 10110000 表示加載數據到寄存器)。
      • 匯編語言:用助記符(如 MOVADD)替代二進制指令,需通過匯編器轉換為機器語言(如 MOV AX, 1 表示將數值1存入AX寄存器)。
  • 特點
    • 可讀性差:語法復雜,依賴硬件架構(不同CPU的匯編指令集不同,如x86、ARM)。
    • 平臺依賴性強:代碼只能在特定硬件或操作系統上運行。
    • 控制精細:可直接操作內存地址、寄存器,適合編寫高性能或硬件驅動程序。

二、高級語言需要編譯/鏈接的原因

1. 計算機只能執行機器語言

高級語言代碼(如C語言的 .c 文件)無法被CPU直接執行,必須經過 翻譯過程 轉換為機器語言(二進制可執行文件)。這一過程通常包括 編譯、鏈接 等步驟,目的是將抽象的高級語法轉換為CPU能理解的指令序列。

2. 編譯(Compilation)的作用
  • 步驟
    1. 預處理:處理 #include 頭文件、#define 宏定義(如展開代碼)。
    2. 編譯:將高級語言代碼轉換為 匯編語言(中間形式)。
    3. 匯編:將匯編語言轉換為 目標文件.o.obj,包含二進制機器指令,但未解決外部依賴)。
  • 輸出:目標文件(二進制,但可能包含未解析的符號,如調用其他文件的函數)。
3. 鏈接(Linking)的作用
  • 解決依賴
    目標文件可能引用其他文件的函數(如C標準庫的 printf)或全局變量,鏈接器負責:
    1. 合并目標文件:將多個 .o 文件(如主函數和自定義函數)合并為一個整體。
    2. 解析符號引用:將未定義的符號(如函數名)映射到實際內存地址。
    3. 鏈接庫文件:引入標準庫(如C的 libc)或第三方庫的代碼。
  • 輸出:可執行文件(.exe 或無擴展名,能直接在操作系統中運行)。

三、編譯型語言 vs. 解釋型語言

高級語言按翻譯方式分為兩類:編譯型解釋型,核心區別在于翻譯過程是“一次性完成”還是“邊運行邊翻譯”。

1. 編譯型語言(Compiled Language)
  • 工作流程
    源代碼 → 編譯器(Compiler) → 目標代碼(機器語言)→ 鏈接器 → 可執行文件。
  • 特點
    • 一次編譯,多次執行:編譯后的可執行文件可直接運行,無需重新編譯(如C語言的 .c 文件編譯為 .exe)。
    • 執行效率高:機器語言直接由CPU執行,速度快(適合計算密集型任務,如游戲、操作系統)。
    • 平臺依賴性:不同操作系統/CPU架構需重新編譯(如Windows的 .exe 不能在Linux直接運行,這里如何實現跨平臺,可以參考這個視頻:【這個問題99%的人會答錯!包括我】)。
  • 例子:C、C++、Go、Rust。
2. 解釋型語言(Interpreted Language)
  • 工作流程
    源代碼 → 解釋器(Interpreter) → 邊逐行翻譯邊執行(不生成獨立的可執行文件)。
    • 部分語言(如Java、Python)會先生成中間形式(字節碼),再由虛擬機(JVM、Python解釋器)解釋執行。
  • 特點
    • 跨平臺性強:只要目標平臺安裝解釋器/虛擬機,代碼即可運行(如Python代碼在Windows/Linux上無需修改)。
    • 執行效率較低:每次運行都需翻譯,速度慢于編譯型語言(適合快速開發、腳本任務)。
    • 動態類型支持:變量類型在運行時確定,靈活性高(如Python的 x = 1x = "hello" 無需聲明類型)。
  • 例子:Python、JavaScript、Ruby、PHP、Perl。
3. 混合類型(中間形式)
  • Java、C#:先編譯為字節碼(平臺無關的中間代碼),再由虛擬機(JVM、.NET CLR)解釋執行,兼具編譯型的跨平臺性和解釋型的靈活性。
  • Python(優化模式):可通過 pyc 文件緩存字節碼,減少重復翻譯,但本質仍是解釋執行。

四、核心區別對比

特性編譯型語言解釋型語言
翻譯時機運行前一次性編譯為機器碼運行時逐行解釋執行
執行效率高(機器碼直接執行)低(解釋器逐條翻譯)
跨平臺性差(需針對不同平臺重新編譯)好(依賴解釋器/虛擬機)
開發效率低(編譯錯誤需重新編譯)高(即時反饋,無需編譯步驟)
典型場景系統級開發、高性能計算腳本編寫、Web開發、快速原型
代表語言C、C++、GoPython、JavaScript、Ruby

五、總結

  • 高級語言 提升開發效率,屏蔽硬件細節;低級語言 控制硬件,實現高性能。
  • 編譯/鏈接 是將高級語言轉換為機器可執行代碼的必要步驟,解決代碼依賴和平臺差異。
  • 編譯型 vs. 解釋型 的選擇取決于需求:追求效率選編譯型(如C),追求靈活和跨平臺選解釋型(如Python),而Java等語言通過中間形式平衡兩者優勢。
    理解這些區別有助于根據項目需求選擇合適的編程語言和開發模式。

其中我們要學習的 編譯 就是上述的一個步驟。
在這里插入圖片描述

其中編譯階段又分為幾個步驟:
在這里插入圖片描述

詞法分析(Lexical Analysis)

詞法分析是編譯的首個階段,此階段的詞法分析器會把C++源代碼當作字符流來處理,接著按照C++詞法規則,將其轉換為一系列有意義的詞法單元(Token)。

  • 關鍵作用
    • 過濾掉注釋和空白字符(像空格、換行符這類)。
    • 識別出標識符(例如變量名、函數名)、關鍵字(像int、if)、字面量(例如123、“hello”)以及運算符(如+、*)。
    • 進行詞法錯誤檢查,比如檢測非法字符、不匹配的引號等問題。
  • C++示例
    對于源代碼int a = 42 + b;,經過詞法分析后會生成如下詞法單元:
    [int] [標識符:a] [=] [字面量:42] [+] [標識符:b] [;]
    

語法分析(Syntax Analysis)

語法分析階段,語法分析器會依據C++的語法規則,把詞法單元構建成抽象語法樹(AST)。

  • 關鍵作用
    • 驗證代碼結構是否符合C++語法規范。
    • 檢測語法錯誤,例如括號不匹配、缺少分號、錯誤的if語句結構等。
    • 為后續的語義分析和代碼生成搭建結構化的表示形式。
  • C++示例
    對于表達式a = 42 + b;,其抽象語法樹可能呈現為:
    AssignmentExpr
    ├─ Left: Identifier(a)
    └─ Right: BinaryOp(+)├─ Left: Literal(42)└─ Right: Identifier(b)
    

語義分析(Semantic Analysis)

語義分析階段會對抽象語法樹進行靜態語義檢查,保證代碼在語義上是合法的。

  • 關鍵作用
    • 類型檢查:保證操作數的類型是兼容的,例如intint相加,而不是int和函數指針相加。
    • 符號表查詢:確認變量和函數在使用之前已經被聲明或定義。
    • 檢測語義錯誤,例如變量未定義、類型不匹配、函數調用參數數量不對等。
  • C++示例
    • 錯誤示例:int a = "hello";(類型不匹配)
    • 正確示例:int a = func(42);(假設func被聲明為返回int類型)

中間代碼生成(Intermediate Code Generation)

該階段會把抽象語法樹轉換為與機器無關的中間表示形式(IR),像三地址碼、LLVM IR等。

  • 關鍵作用
    • 簡化后續的代碼優化和目標代碼生成工作。
    • 支持跨平臺編譯,因為中間代碼可以被翻譯成不同架構的機器碼。
  • C++示例
    對于代碼a = (b + c) * d;,可能生成如下三地址碼:
    t1 = b + c
    t2 = t1 * d
    a = t2
    

代碼優化(Code Optimization)

代碼優化階段會對中間代碼進行轉換,以提升代碼的執行效率,同時不會改變程序的語義。

  • 關鍵作用
    • 常量傳播:例如把x = 5 + 3;優化成x = 8;
    • 死代碼消除:移除不會被執行的代碼,如if (false) { ... }
    • 循環不變代碼外提:將循環內不會改變結果的計算移到循環外面。
    • 強度削弱:把昂貴的運算(如乘法)替換為代價更低的運算(如移位)。
  • C++示例
    原始代碼:
    int a = 10;
    int b = a * 4; // 會被優化成 b = a << 2
    
    優化后的中間代碼:
    a = 10
    b = a << 2  // 用移位替代乘法
    

一些問題:

  1. 高級語言的執行都存在中間代碼生成階段。(?)

解釋:像 Python 這類解釋型語言存在中間代碼生成階段,而直接編譯型語言(如 C 語言)可能直接生成目標代碼。

  1. 中間代碼所生成的依據是語法分析。(?)

解釋:在進行了語法分析和語義分析階段的工作之后,有的編譯程序將源程序變成一種內部表示形式,這種內部表示形式叫做中間語言或中間代碼。

所謂“中間代碼”是一種結構簡單、含義明確的記號系統,這種記號系統可以設計為多種多樣的形式,重要的設計原則為兩點:一是容易生成;二是容易將它翻譯成目標代碼。

  1. 詞法分析中,對變量分析后的輸出是該變量的值和類型。(?)

解釋:詞法分析的輸出是記號(Token),包含類型和屬性值,并非變量的實際值與類型,變量值和類型的確定發生在語義分析階段。

  1. 源程序經詞法分析后得到的中間結果是 (A)
    A. 單詞(token)
    B. 四元式
    C. 語法樹
    D. 語法分析程序

解釋

  • 詞法分析:輸出 Token 序列。
  • 語法分析:依據 Token 序列構建出抽象語法樹(AST)。
  • 中間代碼生成:生成三地址碼或者四元式等中間表示形式。
  • 語法分析程序:屬于編譯程序的一個組件,并非詞法分析的輸出內容。

第一/二章:概述、文法和語言

在這里插入圖片描述

  • 空串,一個字符串的長度為0
  • 空集,一個集合中沒有任何元素(空串也是一個元素)
  • 字符串的乘積,字符串直接拼接在一起
  • 集合的乘積,使用前一個集合中的元素與后一個集合中元素進行拼接。
  • 集合的閉包,有限個集合的乘積。

在這里插入圖片描述


在這里插入圖片描述


文法

分類

  • 0型文法:短語文法
  • 1型文法:上下文有關文法
  • 2型文法:上下文無關文法
  • 3型文法:正規文法

上下文無關文法

上下文無關文法,是一個四元組,包含非終結符號、終結符號、重寫規則集合、識別符,可以理解為由 非終結符定義為非終結符/終結符 產生式組成的文法。

  • 終結符號,只在產生式的右邊出現的符號。
  • 第一條產生式的左部,是識別符。
  • 通常使用大寫字母表示非終結符,小寫字母表示為終結符。(但并不是說,“文法中的小寫字母一定是指終結符”,在文法里,習慣上用小寫字母表示終結符,但這并非強制規定,具體要依據文法的定義來判斷符號類型。)

在這里插入圖片描述

  • 左線性文法和右線性文法,在一個文法中同時只能出現一種,這個文法才是正規文法
    在這里插入圖片描述
    在這里插入圖片描述

相關概念

在這里插入圖片描述
在這里插入圖片描述

所以,句子一定是句型


在這里插入圖片描述

在這里插入圖片描述

  • 子樹:樹根和其向下射出的部分。
  • 簡單子樹:有且只有單層分支的子樹。
  • 子樹的末端結支符號串是相對于子樹根的短語
  • 簡單子樹的末端結點組成的符號串是相對于簡單子樹根的簡單短語/直接短語。(根節點能夠直接推出終結符)
  • 素短語:(在短語中找,至少含有一個終結符,且不含其他更小素短語)
  • 最左簡單子樹的末端結點組成的符號串是句柄。(句柄這個概念只會出現在最右推導/規范推導中才會出現的概念)

一個句型的最左 直接短語 稱為該句型的句柄。

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述
根據文法畫出語法樹,進行推導:
在這里插入圖片描述


在這里插入圖片描述


二義性

在這里插入圖片描述

  • 如果兩種推導方式畫出的樹不同,則說明該文法有二義性。
  • 可能存在兩個不同的最左推導,但是它們對應的語法樹相同。

注意錯誤的說法如下(充分條件和必要條件的區別):

  1. 如果文法是二義的,則最左推導和最右推導必然不同(?)
  2. 如果文法是二義的,則最左推導和最右推導對應的語法樹必定相同。(?)

在這里插入圖片描述
在這里插入圖片描述


二義文法由于無法進行語法分析,沒有存在的必要。(?)

解釋: 二義文法并非無法進行語法分析,而是需要結合消除歧義的規則(如優先級、結合性)來唯一確定語法結構。在編譯實踐中,二義文法常被合理使用,以簡化文法描述并保持分析的正確性,因此具有明確的存在價值。

第三章:詞法分析

右線性文法

在這里插入圖片描述

正規式

在這里插入圖片描述


在這里插入圖片描述

解析: 正規式的本質作用是定義和識別語言集合。當兩個正規式 M 1 M_1 M1? M 2 M_2 M2? 識別的語言集合相等時,即對于任意一個字符串,若 M 1 M_1 M1?能識別(接受該字符串), M 2 M_2 M2? 也能識別,反之亦然,那么就稱這兩個正規式等價 。


在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述
這一步可以先不看,先看后面的“根據正規式得到NFA”。
在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

題型:

  1. 根據正規式畫出NFA圖
  2. 根據NFA圖,使用子集構造法
  3. 根據子集構造法,畫出DFA(新狀態集合中,凡是包含原來NFA終態的,都是新的終態)

參考視頻。

根據正規式得到NFA

參考視頻:【編譯原理根據正規表達式構造NFA,到DFA,以及最后的DFA化簡/最小化】
在這里插入圖片描述

NFA的確定化和最小化

在這里插入圖片描述
先以第(2)問進行講解:
在這里插入圖片描述
在這里插入圖片描述
獲取到確定化后的集合,也可以畫出對應的圖。

在這里插入圖片描述
最小化是對已經確定好的DFA來說的,有這幾個步驟:

  1. 初始化,將集合換分為兩個集合:一個終態集合,一個其他集合
  2. 判斷其他集合是否可區分:可區分就單獨成一個集合。
    在這里插入圖片描述

最終答案:

在這里插入圖片描述

在這里插入圖片描述

具有ε動作的NFA確定化

在這里插入圖片描述
在這里插入圖片描述
這里關于第一行 q 0 q_0 q0?狀態到 q 2 q_2 q2?中,有 S 3 S_3 S3?狀態的解釋:假設a,b,c是各種票,空是免費通過, S 2 S_2 S2?用c票到了 S 2 S_2 S2?,然后走免費通道到了 S 3 S_3 S3?(必須先有一張票,才能走免費通道)
在這里插入圖片描述


在這里插入圖片描述


考察題目

  1. 沒有ε邊的有限自動機一定是DFA。(?)

解釋

  • DFA 要求每個狀態對每個輸入符號必須有且僅有一個確定的轉移。
  • NFA 允許對同一輸入符號存在多個轉移(非確定性)或無轉移,即使沒有ε邊也是如此。
  1. 不確定的有限自動機(NFA)可能存在一個以上的起始狀態。(?)

評分標準:
(1) 正規式得2分,構造NFA得4分(共6分)
(2) 子集構造法:表格4分,DFA 4分,最簡判斷1分(9分)

在這里插入圖片描述
(1)正規式 a ( a ∣ b ) ? b a(a|b)^*b a(ab)?b

這里中間部分 ( a ∣ b ) ? (a|b)^* (ab)?的含義在前面講解過:
在這里插入圖片描述
中間部分的正規式可以表示為(a|b)*,但需要注意,這里中間部分可能為空,即允許字符串長度為2的情況(如ab)。因此,整個正規式可以寫成:a(a|b)*b。這個表達式表示以a開頭,中間有零個或多個a或b,最后以b結尾的所有字符串。

(2)得到NFA:
在這里插入圖片描述

(3)根據子集構造法,得到最簡DFA
ε-CLOSURE{S} = {S}

I ε I_ε Iε? I a I_a Ia? I b I_b Ib?
q 0 q_0 q0?{S}{A, B, C} q 1 q_1 q1??
q 1 q_1 q1?{A, B, C}{B, C} q 2 q_2 q2?{B, C, Z} q 3 q_3 q3?
q 2 q_2 q2?{B, C}{B, C} q 2 q_2 q2?{B, C, Z} q 3 q_3 q3?
q 3 q_3 q3?{B, C, Z}{B, C} q 2 q_2 q2?{B, C, Z} q 3 q_3 q3?
  • 始態: q 0 q_0 q0?
  • 終態: q 3 q_3 q3?

π = { { q 0 q_0 q0? q 1 q_1 q1? q 2 q_2 q2?},{ q 3 q_3 q3?}}

{ q 0 q_0 q0? q 1 q_1 q1? q 2 q_2 q2?}不可區分:
在這里插入圖片描述

第四章:自頂向下語法分析方法

在這里插入圖片描述

在這里插入圖片描述

First和Follow集

求這兩個集合是后續做題的基礎,所以必須會!!!

  • First(A):要找到左邊等于A的產生式,然后看產生式的右部可能出現的終結符。空串也屬于符號集。
  • Follow(A):要找到產生式右部含有A的產生式,然后查看A右邊的情況,找出該非終結符后面所能跟隨的所有終結符:
    • 如果A右邊是空,則將Follow(左部非終結符) 添加到結果集中
    • 否則求出A右邊符號串的First集 - 空串。

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

LL(1)文法

當需要選用自頂向下分析技術時(文法到字符串),必須判別所給文法是否是LL(1)文法。因而對任給文法需首先計算FIRST、FOLLOW、SELECT集合,進而判別文法是否為LL(1)文法。

LL (1) 中第一個 L 表示從左到右掃描輸入串,第二個 L 表示最左推導,1 表示向前看一個終結符。

判斷一個文法是否是LL(1)文法,有兩種方式(在使用這兩個方法之前,還必須要消除文法的左遞歸和回溯):

First集的交集為空集

對于一個非終結符有多個產生式,才需要求出該非終結符的First集。
在這里插入圖片描述
在這里插入圖片描述

select集

選擇符號集:
在這里插入圖片描述

  1. 右部推導不出空串,就是First集
  2. 右部可以推導出空串,就是First集-空串,左部的Follow集。

在這里插入圖片描述
所以說,判斷一個文法是否是LL(1)文法,只需要求出 “一個非終結符號有多于兩個的產生式” 的非終結符的select集。

非LL(1)文法到LL(1)文法的等價變換

以下這兩個步驟,都是在考察LL(1)文法時要進行的第一步操作,類似于:
在這里插入圖片描述

提取左公共因子

在這里插入圖片描述

消除左遞歸

在這里插入圖片描述

在這里插入圖片描述

  1. 與E無關是β,這里是T
  2. 與E相關,出現在右邊的是α

在這里插入圖片描述


在這里插入圖片描述

在這里插入圖片描述

LL(1)分析的實現

表驅動分析程序/LL(1)分析表

  1. 先求出First集,如果一個非終結符能推出 ε ε ε,就需要求出Follow集
  2. 將產生式寫到 是非終結符,其First集為終結符的
    在這里插入圖片描述

在這里插入圖片描述

遞歸向下分析方法

  • 一個非終結符對應一個子程序
  • 根據產生式的右部來設計:
    • 每遇到一個終結符,判斷當前讀入的單詞是否與終結符匹配,如果匹配則繼續讀下一個單詞;如果不匹配則進行錯誤處理。
    • 每遇到一個非終結符,則調用對應的子程序

在這里插入圖片描述
在這里插入圖片描述

分析過程

在這里插入圖片描述

在這里插入圖片描述


考察題目

評分標準:文法5+集合10+分析表3+分析過程2=20

在這里插入圖片描述

(1)消除左遞歸和左公因子后的文法:

  • A → a A ′ A→a A' AaA
  • A ′ → A B c ∣ ε A'→ABc|ε AABcε
  • B → d B ′ B→dB' BdB
  • B ′ → b B ′ ∣ ε B'→bB'|ε BbBε
    在這里插入圖片描述

(2)改造后的文法是LL(1)文法。預測分析表如下:

非終結符abcd#
A A → a A ′ A→a A' AaA
A’ A ′ → A B c A'→ABc AABc A ′ → ε A'→ε Aε A ′ → ε A'→ε Aε
B B → d B ′ B→dB' BdB
B’ B ′ → b B ′ B'→bB' BbB B ′ → ε B'→ε Bε

(3)輸入串 ( aadc# ) 的分析過程:

步驟分析棧剩余輸入串動作
1#Aa a d c # A → a A ′ A→a A' AaA
2#A’aa a d c #匹配a
3#A’a d c # A ′ → A B c A'→ABc AABc
4#cBAa d c # A → a A ′ A→a A' AaA
5#cBA’aa d c #匹配a
6#cBA’d c # A ′ → ε A'→ε Aε
7#cBd c # B → d B ′ B→dB' BdB
8#cB’dd c #匹配d
9#cB’c # B ′ → ε B'→ε Bε
10#cc #匹配c
11##匹配#,接受

輸入串 ( aadc# ) 被成功分析。

第六章:LR分析

在這里插入圖片描述

LR(0)項集規范族構造過程

  1. 增廣文法的變換:開始符號有多個產生式,需要對開始符號進行增廣文法的變換,使新的開始符號只有一個產生式。
  2. 列表的形式給出:狀態、項目集、后繼符號、后繼狀態
  3. 一個狀態的項目集,就是在產生式右部寫一個點,如果點后面(后繼符號)是非終結符,則需要在項目集中添加該非終結符的產生式(右部也需要帶點)

在這里插入圖片描述
4. 還需要求 S 0 S_0 S0?的項集中每一個式子的閉包,就是把點向后移動一個,如果點后面是非終結符,就進行上面的步驟;如果是終結符/空,就結束。
5. 如果是空,其后繼符號就是把項目集抄一下,然后在前面加上一個#
6. 如果是終結符,其后繼符號就是終結符

在這里插入圖片描述
在這里插入圖片描述

LR(0)文法

在這里插入圖片描述

  • 如果 I i I_i Ii?里同時有歸約項目和移進項目,就是移進-歸約沖突
  • 看一個狀態 I i I_i Ii?里面,是不是只存在一個歸約項目,如果狀態里有兩個歸約項目,京就是歸約-歸約沖突
  • 比如 I i I_i Ii?明明是歸約狀態卻又伸出來個箭頭指向其他的狀態就說明沖突了

在這里插入圖片描述
在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述

在這里插入圖片描述

分析表和分析過程

在這里插入圖片描述


在這里插入圖片描述
在這里插入圖片描述

  1. 遇到 r i r_i ri?時,使用第 i 個歸約式進行出棧歸約,并且GOTO[狀態棧頂狀態, 非終結符],如GOTO[5, B] = 9
  2. 將 GOTO[狀態棧頂狀態, 非終結符] 放到狀態棧中,非終結符放到符號棧中。
  3. 直到 棧頂狀態,輸入串 = acc,結束

SLR(1)分析

判定

沖突項目集的簡單向前看1集合的交集為空集,則是SLR(1)語法:

  • 歸約-移進沖突:歸約項的FOLLOW集,與移進項的終結符的交集。
  • 歸約-歸約沖突:求兩者FOLLOW集的交集

在這里插入圖片描述

分析表

與LR(0)分析表不同的是,對于歸約項不要將一行全使用 r i r_i ri?進行填寫,而只是在FOLLOW(A)集合所在列填寫。
在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

分析過程

在這里插入圖片描述

LR(1)文法

在這里插入圖片描述

  • 后繼狀態的向前搜索符,就是前一個狀態的向前搜索符。
  • 當前集合的擴展閉包的向前搜索符,連接字符串的First集

沖突如何解決?

  • 歸約-歸約沖突,向前搜索符不相交,就可以解決沖突
  • 歸約-移進沖突,歸約項看向前搜索符,移進項還是看點后面的終結符。

表格:

  1. 歸約項的列,由向前搜索符決定。寫成 r i r_i ri?
  2. 移進項的列,由點后面的終結符決定

LR1會使同心集分裂,所以它的狀態數(項目集數)是最多的。

LALR(1)分析

  1. 拓廣文法
  2. 合并同心集:產生式相同,合并向前搜索符
  3. 重新構造表
    在這里插入圖片描述

如何區分LR文法

【11編譯原理如何區別LR(0),SLR(1),LR(1),LALR(1)文法】

逆波蘭表達式

找主運算符的原則:

  1. 括號內的表達式要先看作一個整體;
  2. 運算符優先級越低,也是主運算符;
  3. 在逆波蘭表達式中越是右邊的,越是主運算符

在這里插入圖片描述
對于這個中綴表達式:

  1. 先將括號內部的表達式看作一個整體: E 1 = ( B ? D ? C / A ) E_1 = (B*D-C/A) E1?=(B?D?C/A),表達式變為 A ? E 1 + B A*E_1+B A?E1?+B
  2. 對于 A ? E 1 + B A*E_1+B A?E1?+B表達式,比較*和+的優先級,+的優先級較低,作為主運算符,寫在逆波蘭表達式的最后: ( A ? E 1 ) B + (A*E_1)B+ (A?E1?)B+

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/906125.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/906125.shtml
英文地址,請注明出處:http://en.pswp.cn/news/906125.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【DeepSeek論文精讀】11. 洞察 DeepSeek-V3:擴展挑戰和對 AI 架構硬件的思考

歡迎關注[【AIGC論文精讀】](https://blog.csdn.net/youcans/category_12321605.html&#xff09;原創作品 【DeepSeek論文精讀】1. 從 DeepSeek LLM 到 DeepSeek R1 【DeepSeek論文精讀】7. DeepSeek 的發展歷程與關鍵技術 【DeepSeek論文精讀】11. 洞察 DeepSeek-V3&#xff…

寶塔面板部署前后端項目SpringBoot+Vue2

這篇博客主要用來記錄寶塔部署前端后端項目的過程。因為寶塔部署有點麻煩&#xff0c;至少在我看來挺麻煩的。我還是喜歡原始的ssh連接服務器進行操作。但是公司有項目用到了寶塔&#xff0c;沒辦法啊&#xff0c;只能摸索記錄一下。 我們需要提前準備好后端項目的jar包和前端項…

電機試驗平臺:創新科技推動電動機研究發展

電機試驗平臺是電機制造和研發過程中不可或缺的重要設備&#xff0c;其功能涵蓋了電機性能測試、電機壽命測試、電機質量評估等多個方面。隨著科技的不斷發展和電機應用領域的日益擴大&#xff0c;對電機試驗平臺的要求也越來越高。本文將從現代化電機試驗平臺的設計與應用兩個…

LangGraph 7 - Platform - Agentic RAG、監督、SQL代理、追蹤、私密對話、認證、RemoteGraph、LangSmith

文章目錄 代理式檢索增強生成&#xff08;Agentic RAG&#xff09;安裝 1、預處理文檔2、創建檢索器工具3、生成查詢4、文檔分級5、問題重寫6、生成答案7、構建流程圖8、運行智能RAG代理 多智能體監督系統安裝配置1、創建工作代理研究代理數學代理工具 2、使用 langgraph-super…

生命之樹--樹形dp

1.樹形dp--在dfs遍歷樹的同時dp&#xff0c;從上到下遞歸&#xff0c;到葉子是邊界條件 https://www.luogu.com.cn/problem/P8625 #include<bits/stdc.h> using namespace std; #define N 100011 typedef long long ll; typedef pair<ll,int> pii; int n,c; ll …

10.8 LangChain三大模塊深度實戰:從模型交互到企業級Agent工具鏈全解析

LangChain Community 項目:Model I/O, Retrieval, Agent Tooling 關鍵詞:LangChain Model I/O, 檢索增強生成, Agent 工具鏈, 多路召回策略, 工具調用協議 1. Model I/O 模塊:大模型交互標準化接口 Model I/O 是 LangChain 生態中連接大模型的核心模塊,定義了統一的輸入輸…

鴻蒙OSUniApp 實現圖片上傳與壓縮功能#三方框架 #Uniapp

UniApp 實現圖片上傳與壓縮功能 前言 在移動應用開發中&#xff0c;圖片上傳是一個非常常見的需求。無論是用戶頭像、朋友圈圖片還是商品圖片&#xff0c;都需要上傳到服務器。但移動設備拍攝的圖片往往尺寸較大&#xff0c;直接上傳會導致流量消耗過大、上傳時間過長&#x…

已經裝了pygame但pycharm顯示沒有該模塊/軟件包無法加載出來下載pygame

首先&#xff0c;如果你已經通過pip install pygame或者其他什么命令下載好了pygame &#xff08;可以通過pip list查看&#xff0c;有pygame說明pygame已經成功安裝在當前python環境中&#xff09;。然而&#xff0c;如果你在 PyCharm 中仍然看不到 pygame&#xff0c;可能是因…

第6章 實戰案例:基于 STEVAL-IDB011V1 板級 CI/CD 全流程

在前五章中,我們完成了嵌入式 CI/CD 從環境搭建、編譯自動化、測試自動化、發布分發到監控回歸的全技術鏈條。本章將以 STEVAL-IDB011V1(搭載 BlueNRG-355)評估板為實戰載體,手把手演示如何在 GitLab CI(或 Jenkins)上,構建一條從 Git Push → 編譯 → 測試 → 刷寫 → …

系統架構設計(十四):解釋器風格

概念 解釋器風格是一種將程序的每個語句逐條讀取并解釋執行的體系結構風格。程序在運行時不會先被編譯為機器碼&#xff0c;而是動態地由解釋器分析并執行其語義。 典型應用&#xff1a;Python 解釋器、JavaScript 引擎、Bash Shell、SQL 引擎。 組成結構 解釋器風格系統的…

1-機器學習的基本概念

文章目錄 一、機器學習的步驟Step1 - Function with unknownStep2 - Define Loss from Training DataStep3 - Optimization 二、機器學習的改進Q1 - 線性模型有一些缺點Q2 - 重新詮釋機器學習的三步Q3 - 機器學習的擴展Q4 - 過擬合問題&#xff08;Overfitting&#xff09; 一、…

SQL里where條件的順序影響索引使用嗎?

大家好&#xff0c;我是鋒哥。今天分享關于【SQL里where條件的順序影響索引使用嗎&#xff1f;】面試題。希望對大家有幫助&#xff1b; SQL里where條件的順序影響索引使用嗎&#xff1f; 1000道 互聯網大廠Java工程師 精選面試題-Java資源分享網 在 SQL 查詢中&#xff0c;W…

計算機科技筆記: 容錯計算機設計05 n模冗余系統 TMR 三模冗余系統

NMR&#xff08;N-Modular Redundancy&#xff0c;N 模冗余&#xff09;是一種通用的容錯設計架構&#xff0c;通過引入 N 個冗余模塊&#xff08;N ≥ 3 且為奇數&#xff09;&#xff0c;并采用多數投票機制&#xff0c;來提升系統的容錯能力與可靠性。單個模塊如果可靠性小于…

中級網絡工程師知識點7

1.存儲區城網絡SAN可分為IP-SAN,FC-SAN兩種&#xff0c;從部署成本和傳輸效率兩個方面比較兩種SAN&#xff0c;比較結果為FCSAN部署成本更高 2.RAID2.0技術的優勢&#xff1a; &#xff08;1&#xff09;自動負載均衡&#xff0c;降低了存儲系統故障率 &#xff08;2&#x…

在Ubuntu24.04中配置開源直線特征提取軟件DeepLSD

在Ubuntu24.04中配置開源直線特征提取軟件DeepLSD 本文提供在Ubuntu24.04中配置開源直線特征提取軟件DeepLSD的基礎環境配置、列出需要修改的文件內容&#xff0c;以及報錯解決方案集錦。 基礎的編譯安裝環境 python3.8.12CUDA12gcc/g 9.5&#xff08;系統自帶的g-13版本太新…

Nginx+Lua 實戰避坑:從模塊加載失敗到版本沖突的深度剖析

Nginx 集成 Lua (通常通過 ngx_http_lua_module 或 OpenResty) 為我們提供了在 Web 服務器層面實現動態邏輯的強大能力。然而,在享受其高性能和靈活性的同時,配置和使用過程中也常常會遇到各種令人頭疼的問題。本文將結合實際案例,深入分析在 Nginx+Lua 環境中常見的技術問題…

Vue.js組件開發進階

Vue.js 是一個漸進式 JavaScript 框架&#xff0c;廣泛用于構建用戶界面。組件是 Vue.js 的核心概念之一&#xff0c;允許開發者將 UI 拆分為獨立、可復用的模塊。本文將深入探討 Vue.js 組件的開發&#xff0c;涵蓋從基礎到高級的各個方面。 組件的基本概念 在 Vue.js 中&am…

藍橋杯19682 完全背包

問題描述 有 N 件物品和一個體積為 M 的背包。第 i 個物品的體積為 vi?&#xff0c;價值為 wi?。每件物品可以使用無限次。 請問可以通過什么樣的方式選擇物品&#xff0c;使得物品總體積不超過 M 的情況下總價值最大&#xff0c;輸出這個最大價值即可。 輸入格式 第一行…

深度學習之用CelebA_Spoof數據集搭建一個活體檢測-一些模型訓練中的改動帶來的改善

實驗背景 在前面的深度學習之用CelebA_Spoof數據集搭建一個活體檢測-模型搭建和訓練&#xff0c;我們基于CelebA_Spoof數據集構建了一個用SqueezeNe框架進行訓練的活體2D模型&#xff0c;采用了蒸餾法進行了一些簡單的工作。在前面提供的訓練參數中&#xff0c;主要用了以下幾…

2025年PMP 學習二十 第13章 項目相關方管理

第13章 項目相關方管理 序號過程過程組過程組1識別相關方啟動2規劃相關方管理規劃3管理相關方參與與執行4監控相關方參與與監控 相關方管理&#xff0c;針對于團隊之外的相關方的&#xff0c;核心目標是讓對方為了支持項目&#xff0c;以達到項目目標。 文章目錄 第13章 項目相…