實驗環境:Python3.6
實驗目的
- 根據 PL/0 語言的文法規范,編寫 PL/0 語言的標識符識別程序。
- 通過設計調試標識符識別程序,實現從源程序中分出各個標識符的方法;加深對課堂教學的理解; 為后序詞法分析程序的實現打下基礎 。
- 掌握從源程序文件中讀取有效字符的方法和產生源程序的內部表示文件的法。
- 掌握識別標識符的實現方法。
- 上機調試完成的識別標識符程序的實現。
實驗時間
2學時
實驗內容
上機調試完成的識別標識符程序的實現。
實驗要求
- 識別程序讀入 PL/0 語言源程序(文本文件),識別結果也以文本文件保存 。
- 按標識符出現的順序輸出結果, 每個標識符一行, 采用二元式序列,即: (標識符值, 標識符出現次數)
- 源程序中字符不區分大小寫,即:“a1” 和“A1” 是同一個標識符。
- 准備至少 5 組測試用例,每組測試用例包括:輸入源程序文件和輸出結果。
- 測試用例應該考慮各種合法標識符的組合情況。
輸入輸出樣例
輸入文件
Const num=100;
Var a1,b2;
Begin
Read(A1);
b2:=a1+num;
write(A1,B2);
End.
輸出:(文本文件)
(num: 2)
(a1: 4)
(b2: 3)
實驗內容
實驗思路
PL/0程序中有兩種標識符定義關鍵字var
和const
,procedure
,利用這三種關鍵字識別標識符,將標識符存儲在一個數組中,之后再根據數組中的標識符進行正則匹配,查找程序中出現了多少次此標識符。本實驗的程序使用python編寫。
實驗代碼解析
# 導入庫,正則匹配需要
import re
# 定義符數組
dingyi = ['var', 'const', 'procedure']
# 計數字典
count = {}
# 程序分割后的語句
yuju = []
# 標識符存儲數組
bianliang = []
# 存儲語句的數組
a = []
# 讀文件操作
with open("input.txt") as f:
# 將字符全部轉為小寫
content = f.read().lower().split('\n')
for c in content:
c = c.strip()
# 去除注釋
if len(c) != 0:
if c[0] == '{':
continue
# 判斷字符串定義
if c[0:3] == 'var' or c[0:5] == 'const' or c[0:9] == 'procedure':
if 'var' in c:
c = c.replace('var ', '')
if 'const' in c:
c = c.replace('const ', '')
elif 'procedure' in c:
c = c.replace('procedure', '')
c.replace(' ', '')
con = c.split(',')
for cd in con:
x = cd.split('=')
count[x[0].rstrip(";").replace(' ', '')] = 0
# 存儲字符串
bianliang.append(x[0].rstrip(";").replace(' ', ''))
for c in content:
# 去除字符左右兩邊的空格
c = c.strip()
if len(c) != 0:
# 去除注釋
if c[0] == '{':
continue
for b in bianliang:
# 正則匹配 [^a-z]為非字母
matchObj = re.match(r'.*[^a-z]' + b + '[^a-z^0-9]', c, re.M | re.I)
a = -1
while matchObj:
count[b] = count[b] + 1
a = matchObj.end() - 2
matchObj = re.match(r'.*[^a-z]' + b + '[^a-z^0-9]', c[:matchObj.end() - 2], re.M | re.I)
matchObj = re.match(r'' + b + '[^a-z^0-9]', c[:a], re.M | re.I)
while matchObj:
count[b] = count[b] + 1
matchObj = re.match(r'' + b + '[^a-z^0-9]', c[:matchObj.end() - 2], re.M | re.I)
# 寫入文件操作
with open("output.txt", 'w') as f:
for i in bianliang:
f.write("(" + i + ":\t" + str(count[i]) + ")\n")
測試用例
測試用例一
var a, b, c, r;
{ 將a, b, c排序 }
begin
read(a);
read(b);
read(c);
if a > b then
begin
r := a;
a := b;
b := r;
end;
if b > c then
begin
r := b;
b := c;
c := r;
end;
if a > b then
begin
r := a;
a := b;
b := r;
end;
write(a);
write(b);
write(c);
end.
測試用例二
var a, b, c, flag, x, y, z, flag2, flag3;
const yiban=0, dengyao = 1, dengyaozhijiao = 2, zhijiao=3, dengbian=4, fei=5;
procedure dyzhijiao;
begin
if 2 * x * x = y * y then
begin
write(dengyaozhijiao);
flag2 := 1;
flag := 1;
end;
if flag2 # 1 then
begin
write(dengyao);
flag := 1;
end;
end;
beigin
call dyzhijiao;
end.
測試用例三
var a, b, c, flag, x, y, z, flag2, flag3;
const yiban=0, dengyao = 1, dengyaozhijiao = 2, zhijiao=3, dengbian=4, fei=5;
begin
if x*x + y*y = z*z then
begin
write(zhijiao);
flag := 1;
end;
end;
測試用例四
var a, b, c, flag, x, y, z, flag2, flag3;
const yiban=0, dengyao = 1, dengyaozhijiao = 2, zhijiao=3, dengbian=4, fei=5;
begin
if a+b>c then
begin
if a+c>b then
begin
if b+c>a then
begin
flag3 := 1;
if a = b then
begin
if b = c then
begin
write(dengbian);
flag := 1;
end;
end;
if flag # 1 then
begin
if a = b then
begin
x := a;y := c;
call dyzhijiao;
end;
if c = b then
begin
x := b;y := a;
call dyzhijiao;
end;
if a = c then
begin
x := a;y := b;
call dyzhijiao;
end;
if flag # 1 then
begin
x:=a;y:=b;z:=c;
call zhijiao;
x:=a;y:=c;z:=b;
call zhijiao;
x:=c;y:=b;z:=a;
call zhijiao;
end;
if flag # 1 then
begin
wirte(yiban)
end;
end;
end;
end;
end;
測試用例五
var flag3;
const yiban=0, dengyao = 1, dengyaozhijiao = 2, zhijiao=3, dengbian=4, fei=5;
if flag3 # 1 then
begin
write(fei)
end;