?? pl-0語(yǔ)言編譯程序分析.htm
字號(hào):
if ch = '>' then (* 如果讀到大于號(hào),處理過(guò)程類似于處理小于號(hào) *)
begin
getch; (* 再讀一個(gè)字符 *)
if ch = '=' then (* 如果讀到等號(hào) *)
begin
sym := geq; (* 購(gòu)成一個(gè)大于等于號(hào) *)
getch (* 讀一個(gè)字符 *)
end
else (* 如果大于號(hào)后不是跟的等號(hào) *)
sym := gtr (* 那就是一個(gè)單獨(dú)的大于號(hào) *)
end
else(* 如果讀到不是字母也不是數(shù)字也不是冒號(hào)也不是小于號(hào)也不是大于號(hào) *)
begin (* 那就說(shuō)明它不是標(biāo)識(shí)符/保留字,也不是復(fù)雜的雙字節(jié)操作符,應(yīng)該是一個(gè)普通的符號(hào) *)
sym := ssym[ch]; (* 直接成符號(hào)表中查到它的類型,賦給sym *)
getch (* 讀下一個(gè)字符 *)
end
(* 整個(gè)if語(yǔ)句判斷結(jié)束 *)
end (* getsym *);
(* 詞法分析過(guò)程getsym總結(jié):從源文件中讀出若干有效字符,組成一個(gè)token串,識(shí)別它的類型
為保留字/標(biāo)識(shí)符/數(shù)字或是其它符號(hào)。如果是保留字,把sym置成相應(yīng)的保留字類型,如果是
標(biāo)識(shí)符,把sym置成ident表示是標(biāo)識(shí)符,于此同時(shí),id變量中存放的即為保留字字符串或標(biāo)識(shí)
符名字。如果是數(shù)字,把sym置為number,同時(shí)num變量中存放該數(shù)字的值。如果是其它的操作符,
則直接把sym置成相應(yīng)類型。經(jīng)過(guò)本過(guò)程后ch變量中存放的是下一個(gè)即將被識(shí)別的字符 *)
(* 目標(biāo)代碼生成過(guò)程gen *)
(* 參數(shù):x:要生成的一行代碼的助記符 *)
(* y, z:代碼的兩個(gè)操作數(shù) *)
(* 本過(guò)程用于把生成的目標(biāo)代碼寫入目標(biāo)代碼數(shù)組,供后面的解釋器解釋執(zhí)行 *)
procedure gen(x: fct; y, z: integer);
begin
if cx > cxmax then (* 如果cx>cxmax表示當(dāng)前生成的代碼行號(hào)大于允許的最大代碼行數(shù) *)
begin
write('program too long'); (* 輸出"程序太長(zhǎng)",退出 *)
close(fa);
close(fa1);
close(fin);
halt(0)
{goto 99}
(* 我修改的代碼,由于Turbo Pascal 7.0中不允許跨過(guò)程的goto,就只能用上面的方法退出程序了。 *)
end;
with code[cx] do (* 把代碼寫入目標(biāo)代碼數(shù)組的當(dāng)前cx所指位置 *)
begin
f := x;
l := y;
a := z;
end;
cx := cx + 1 (* 移動(dòng)cx指針指向下一個(gè)空位 *)
end (* gen *);
(* 測(cè)試當(dāng)前單詞是否合法過(guò)程test *)
(* 參數(shù):s1:當(dāng)語(yǔ)法分析進(jìn)入或退出某一語(yǔ)法單元時(shí)當(dāng)前單詞符合應(yīng)屬于的集合 *)
(* s2:在某一出錯(cuò)狀態(tài)下,可恢復(fù)語(yǔ)法分析正常工作的補(bǔ)充單詞集合 *)
(* n:出錯(cuò)信息編號(hào),當(dāng)當(dāng)前符號(hào)不屬于合法的s1集合時(shí)發(fā)出的出錯(cuò)信息 *)
procedure test(s1, s2: symset; n: integer);
begin
if not (sym in s1) then (* 如果當(dāng)前符號(hào)不在s1中 *)
begin
error(n); (* 發(fā)出n號(hào)錯(cuò)誤 *)
s1 := s1 + s2; (* 把s2集合補(bǔ)充進(jìn)s1集合 *)
while not (sym in s1) do (* 通過(guò)循環(huán)找到下一個(gè)合法的符號(hào),以恢復(fù)語(yǔ)法分析工作 *)
getsym
end
end (* test *);
(* 語(yǔ)法分析過(guò)程block *)
(* 參數(shù):lev:這一次語(yǔ)法分析所在的層次 *)
(* tx:符號(hào)表指針 *)
(* fsys:用于出錯(cuò)恢復(fù)的單詞集合 *)
procedure block(lev, tx: integer; fsys: symset);
var
dx: integer; (* data allocation index *) (* 數(shù)據(jù)段內(nèi)存分配指針,指向下一個(gè)被分配空間在數(shù)據(jù)段中的偏移位置 *)
tx0: integer; (* initial table index *) (* 記錄本層開(kāi)始時(shí)符號(hào)表位置 *)
cx0: integer; (* initial code index *) (* 記錄本層開(kāi)始時(shí)代碼段分配位置 *)
(* 登陸符號(hào)表過(guò)程enter *)
(* 參數(shù):k:欲登陸到符號(hào)表的符號(hào)類型 *)
procedure enter(k: object1);
begin (* enter object into table *)
tx := tx + 1; (* 符號(hào)表指針指向一個(gè)新的空位 *)
with table[tx] do (* 開(kāi)始登錄 *)
begin
name := id; (* name是符號(hào)的名字,對(duì)于標(biāo)識(shí)符,這里就是標(biāo)識(shí)符的名字 *)
kind := k; (* 符號(hào)類型,可能是常量、變量或過(guò)程名 *)
case k of (* 根據(jù)不同的類型進(jìn)行不同的操作 *)
constant: (* 如果是常量名 *)
begin
if num > amax then (* 在常量的數(shù)值大于允許的最大值的情況下 *)
begin
error(31); (* 拋出31號(hào)錯(cuò)誤 *)
num := 0; (* 實(shí)際登陸的數(shù)字以0代替 *)
end;
val := num (* 如是合法的數(shù)值,就登陸到符號(hào)表 *)
end;
variable: (* 如果是變量名 *)
begin
level := lev; (* 記下它所屬的層次號(hào) *)
adr := dx; (* 記下它在當(dāng)前層中的偏移量 *)
dx := dx+1; (* 偏移量自增一,為下一次做好準(zhǔn)備 *)
end;
procedur: (* 如果要登陸的是過(guò)程名 *)
level := lev (* 記錄下這個(gè)過(guò)程所在層次 *)
end
end
end (* enter *);
(* 登錄符號(hào)過(guò)程沒(méi)有考慮到重復(fù)的定義的問(wèn)題。如果出現(xiàn)重復(fù)定義,則以最后一次的定義為準(zhǔn)。 *)
(* 在符號(hào)表中查找指定符號(hào)所在位置的函數(shù)position *)
(* 參數(shù):id:要找的符號(hào) *)
(* 返回值:要找的符號(hào)在符號(hào)表中的位置,如果找不到就返回0 *)
function position (id: alfa): integer;
var
i: integer;
begin (* find identifier in table *)
table[0].name := id; (* 先把id放入符號(hào)表0號(hào)位置 *)
i := tx; (* 從符號(hào)表中當(dāng)前位置也即最后一個(gè)符號(hào)開(kāi)始找 *)
while table[i].name <> id do (* 如果當(dāng)前的符號(hào)與要找的不一致 *)
i := i - 1; (* 找前面一個(gè) *)
position := i (* 返回找到的位置號(hào),如果沒(méi)找到則一定正好為0 *)
end(* position *);
(* 常量聲明處理過(guò)程constdeclaration *)
procedure constdeclaration;
begin
if sym = ident then (* 常量聲明過(guò)程開(kāi)始遇到的第一個(gè)符號(hào)必然應(yīng)為標(biāo)識(shí)符 *)
begin
getsym; (* 獲取下一個(gè)token *)
if sym in [eql, becomes] then (* 如果是等號(hào)或賦值號(hào) *)
begin
if sym = becomes then (* 如果是賦值號(hào)(常量生明中應(yīng)該是等號(hào)) *)
error(1); (* 拋出1號(hào)錯(cuò)誤 *)
(* 這里其實(shí)自動(dòng)進(jìn)行了錯(cuò)誤糾正使編譯繼續(xù)進(jìn)行,把賦值號(hào)當(dāng)作等號(hào)處理 *)
getsym; (* 獲取下一個(gè)token,等號(hào)或賦值號(hào)后應(yīng)接上數(shù)字 *)
if sym = number then (* 如果的確是數(shù)字 *)
begin
enter(constant); (* 把這個(gè)常量登陸到符號(hào)表 *)
getsym (* 獲取下一個(gè)token,為后面作準(zhǔn)備 *)
end
else
error(2) (* 如果等號(hào)后接的不是數(shù)字,拋出2號(hào)錯(cuò)誤 *)
end
else
error(3) (* 如果常量標(biāo)識(shí)符后接的不是等號(hào)或賦值號(hào),拋出3號(hào)錯(cuò)誤 *)
end
else
error(4) (* 如果常量聲明過(guò)程遇到的第一個(gè)符號(hào)不為標(biāo)識(shí)符,拋出4號(hào)錯(cuò)誤 *)
end(* constdeclaration *);
(* 變量聲明過(guò)程vardeclaration *)
procedure vardeclaration;
begin
if sym = ident then (* 變量聲明過(guò)程開(kāi)始遇到的第一個(gè)符號(hào)必然應(yīng)為標(biāo)識(shí)符 *)
begin
enter(variable); (* 將標(biāo)識(shí)符登陸到符號(hào)表中 *)
getsym (* 獲取下一個(gè)token,為后面作準(zhǔn)備 *)
end
else
error(4) (* 如果變量聲明過(guò)程遇到的第一個(gè)符號(hào)不是標(biāo)識(shí)符,拋出4號(hào)錯(cuò)誤 *)
end(* vardeclaration *);
(* 列出當(dāng)前一層類PCODE目標(biāo)代碼過(guò)程listcode *)
procedure listcode;
var
i: integer;
begin (* list code generated for this block *)
if listswitch then (* 如果用戶選擇是要列出代碼的情況下才列出代碼 *)
begin
for i := cx0 to cx - 1 do (* 從當(dāng)前層代碼開(kāi)始位置到當(dāng)前代碼位置-1處,即為本分程序塊 *)
with code[i] do
begin
writeln(i: 4, mnemonic[f]: 5, l: 3, a: 5); (* 顯示出第i行代碼的助記符和L與A操作數(shù) *)
(* 我修改的代碼:原程序此處在輸出i時(shí),沒(méi)有指定占4個(gè)字符寬度,不美觀也與下面一句不配套。 *)
writeln(fa, i: 4, mnemonic[f]: 5, l: 3, a: 5) (* 同時(shí)把屏顯打印到文件 *)
end;
end
end(* listcode *);
(* 語(yǔ)句處理過(guò)程statement *)
(* 參數(shù)說(shuō)明:fsys: 如果出錯(cuò)可用來(lái)恢復(fù)語(yǔ)法分析的符號(hào)集合 *)
procedure statement(fsys: symset);
var
i, cx1, cx2: integer;
(* 表達(dá)式處理過(guò)程expression *)
(* 參數(shù)說(shuō)明:fsys: 如果出錯(cuò)可用來(lái)恢復(fù)語(yǔ)法分析的符號(hào)集合 *)
procedure expression(fsys: symset);
var
addop: symbol;
(* 項(xiàng)處理過(guò)程term *)
(* 參數(shù)說(shuō)明:fsys: 如果出錯(cuò)可用來(lái)恢復(fù)語(yǔ)法分析的符號(hào)集合 *)
procedure term(fsys: symset);
var
mulop: symbol;
(* 因子處理過(guò)程factor *)
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -