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] Phát hiện khai báo trùng trong cùng phạm vi

    Trong một phạm vi (scope) của bảng ký hiệu, mỗi tên biến chỉ được phép khai báo đúng một lần — khai báo trùng tên trong cùng một phạm vi (không phải ở phạm vi bao ngoài, mà chính xác là cùng một khối lệnh đang mở) là lỗi biên dịch "khai báo trùng" (redeclaration error).

    Xét mô hình ngăn xếp phạm vi quen thuộc: BEGIN đẩy một phạm vi rỗng mới, END gỡ phạm vi ở đỉnh ngăn xếp (không bao giờ gỡ phạm vi toàn cục), DECL x v khai báo biến x với giá trị v (một chuỗi không chứa khoảng trắng) vào phạm vi ở đỉnh ngăn xếp hiện tại.

    Cho dãy nnn lệnh (đánh số dòng lệnh từ 111 đến nnn theo thứ tự xuất hiện trong input), hãy tìm tất cả các lệnh DECL x v mà tại thời điểm thực hiện, tên x đã tồn tại sẵn trong chính phạm vi ở đỉnh ngăn xếp lúc đó (tức là bị khai báo trùng ngay trong cùng khối, không tính các biến cùng tên ở phạm vi bao ngoài). Với mỗi lệnh DECL gây lỗi như vậy, dòng lệnh đó được xem là lỗi và sẽ không ghi đè giá trị cũ trong phạm vi (giá trị cũ được giữ nguyên).

    Lưu ý: khi một phạm vi được mở lại bằng một BEGIN mới (dù cùng độ sâu lồng như một khối đã đóng trước đó), nó là một phạm vi hoàn toàn mới, rỗng, không "nhớ" các biến đã khai báo trong khối trước đó ở cùng vị trí.

    Ví dụ: với dãy lệnh

    7
    DECL x 1
    BEGIN
    DECL x 2
    DECL y 3
    DECL x 4
    END
    DECL x 5
    

    lệnh số 555 (DECL x 4) trùng với x vừa khai báo ở lệnh số 333 trong cùng khối con, và lệnh số 777 (DECL x 5) trùng với x đã khai báo ở lệnh số 111 trong phạm vi toàn cục (khối con đã đóng ở lệnh 666 nên không liên quan). Kết quả in ra:

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

      Dòng đầu tiên chứa số nguyên nnn (1≤n≤2×1051 \le n \le 2\times10^51≤n≤2×105) — số lệnh. nnn dòng tiếp theo, mỗi dòng là một lệnh dạng BEGIN, END, hoặc DECL x v (x, v là các chuỗi không chứa khoảng trắng). Dữ liệu đảm bảo mọi END đều khớp với một BEGIN đã mở trước đó.

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

      Nếu tồn tại ít nhất một lệnh DECL bị khai báo trùng trong cùng phạm vi, in ra các số hiệu dòng lệnh (theo thứ tự tăng dần, mỗi số một dòng) của tất cả các lệnh đó. Nếu không có lệnh nào bị trùng, in ra đúng một dòng chứa chuỗi OK.

    Ví dụ:

    Đầu vào:

    4
    DECL a 1
    BEGIN
    DECL a 2
    END
    

    Đầu ra:

    OK
    

    Đầu vào:

    7
    DECL x 1
    BEGIN
    DECL x 2
    DECL y 3
    DECL x 4
    END
    DECL x 5
    

    Đầu ra:

    5
    7
    

    Đang tải editor...