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] Khai triển macro tự tham chiếu (quy tắc sơn xanh)

    Một macro object-like có thể tham chiếu đến chính nó hoặc tạo thành vòng lặp tham chiếu lẫn nhau (ví dụ #define X 1 + X). Nếu khai triển "ngây thơ" (cứ thấy tên macro là thay thế) thì quá trình này sẽ lặp vô hạn. Các trình biên dịch C thật sự tránh điều này bằng quy tắc: trong quá trình khai triển một macro, nếu tên của chính nó (hoặc tên của một macro "tổ tiên" đang trong quá trình khai triển dẫn đến vị trí hiện tại) xuất hiện lại, thì không khai triển tiếp occurrence đó nữa — giữ nguyên nó như một token thường (dân trong ngành gọi vui là macro đó đã bị "sơn xanh" tại vị trí đó).

    Cho nnn định nghĩa macro object-like (không tham số) NAME t_1 t_2 \dots t_B, trong đó NAMENAMENAME là tên macro và t1,…,tBt_1,\dots,t_Bt1​,…,tB​ là thân macro — một dãy token (B≥0B \ge 0B≥0), mỗi token có thể là tên của một macro khác (kể cả chính nó) hoặc một token thường. Cho một tên macro truy vấn QQQ (đảm bảo đã được định nghĩa).

    Hãy khai triển QQQ đầy đủ theo quy tắc đệ quy chính xác sau: gọi expand(t,S)\text{expand}(t, S)expand(t,S) là kết quả khai triển token ttt biết tập "đã sơn xanh" hiện tại là SSS — nếu ttt là tên một macro và t∉St \notin St∈/S, kết quả là nối tiếp expand(ti,S∪{t})\text{expand}(t_i, S \cup \{t\})expand(ti​,S∪{t}) cho từng token tit_iti​ trong thân macro ttt (theo thứ tự); ngược lại (không phải macro, hoặc t∈St \in St∈S) kết quả là chính token ttt. Đáp số là expand(Q,∅)\text{expand}(Q, \emptyset)expand(Q,∅).

    Ví dụ: X có thân 1 + X. Khai triển X: vì X tham chiếu chính nó, khi gặp lại token X bên trong khai triển của chính nó thì giữ nguyên. Kết quả: 1 + X.

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

      Dòng đầu tiên chứa số nguyên nnn (1≤n≤1001 \le n \le 1001≤n≤100). nnn dòng tiếp theo, mỗi dòng có dạng NAME t_1 t_2 \dots t_B (0≤B≤200 \le B \le 200≤B≤20, các tên macro và token chỉ gồm chữ/số/gạch dưới). Dòng cuối cùng chứa tên macro truy vấn QQQ, đảm bảo QQQ xuất hiện là tên của một trong nnn định nghĩa trên.

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

      In ra một dòng là kết quả khai triển expand(Q,∅)\text{expand}(Q,\emptyset)expand(Q,∅), các token cách nhau một khoảng trắng (dòng rỗng nếu kết quả không còn token nào).

    Ví dụ:

    Đầu vào:

    2
    A B end
    B A start
    A
    

    Đầu ra:

    A start end
    

    Đầu vào:

    2
    X 1 + X
    A A
    X
    

    Đầu ra:

    1 + X
    

    Đang tải editor...