編譯原理 學習 2025年6月10日11:17:54

編譯原理

將高級編程語言編寫的源代碼轉換成機器可執行的代碼(二進制或匯編代碼)

核心任務:

詞法分析(正則表達式和有限自動機):
示例Token分類:關鍵字:if, while
運算符:+, =
標識符:變量名

? ? ? ? ? ? ? ? 分解源代碼為單詞 識別 其中關鍵字 變量名 運算符

語法分析(上下文無關文法CFG):
示例CFG規則:
E → E + T | T
T → T * F | F
F → (E) | id

? ? ? ? ? ? ? ? ? ? ? 根據語法規則 構建抽象語法樹(AST) 檢查程序結構 是否正確??

語義分析(語法制導翻譯):

驗證類型匹配,變量聲明等語義規則

代碼優化(數據流分析):

刪除冗余代碼、循環優化等技術提升程序性能。

目標代碼生成:

優化過后轉換成二進制或者匯編

應用場景:

編譯器開發(GCC.LLVM等工具鏈實現)

靜態分析工具(檢測代碼風格和漏洞 如:ESLint)

領域特定語言(DSL快速構建小型語言的處理工具)

使用現有的工具和庫(如:Lex/Yacc/Bison/Flex)實踐編譯器開發

Windows環境安裝工具flex bison

CMD管理員輸入以下代碼

choco install winflexbison3

當出現

Do you want to run the script?([Y]es/[A]ll - yes to all/[N]o/[P]rint):

回復A 運行所有腳本

如果遇到運行問題可把以下地址添加到PATH(環境變量))默認路徑為?C:\Program Files (x86)\WinFlexBison 主要下圖信息輸出 比如說我的電腦 安裝位置就為

C:\ProgramData\chocolatey\lib\winflexbison3\tools

檢測是否安裝成功

win_flex --version
win_bison --version

實戰項目AI:實現一個簡單的計算器(支持加減乘除)

編寫?calc.l(Flex 文件)

%{
#include "y.tab.h"  // 包含 Yacc/Bison 生成的頭文件,用于 token 類型定義// 文件名可能是 y.tab.h 或 calc.tab.h,取決于 Yacc/Bison 文件配置
%}
%option noyywrap  // 禁用 yywrap 函數,簡化 Lex 程序
%%
// 模式匹配規則部分
[0-9]+      { yylval = atoi(yytext); return NUMBER; }  // 匹配數字并轉換為整數
"+"         { return ADD; }  // 匹配加號運算符
"-"         { return SUB; }  // 匹配減號運算符
"*"         { return MUL; }  // 匹配乘號運算符
"/"         { return DIV; }  // 匹配除號運算符
"("         { return LPAREN; }  // 匹配左括號
")"         { return RPAREN; }  // 匹配右括號
[ \t\n]     ; // 忽略空格、制表符和換行符
.           { printf("未知字符: %s\n", yytext); }  // 處理其他未定義字符
%%
// 用戶代碼部分(此處為空)

編寫?calc.y(Bison 文件)

%{
#include <stdio.h>
#include <stdlib.h>
extern int yylex();      // 聲明詞法分析器函數
extern FILE *yyin;       // 輸入文件指針
void yyerror(const char *msg) {   // 錯誤處理函數
fprintf(stderr, "Error: %s\n", msg);
}
%}
%token ADD SUB MUL DIV LPAREN RPAREN  NUMBER  // 定義token類型
%left '+' '-'     // 定義運算符優先級和結合性
%left '*' '/'     // 乘法除法優先級高于加減法
%%
input:            // 輸入規則
/* 空輸入 */
| input line  // 多行輸入處理
;
line:             // 行處理規則
'\n'          // 空行
| expr '\n' { printf("= %d\n", $1); }  // 表達式行,輸出計算結果;
expr:             // 表達式規則
NUMBER            { $$ = $1; }  // 數字直接返回
| expr '+' expr   { $$ = $1 + $3; }  // 加法運算
| expr '-' expr   { $$ = $1 - $3; }  // 減法運算
| expr '*' expr   { $$ = $1 * $3; }  // 乘法運算
| expr '/' expr   { if ($3 == 0) yyerror("Division by zero"); else $$ = $1 / $3; }  // 除法運算,檢查除零錯誤
| '(' expr ')'    { $$ = $2; }  // 括號表達式
;
%%
主程序部分
int main(int argc, char **argv) {
if (argc > 1) {          // 如果有命令行參數
yyin = fopen(argv[1], "r");  // 打開文件作為輸入
} else {
yyin = stdin;        // 否則使用標準輸入
}// 啟用 Bison 調試模式yydebug = 1;yyparse();               // 調用語法分析器
return 0;}

