编译原理实验 识别标识符
实验环境: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;
我不管,JS天下第一