2017春季學期編譯原理期末實驗報告

NO IMAGE

實驗名:PL/0編譯器的實現
一、實驗目的
理解編譯器的工作機制,掌握編譯器的構造方法
掌握詞法分析器的生成工具LEX的用法
掌握語法分析器的生成工具YACC的用法

二、實驗內容簡要概括
1.實驗分為三個部分:
分別是詞法分析、語法分析、語義分析和代碼生成部分
三個部分對應PL/0編譯程序的編譯過程,使得在學習原理的過程中可以更好的體會到分析過程。

2.詞法分析
   編寫PL/0語言識別程序,並藉助flex工具生成一個PL/0語言的詞法分析程序,對輸入的PL/0語言的源程序進行掃描,識別出單詞符號的類別,輸出各種符號的信息。

參考LEX源程序的格式,自定義聲明,輔助定義,識別規則和子程序。

3.語法分析
編寫一個PL/0語言的語法分析程序,藉助bison工具生成,使得程序可以對輸入的PL/0源程序進行語法分析,並按語法歸約過程輸出歸約時所用的語法規則。

4.語義分析
使用C語言編寫PL/0的語義分析程序,要求將其轉換成一個類pcode語言

三、實驗環境:
OS:Windows10 1607
Compiler:Cygwin64 Terminal,yacc,lex,bison, code:blocks:13.12

輔助:sublime text 3126, notepad++ 7.41
使用語言:C

四、實驗設計說明
1.第一部分:詞法分析

實驗具體輸入輸出要求如下

輸入:PL0源程序

輸出:將單詞符號分為下面五類,然後統計PL0源程序中各單詞符號出現的次數

K類(關鍵字)I類(標識符)C類(常量)P類(算符及界符)O類(其他)

根據要求,再參考lex的語法格式,設計思路大致如下:

1)對五類關鍵詞分別建立結構體,類似於Hash的鏈表法一樣,一個關鍵詞中對應一個數組,將每一個讀入的,相同類型但是不同內容的符號插在對應類別的結構體後面。結構體設計如圖。

2017春季學期編譯原理期末實驗報告

2)輔助定義環節添加關鍵詞信息與對應的語義動作insert

  1. 對讀進來的PL/0文件進行分析,將結果輸出到另外一個文件中

該部分的最大難度在於語義動作insert

本次實驗對輸入的字符串有長度限制,需要在分析語言的過程中給予警告,但同時也不能終止編譯動作,因為如果每次編譯報錯,只能報一行錯誤,會使得編譯器的分析效率十分低下。本次實驗中insert動作對應的函數如下:

2017春季學期編譯原理期末實驗報告

2.第二部分:語法分析
實驗具體輸入輸出要求如下

輸入:PL0源程序

輸出:關於該程序的語法結構分析說明

參考bison的說明,大致明白這次實驗是在詞法分析的基礎之上多加了對於語法規則的定義,其中定義的語句要符合C語言文法。

語法格式:左部(非終結符):右部(文法符號串);

非終結符名稱通常用小寫字母,終結符名稱通常用大寫字母。

右部為空表示左部的非終結符可以匹配空串。

左部相同的語法規則應儘量合併。

語義動作出現在規則的尾部時,bison在歸約前執行它;語義動作出現在規則的中間時,bison在識別出它前面的若干文法符號後執行它。

實現思路參考詞法分析實驗,只是這次在對應的語義動作環節直接輸出,而不需要insert到結構體中。

實驗輸出如下:

2017春季學期編譯原理期末實驗報告

3.第三部分:語義分析和目標語言的生成

實驗具體輸入輸出要求如下

輸入:PL0源程序

輸出:類Pcode代碼

首先需要對類Pcode進行了解

目標代碼類pcode是一種棧式機的彙編語言。

棧式機系統結構:沒有累加器和寄存器,只有存儲棧指針所有運算都在棧頂

指令格式fla

f  功能碼

l  層次差
(標識符引用層減去定義層)

a  根據不同的指令有所區別

參考類Pcode的功能表和解釋器結構,將程序分成三個部分:code.l,code.y和define.h。其中define.h定義了類Pcode的功能碼代號,符號表和指令結構,code.l屬於詞法分析部分,code.y屬於語法與語義分析部分。其中在語義動作說明部分,根據輸入情況不同用$偽變量進行壓棧出棧操作。

本次實驗中已經提供了interpret函數,所以省略了C語言中對於功能碼的具體情況說明,接下來的思路就是根據輸入的程序,先檢查詞法有無錯誤—>構建符號表–>執行interpret()的內容à輸出類Pcode結果

實驗結果圖在第五部分

五、以一個*PL0*的源程序作具體說明

原PL0程序如下:

var a, b, c;
procedure gcd;
procedure rec;
begin
    if a <> 0 then
        begin
            a := a - 1;
        end;
end;
begin
    if c < b then
        begin
            c := b;
            call rec;
        end;
end;
begin
    read(a);
    read(b);
    read(c);
    write(a);
    call gcd;
    write(a);
end.

這個程序裡面存在著過程嵌套,其實這一次實驗中還實現了並列,但是在此就不贅述了。
實驗輸出結果如圖

2017春季學期編譯原理期末實驗報告

(注:在寫報告的過程中才發現之前看錯ppt說明的指令功能表,誤將INT看成INI,但為了閱讀的方便,所以此處不再做修改)

2017春季學期編譯原理期末實驗報告

2017春季學期編譯原理期末實驗報告

2017春季學期編譯原理期末實驗報告

相關文章

計算機網絡實驗課結課考試:子網劃分

Win10安裝TensorFlow步驟及問題

計算機網絡大作業:基於WIFI信號強度的主被動定位

計算機網絡實驗七:交換帶寬與端口密度