Windows安裝的工具需要在原代碼調用的前提上添加 win_ 這樣才會識別

下圖是因為編譯時被安全軟件攔截生成的提示?

1.生成?.c?文件

//修改前  以下代碼 Windows 環境不會識別
flex calc.l         # 生成 calc.yy.c
bison -dy calc.y    # 生成 calc.tab.c 和 calc.tab.h
//修改后 正常生成,如果出現還是不識別 返回文章前面尋找路徑添加到 環境變量
win_flex calc.l
win_bison -dy calc.y
  • yylex():由詞法分析器提供,負責返回詞法單元。
  • yyerror():用戶需實現的錯誤處理函數
  • yylval/yylloc:用于傳遞詞法單元的屬性和位置信息。
  • yyparse()?是由語法分析器生成工具(如 Bison 或 Yacc)自動生成的函數,用于執行語法分析過程。它通常與詞法分析器(如 Lex 或 Flex 生成的?yylex())配合使用,構成編譯器或解釋器的核心部分。

可以看到生成了三個文件

  • lex.yy.c(由 Flex 生成)
  • y.tab.c(由 Bison 生成)
  • y.tab.h(定義 token)

?

?2.編譯鏈接?

gcc lex.yy.c y.tab.c -o calc   //正常鏈接gcc lex.yy.c y.tab.c -DYYDEBUG=1 -o calc  //打開調試開關的鏈接
//lex.yy.c:由Lex(或Flex)生成的詞法分析器源代碼,負責將輸入字符流分解為標記(tokens)。
//y.tab.c:由Yacc(或Bison)生成的語法分析器源代碼,包含語法規則和語義動作,通常依賴詞法分析器的輸出。

可以看到生成了一個exe程序

?

?點擊運行并輸入算式:

Starting parse       // 開始語法分析(調用 yyparse())
Entering state 0     // 進入狀態 0(初始狀態)
Stack now 0          // 當前狀態棧:[0]Reducing stack by rule 1 (line 15):   // 根據規則 1 歸約(對應 input 規則)-> $$ = nterm input ()             // 將 input 規約為一個非終結符(空輸入)Entering state 1     // 狀態變為 1
Stack now 0 1        // 狀態棧更新為 [0, 1]Reading a token      // 開始讀取第一個 token
5 + 3                // 用戶輸入內容(注意這行是你手動或從文件輸入的內容)Next token is token NUMBER ()        // 下一個 token 是 NUMBER(數字 5)
Shifting token NUMBER ()             // 將該 token 移入棧中
Entering state 3                     // 進入狀態 3
Stack now 0 1 3                      // 狀態棧變為 [0, 1, 3]Reducing stack by rule 5 (line 23):  // 根據規則 5 歸約(exp: NUMBER)$1 = token NUMBER ()              // 使用 NUMBER 值(即 5)構造 exp-> $$ = nterm exp ()              // 將 NUMBER 歸約為 exp(表達式)Entering state 7                     // 進入狀態 7
Stack now 0 1 7                      // 狀態棧變為 [0, 1, 7]Reading a token      // 繼續讀取下一個 tokenNext token is token '+' ()           // 下一個 token 是 '+'(加號)
Shifting token '+' ()                // 將 '+' 移入棧中
Entering state 9                     // 進入狀態 9
Stack now 0 1 7 9                    // 狀態棧變為 [0, 1, 7, 9]Reading a token      // 繼續讀取下一個 tokenNext token is token NUMBER ()  
// 下一個讀取到的 token 是 NUMBER(即數字 "3")Shifting token NUMBER ()
// 將這個 token(數字 3)移入解析棧中Entering state 3
// 當前狀態變為 3(通常是處理 NUMBER 的狀態)Stack now 0 1 7 9 3  
// 當前解析棧的狀態序列:[0, 1, 7, 9, 3]
// 表示當前處于狀態 3,前面是狀態 0 → 1 → 7 → 9 → 3Reducing stack by rule 5 (line 23):  
// 根據語法規則第 5 條進行歸約(對應 exp: NUMBER)$1 = token NUMBER ()  
// 使用當前 token 的值(即 3)作為規則中的第一個操作數-> $$ = nterm exp ()  
// 將 NUMBER 歸約為非終結符 exp(表達式)
// 即:把數字 3 看作是一個“表達式”expEntering state 15  
// 歸約完成后進入新狀態 15(通常是由 exp '+' exp 后匹配到新的 exp)Stack now 0 1 7 9 15  
// 當前狀態棧更新為 [0, 1, 7, 9, 15]Reading a token  
// 準備讀取下一個 token(輸入結束或換行)

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

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

