Các lượt nộp
    Danh sách bài
    Trang chủ
    Báo lỗi

    solution

    Đề bài: [Trình biên dịch] Tra cứu tên và kiểu trong ngăn xếp phạm vi

    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.

    • Định dạng đầu vào:

      Dòng đầu tiên chứa số nguyên nnn (0≤n≤20000 \le n \le 20000≤n≤2000) là số lệnh. nnn 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).

    • Định dạng đầu ra:

      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...