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] Chỉ số De Bruijn cho tham chiếu biến

    Trong xử lý phạm vi (scope) lồng nhau, nhiều trình biên dịch không lưu trực tiếp độ sâu tuyệt đối của biến mà lưu khoảng cách tương đối (chỉ số kiểu De Bruijn) từ nơi biến được sử dụng đến phạm vi nơi nó được khai báo — đây là cách biểu diễn phổ biến trong các bộ thông dịch closure/lambda calculus.

    Chương trình bắt đầu với phạm vi toàn cục (mức 000). Bạn cần xử lý các lệnh sau, theo thứ tự:

    • {: mở một phạm vi mới lồng vào phạm vi hiện tại.
    • }: đóng phạm vi lồng gần nhất hiện tại (không bao giờ đóng phạm vi toàn cục; dữ liệu vào đảm bảo không có lệnh } thừa).
    • DECL <name>: khai báo biến name 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 (không tính các phạm vi bao ngoài) thì đây là lỗi khai báo trùng.
    • USE <name>: tham chiếu biến name. Gọi ddd là số lần phải "đi ra" phạm vi bao ngoài (tính từ phạm vi hiện tại) để tìm thấy khai báo gần nhất của name — nếu tìm thấy ngay trong phạm vi hiện tại thì d=0d=0d=0; nếu phải ra ngoài đúng một cấp thì d=1d=1d=1, v.v. Biến ở phạm vi gần hơn luôn được ưu tiên (che khuất biến cùng tên ở phạm vi ngoài).

    Ví dụ

    Input:

    7
    DECL x
    {
    USE x
    DECL x
    USE x
    }
    USE x
    

    Output:

    1
    0
    0
    

    Giải thích: x được khai báo ở phạm vi toàn cục. Vào phạm vi con, USE x lần đầu phải đi ra 1 cấp mới thấy x (in 1); sau đó DECL x khai báo x mới ngay trong phạm vi con (che khuất x ngoài); USE x lần hai thấy ngay (d=0d=0d=0). Ra khỏi phạm vi con, USE x cuối cùng lại thấy x toàn cục ngay lập tức (d=0d=0d=0).

    • Đị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>, USE <name>.

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

      Với mỗi lệnh DECL bị trùng tên trong cùng phạm vi hiện tại, in ra ERROR: <name> da duoc khai bao trong pham vi nay; nếu khai báo thành công thì không in gì. Với mỗi lệnh USE: nếu tìm thấy khai báo (ở phạm vi hiện tại hoặc bất kỳ phạm vi bao ngoài nào, kể cả toàn cục), in ra khoảng cách ddd (một số nguyên không âm); nếu không tìm thấy ở bất kỳ đâu, in ra UNDECLARED. Lệnh { và } không sinh ra output. Các dòng output theo đúng thứ tự lệnh trong input.

    Ví dụ:

    Đầu vào:

    0
    

    Đầu ra:

    
    

    Đầu vào:

    7
    DECL x
    {
    USE x
    DECL x
    USE x
    }
    USE x
    

    Đầu ra:

    1
    0
    0
    

    Đang tải editor...