相關文章

風中低語:Linux 信號處理的藝術與實踐

文章目錄 &#x1f307;前言&#x1f3d9;?正文1、信號的處理時機1.1、處理情況1.2、“合適” 的時機 2、用戶態與內核態2.1、概念2.2、重談進程地址空間2.3、信號的處理過程 3、信號的捕捉3.1、內核如何實現信號的捕捉&#xff1f;3.2、sigaction 4、信號部分小結 補充 5、可…

ASP.NET Core SignalR - 部分客戶端消息發送

文章目錄 前言一、消息發送的核心概念1.客戶端標識2.消息接收范圍 二、向特定用戶發送消息管理員向指定用戶發送私信&#xff0c;或用戶之間一對一聊天。 三、向組發送消息聊天室、工作群組、通知訂閱等。 四、廣播消息系統公告、實時統計數據更新等。 五、向角色發送消息向管理…

前后端交互過程中—各類文件/圖片的上傳、下載、顯示轉換

前后端交互過程中—各類文件/圖片的上傳、下載、顯示轉換 圖片上傳下載常用函數&#xff1a;new Blob()**blobParts&#xff1a;&#xff08;必傳&#xff09;****options&#xff1a;&#xff08;可選&#xff09;**blob的常見的MIME類型&#xff1a; URL.createObjectURL()替…

校園二手交易平臺(微信小程序版)

文章目錄 1. 項目概述2. 項目功能思維導圖3. 技術架構1. 前端技術棧2. 后端技術棧 4. 核心模塊實現5. 總結6. 項目實現效果截圖7. 關于作者其它項目視頻教程介紹 1. 項目概述 校園二手交易平臺微信小程序旨在為在校學生提供一個便捷的二手物品交易渠道&#xff0c;包含用戶模塊…

Linux簡單的操作

ls ls 查看當前目錄 ll 查看詳細內容 ls -a 查看所有的內容 ls --help 查看方法文檔 pwd pwd 查看當前路徑 cd cd 轉路徑 cd .. 轉上一級路徑 cd 名 轉換路徑 …

【芯片設計- RTL 數字邏輯設計入門 4.2 -- 組合邏輯賦值 + 時序邏輯狀態保持】

文章目錄 Overview原語句分析變量含義假設(根據命名推測)狀態更新邏輯詳解狀態轉移邏輯舉個實際例子小結Overview 本文將詳細介紹 verilog rtl 中 assign reg_halt_mode_nx = halt_taken | (reg_halt_mode & ~halt_return);的作用,以及這里為何要使用 reg_halt_mode,…

【單片機期末】匯編試卷

一、選擇題 DPTR是16位的&#xff0c;所以尋址范圍是64KB R1是8位的&#xff0c;只能尋址256 訪問內部ROM只能用MOVC指令 一個指令周期是時鐘周期的1/12 12個時鐘周期是一個機器周期 單指令周期是指一個機器周期 T 1 / f 12MHz ~ 1us 13位計數16位計數8位自動重裝載雙8位計數器…

校驗枚舉類類型的入參合法性的統一方案

文章目錄 背景解決實踐定義枚舉類 InEnum注解定義驗證邏輯 InEnumValidator 實際使用 背景 業務要做電商平臺做入參, 在電商平臺被抽離成枚舉類的情況下 &#xff0c;要怎么驗證輸入的參數是正確的呢? 解決 Constraint 實現自定義驗證邏輯 Constraint 注解用于標注其他注解&am…

Unity-NavMesh詳解-其一

今天我們來詳細地探究一下Unity的NavMesh這一性能強大的組件&#xff1a; NavMesh基本使用 NavMesh簡單地說本質上是一個自動尋路的AI組件&#xff0c;我們首先來學習基本的使用。 畫面中我已經添加好了地面&#xff0c;目標&#xff0c;障礙物以及玩家四個要素。 注意我們要…

