Trình biên dịch quản lý các phạm vi (scope) lồng nhau bằng một ngăn xếp bảng ký hiệu: mỗi phạm vi có một bảng ký hiệu riêng, phạm vi toàn cục ở độ sâu (depth) 0, mỗi lần vào khối lệnh mới độ sâu tăng thêm 1.
Xử lý các lệnh sau theo thứ tự:
{: mở một phạm vi mới (độ sâu tăng 1).}: đóng phạm vi hiện tại, trở về phạm vi cha (độ sâu giảm 1; không bao giờ đóng phạm vi toàn cục, dữ liệu vào đảm bảo hợp lệ).DECL <name> <type>: khai báo biến name kiểu type trong phạm vi hiện tại. Nếu name đã tồn tại trong chính phạm vi hiện tại, đây là lỗi khai báo trùng (bảng ký hiệu KHÔNG bị ghi đè).USE <name>: tra cứu name, tìm từ phạm vi hiện tại ra dần các phạm vi bao ngoài (biến ở phạm vi gần hơn che khuất biến cùng tên ở phạm vi ngoài).Ví dụ
Input:
8
DECL x int
{
DECL y float
USE x
USE y
DECL x bool
USE x
}
Output:
x int 0
y float 1
x bool 1
Giải thích: x khai báo ở độ sâu 0. Vào khối con (độ sâu 1), y khai báo tại đó; USE x tìm thấy x ở độ sâu 0; USE y tìm thấy y ở độ sâu 1. Sau đó khai báo thêm x kiểu bool ngay trong khối con (độ sâu 1) — biến này che khuất x toàn cục — nên USE x cuối cùng trả về x bool 1.
Dòng đầu tiên chứa số nguyên n (0≤n≤2000) là số lệnh.
n dòng tiếp theo, mỗi dòng là một trong các lệnh: {, }, DECL <name> <type>, USE <name> (type là một chuỗi ký tự bất kỳ không chứa khoảng trắng, không cần kiểm tra hợp lệ về mặt từ vựng).
Với DECL bị trùng tên trong cùng phạm vi hiện tại: in ERROR trung: <name>; nếu thành công thì không in gì.
Với USE: nếu tìm thấy, in <name> <type> <depth> (ba giá trị cách nhau một khoảng trắng, depth là độ sâu — số nguyên không âm — của phạm vi nơi tìm thấy khai báo gần nhất); nếu không tìm thấy ở bất kỳ phạm vi nào, in ERROR: <name> khong ton tai.
Lệnh {, } không sinh output. Thứ tự các dòng output đúng theo thứ tự lệnh trong input.
Ví dụ:
Đầu vào:
0
Đầu ra:
Đầu vào:
8
DECL x int
{
DECL y float
USE x
USE y
DECL x bool
USE x
}
Đầu ra:
x int 0
y float 1
x bool 1
Đang tải editor...