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] FIRST của một chuỗi ký hiệu

    Trong xây dựng bộ phân tích LR nâng cao (đặc biệt là tính tập lookahead khi dựng các tập mục LR(1)), ta thường xuyên cần tính FIRST\mathrm{FIRST}FIRST không chỉ của một ký hiệu chưa kết thúc, mà của cả một chuỗi ký hiệu α=X1X2…Xk\alpha = X_1 X_2 \ldots X_kα=X1​X2​…Xk​ (có thể trộn lẫn terminal và non-terminal, ví dụ FIRST(βa)\mathrm{FIRST}(\beta a)FIRST(βa) khi đóng mục LR(1)).

    Định nghĩa: FIRST(α)\mathrm{FIRST}(\alpha)FIRST(α) là tập tất cả các ký hiệu kết thúc aaa sao cho tồn tại một dẫn xuất α⇒∗a…\alpha \Rightarrow^{*} a \ldotsα⇒∗a…. Nếu α⇒∗ε\alpha \Rightarrow^{*} \varepsilonα⇒∗ε thì ε∈FIRST(α)\varepsilon \in \mathrm{FIRST}(\alpha)ε∈FIRST(α) (ta ký hiệu ε\varepsilonε bằng chuỗi eps trong kết quả).

    Quy tắc tính FIRST(X1X2…Xk)\mathrm{FIRST}(X_1 X_2 \ldots X_k)FIRST(X1​X2​…Xk​): xét lần lượt X1,X2,…X_1, X_2, \ldotsX1​,X2​,…; với mỗi XiX_iXi​, thêm FIRST(Xi)∖{ε}\mathrm{FIRST}(X_i) \setminus \{\varepsilon\}FIRST(Xi​)∖{ε} vào kết quả; nếu ε∉FIRST(Xi)\varepsilon \notin \mathrm{FIRST}(X_i)ε∈/FIRST(Xi​) thì dừng lại (không xét các Xj,j>iX_j, j>iXj​,j>i nữa); nếu ε∈FIRST(Xi)\varepsilon \in \mathrm{FIRST}(X_i)ε∈FIRST(Xi​) với mọi i=1,…,ki = 1, \ldots, ki=1,…,k (tức toàn bộ chuỗi có thể sinh ra rỗng) thì thêm eps vào kết quả.

    Quy ước ký hiệu văn phạm (áp dụng cho toàn bộ đề bài này): mỗi luật sinh được cho ở dạng A -> X1 X2 ... Xk (các ký hiệu cách nhau bởi dấu cách); nếu vế phải là rỗng thì ghi A -> eps. Một ký hiệu được coi là ký hiệu chưa kết thúc (non-terminal) nếu và chỉ nếu ký tự đầu tiên của nó là một chữ cái in hoa (A-Z); mọi ký hiệu còn lại (chữ thường, chữ số, dấu (, ), +, id, ... ) đều là ký hiệu kết thúc (terminal). Ký hiệu đặc biệt eps chỉ dùng để biểu diễn xâu rỗng ε\varepsilonε và không phải là một terminal thật sự. Ký hiệu $ là ký hiệu kết thúc xâu vào (end-marker).

    Cho một văn phạm phi ngữ cảnh (đảm bảo mọi ký hiệu chưa kết thúc xuất hiện trong đề đều có ít nhất một luật sinh) và mmm truy vấn, mỗi truy vấn là một chuỗi ký hiệu α\alphaα (không rỗng). Với mỗi truy vấn, hãy tính FIRST(α)\mathrm{FIRST}(\alpha)FIRST(α).

    Ví dụ: Với văn phạm biểu thức

    E -> T E1
    E1 -> + T E1
    E1 -> eps
    T -> F T1
    T1 -> * F T1
    T1 -> eps
    F -> ( E )
    F -> id
    

    truy vấn E1 $ cho kết quả \mathrm{FIRST}(E1\ \) = {+, $}(vıˋ(vì(vıˋE1nullablene^nphảixeˊttie^ˊp‘ nullable nên phải xét tiếp `nullablene^nphảixeˊttie^ˊp‘), in ra là $,+`.

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

      Dòng đầu tiên gồm hai số nguyên nnn và mmm (1≤n≤1001 \le n \le 1001≤n≤100, 1≤m≤501 \le m \le 501≤m≤50) — số luật sinh và số truy vấn. nnn dòng tiếp theo, mỗi dòng một luật sinh dạng A -> X1 X2 ... Xk hoặc A -> eps. mmm dòng tiếp theo, mỗi dòng là một truy vấn: một chuỗi ký hiệu (terminal và/hoặc non-terminal) cách nhau bởi dấu cách.

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

      In ra mmm dòng, dòng thứ iii là FIRST(αi)\mathrm{FIRST}(\alpha_i)FIRST(αi​) của truy vấn thứ iii: liệt kê các phần tử theo thứ tự sắp xếp tăng dần theo từ điển (so sánh chuỗi kiểu ASCII), cách nhau bởi dấu phẩy , (không có khoảng trắng). Nếu ε\varepsilonε thuộc tập kết quả, biểu diễn bằng chuỗi eps và xếp đúng vị trí theo thứ tự từ điển.

    Ví dụ:

    Đầu vào:

    1 1
    A -> a
    A
    

    Đầu ra:

    a
    

    Đầu vào:

    3 2
    A -> B
    B -> C
    C -> eps
    A
    A b
    

    Đầu ra:

    eps
    b
    

    Đang tải editor...