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] Kiểm tra kiểu với bảng ký hiệu theo phạm vi khối lồng nhau

    Trình biên dịch quản lý các biến bằng bảng ký hiệu theo phạm vi khối lồng nhau (nested block scoping) dưới dạng ngăn xếp các phạm vi (scope stack): khi vào một khối lệnh mới, một phạm vi mới được đẩy vào ngăn xếp; khi ra khỏi khối, phạm vi đó bị gỡ bỏ. Một biến khai báo trong khối trong che khuất (shadow) biến cùng tên ở khối ngoài, và việc tra cứu kiểu của một biến luôn tìm từ phạm vi trong cùng ra ngoài (innermost-first).

    Chương trình gồm nnn lệnh, mỗi lệnh là một trong các dạng:

    • OPEN — mở một phạm vi mới (đẩy vào ngăn xếp).
    • CLOSE — đóng phạm vi hiện tại (gỡ khỏi ngăn xếp).
    • DECL kiểu tên — khai báo biến tên với kiểu ∈{\in \{∈{int, float, bool, string}\}} trong phạm vi hiện tại (nếu tên đã tồn tại trong đúng phạm vi hiện tại, khai báo mới ghi đè kiểu cũ).
    • ASSIGN tên giá_trị — gán, với giá_trị là tên biến khác hoặc hằng số (phân loại như bài kiểm tra kiểu biểu thức số học). Tìm kiểu khai báo của tên theo quy tắc tra cứu phạm vi ở trên, rồi áp dụng đúng luật kiểm tra lệnh gán: L=RL=RL=R hoặc (L=L=L=float, R=R=R=int) → OK; L=L=L=int, R=R=R=float → Narrowing Error; còn lại → Type Mismatch. Nếu tên (hoặc biến được tham chiếu trong giá_trị) không tìm thấy ở bất kỳ phạm vi đang mở nào → Undeclared Variable.
    • PRINT tên — in ra kiểu hiện tại của tên theo tra cứu phạm vi, hoặc Undeclared Variable nếu không tìm thấy.

    Chỉ các lệnh ASSIGN và PRINT mới sinh ra dòng kết quả; OPEN, CLOSE, DECL không sinh dòng nào. Lệnh đầu tiên trong chương trình luôn là OPEN.

    Ví dụ: OPEN / DECL int x / OPEN / DECL float x / PRINT x / CLOSE / PRINT x in ra float rồi int — biến x bên trong che khuất biến x bên ngoài, và sau khi CLOSE thì x bên ngoài lộ trở lại.

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

      Dòng đầu là số nguyên nnn (1≤n≤20001 \le n \le 20001≤n≤2000) — tổng số token-lệnh (đếm mỗi OPEN/CLOSE là 1 lệnh, DECL kiểu tên là 1 lệnh, ASSIGN tên giá_trị là 1 lệnh, PRINT tên là 1 lệnh). nnn dòng tiếp theo, mỗi dòng là một lệnh theo đúng các dạng mô tả ở trên (các token trong một lệnh cách nhau bởi khoảng trắng).

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

      In ra một dòng cho mỗi lệnh ASSIGN hoặc PRINT, theo đúng thứ tự xuất hiện trong chương trình: với ASSIGN là một trong OK, Narrowing Error, Type Mismatch, Undeclared Variable; với PRINT là kiểu của biến (int/float/bool/string) hoặc Undeclared Variable.

    Ví dụ:

    Đầu vào:

    5
    OPEN
    DECL int x
    ASSIGN x 5
    PRINT x
    CLOSE
    

    Đầu ra:

    OK
    int
    

    Đầu vào:

    12
    OPEN
    DECL int x
    ASSIGN x 5
    OPEN
    DECL float x
    ASSIGN x 2.5
    PRINT x
    CLOSE
    PRINT x
    ASSIGN x 2.5
    CLOSE
    PRINT x
    

    Đầu ra:

    OK
    OK
    float
    int
    Narrowing Error
    Undeclared Variable
    

    Đang tải editor...