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] Cấp phát offset khung ngăn xếp theo khối

    Khi sinh mã cho một khối lệnh, trình biên dịch cần cấp phát vị trí lưu trữ (offset trong khung ngăn xếp — stack frame) cho từng biến cục bộ. Một chiến lược đơn giản và phổ biến là bộ cấp phát kiểu ngăn xếp (stack allocator): duy trì một con trỏ khung hiện tại ppp (ban đầu p=0p=0p=0); mỗi khi khai báo một biến kiểu ttt có kích thước size(t)\text{size}(t)size(t) byte, biến đó được gán offset bằng giá trị ppp hiện tại, sau đó ppp tăng thêm size(t)\text{size}(t)size(t); khi một khối lệnh kết thúc, mọi biến cục bộ khai báo bên trong khối đó được giải phóng — con trỏ ppp được khôi phục về đúng giá trị mà nó có ngay trước khi khối đó mở, để không gian này có thể được tái sử dụng bởi các khối anh em (sibling) tiếp theo.

    Kích thước các kiểu dữ liệu: int = 444 byte, char = 111 byte, bool = 111 byte, double = 888 byte. Không cần căn chỉnh (alignment) — cấp phát liên tiếp theo đúng kích thước.

    Cho dãy nnn lệnh, mỗi lệnh thuộc một trong ba dạng:

    • BEGIN: mở một khối lệnh mới — ghi nhớ giá trị ppp hiện tại.
    • END: đóng khối lệnh gần nhất đang mở — khôi phục ppp về giá trị đã ghi nhớ khi khối đó mở (nếu không có khối nào đang mở thì bỏ qua).
    • DECL x t: khai báo biến x kiểu t (t∈{int,char,bool,double}t \in \{\texttt{int}, \texttt{char}, \texttt{bool}, \texttt{double}\}t∈{int,char,bool,double}) trong khối hiện tại, theo đúng cơ chế cấp phát ở trên.

    Với mỗi lệnh DECL, in ra offset được cấp cho biến đó. Sau khi xử lý xong toàn bộ nnn lệnh, in thêm một dòng cuối cùng là kích thước khung ngăn xếp cần thiết — giá trị lớn nhất mà ppp từng đạt được trong suốt quá trình (high-water mark), vì đó chính là dung lượng tối thiểu cần cấp phát sẵn cho toàn bộ hàm.

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

    7
    DECL a int
    BEGIN
    DECL b double
    DECL c char
    END
    BEGIN
    DECL d int
    

    a được offset 000 (p:0→4p: 0\to4p:0→4); vào khối con, b offset 444 (p:4→12p:4\to12p:4→12), c offset 121212 (p:12→13p:12\to13p:12→13); khối đóng, ppp khôi phục về 444; khối mới mở, d offset 444 (p:4→8p:4\to8p:4→8). Kích thước khung lớn nhất từng đạt là 131313. Kết quả in ra:

    0
    4
    12
    4
    13
    
    • Đị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 t (x là tên biến bất kỳ không chứa khoảng trắng, t là một trong bốn từ khóa kiểu: int, char, bool, double).

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

      Với mỗi lệnh DECL (theo đúng thứ tự xuất hiện), in ra một dòng là offset (số nguyên ≥0\ge 0≥0) được cấp cho biến đó. Sau tất cả các dòng đó, in thêm đúng một dòng cuối cùng là kích thước khung ngăn xếp lớn nhất từng cần dùng.

    Ví dụ:

    Đầu vào:

    7
    DECL a int
    BEGIN
    DECL b double
    DECL c char
    END
    BEGIN
    DECL d int
    

    Đầu ra:

    0
    4
    12
    4
    13
    

    Đầu vào:

    4
    DECL a int
    DECL b char
    DECL c bool
    DECL d double
    

    Đầu ra:

    0
    4
    5
    6
    14
    

    Đang tải editor...