vue的created和mounted區別

在Vue.js中&#xff0c;created和mounted的核心區別在于調用時機和DOM可訪問性?&#xff1a;created鉤子在組件實例創建后、DOM掛載前調用&#xff0c;適用于數據初始化&#xff1b;mounted鉤子在DOM掛載后調用&#xff0c;支持DOM操作。?? ?調用時機與核心能力對比? ?…

MySQL 8.0 OCP 英文題庫解析(十四)

Oracle 為慶祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免費考取原價245美元的MySQL OCP 認證。 從今天開始&#xff0c;將英文題庫免費公布出來&#xff0c;并進行解析&#xff0c;幫助大家在一個月之內輕松通過OCP認證。 本期公布試題121~130 試題1…

【HarmonyOS 5】拍攝美化開發實踐介紹以及詳細案例

以下是 HarmonyOS 5 拍攝美化功能的簡潔介紹&#xff0c;整合核心能力與技術亮點&#xff1a; 一、AI 影像創新 ?AI 魔法移圖? 系統級圖像分層技術實現人物/物體自由拖拽、縮放與復制&#xff0c;突破傳統構圖限制。自動分離主體與背景&#xff0c;一鍵生成錯位創意照&…

【Java多線程從青銅到王者】懶漢模式的優化(九)

懶漢模式的問題 我們看上述的代碼&#xff0c;當第一次調用getIntance的時候&#xff0c;intance為null&#xff0c;就會進入if里面&#xff0c;創建出實例&#xff0c;當不是第一次調用的時候&#xff0c;此時的intandce不是null&#xff0c;不進入循環&#xff0c;直接return…

SCI期刊查重參考文獻會被查重嗎?

查重的時候&#xff0c;參考文獻不會被查重。 不管中文還是英文查重系統里一般都有排除參考文獻的設置。 比如英文查重系統iThenticate 的排除文獻的設置如下&#xff1a; 在iThenticate在線報告界面的右下角點擊“漏斗”圖標&#xff08;Filter&#xff09;&#xff0c; ?…

OpenLayers 獲取地圖狀態

注&#xff1a;當前使用的是 ol 5.3.0 版本&#xff0c;天地圖使用的key請到天地圖官網申請&#xff0c;并替換為自己的key 地圖狀態信息包括中心點、當前縮放級別、比例尺以及當前鼠標移動位置信息等&#xff0c;在WebGIS開發中&#xff0c;地圖狀態可以方便快捷的向用戶展示基…

JxBrowser 8.8.0 版本發布啦!

一次調用即可下載文件精準清除瀏覽數據右鍵點擊位置檢測獲取元素在視口中的位置 &#x1f517; 點擊此處了解更多詳情。 &#x1f193; 獲取 30 天免費試用。

React 中的TypeScript開發范式

在 TypeScript 中使用 React 可以提高代碼的可維護性、可讀性和可靠性。TypeScript 提供了靜態類型檢查和豐富的類型系統&#xff0c;這些功能在 React 開發中非常有用。下面詳細介紹如何在 React 項目中使用 TypeScript&#xff0c;并結合泛型和 infer 來定義類型。 1. 項目初…

72道Nginx高頻題整理(附答案背誦版)

1. 簡述什么是Nginx &#xff1f; Nginx 是一個開源的高性能HTTP和反向代理服務器&#xff0c;也能夠用作IMAP/POP3/SMTP代理服務器。它最初由Igor Sysoev為俄羅斯的一個大型網站Rambler開發&#xff0c;并在2004年首次公開發布。Nginx被設計用來解決C10k問題&#xff0c;即同…

AI時代,數據分析師如何成為不可替代的個體

在數據爆炸的 AI 時代&#xff0c;AI工具正以驚人的速度重塑數據分析行業&#xff0c;數據分析師的工作方式正在經歷一場前所未有的變革。數據分析師又該如何破局&#xff0c;讓自己不被AI取代呢&#xff1f; 一、AI工具對重復性工作的徹底解構 如以往我們需要花幾天寫一份數…

DockerHub與私有鏡像倉庫在容器化中的應用與管理

哈嘍&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的應用與管理 Docker Hub的基本概念與使用方法 Docker Hub是Docker官方提供的一個公共鏡像倉庫&#xff0c;用戶可以在其中找到各種操作系統、軟件和應用的鏡像。開發者可以通過Docker Hub輕松獲取所…