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 và báo cáo xung đột trong bảng LL(1)

    Khi xây dựng bảng phân tích LL(1)LL(1)LL(1) M[A,a]M[A, a]M[A,a] từ các tập SELECT\text{SELECT}SELECT (xem định nghĩa SELECT(A→α)=(FIRST(α)∖{ε})∪FOLLOW(A) [ε∈FIRST(α)]\text{SELECT}(A \to \alpha) = (\text{FIRST}(\alpha)\setminus\{\varepsilon\}) \cup \text{FOLLOW}(A)\,[\varepsilon \in \text{FIRST}(\alpha)]SELECT(A→α)=(FIRST(α)∖{ε})∪FOLLOW(A)[ε∈FIRST(α)]), một Ô M[A,a]M[A, a]M[A,a] được gọi là XUNG ĐỘT (conflict) nếu có TỪ HAI luật sinh A→αiA \to \alpha_iA→αi​ trở lên cùng thỏa a∈SELECT(A→αi)a \in \text{SELECT}(A \to \alpha_i)a∈SELECT(A→αi​) — khi đó bộ phân tích không thể quyết định dùng luật sinh nào chỉ dựa vào kí hiệu tra trước aaa, và văn phạm không phải LL(1)LL(1)LL(1).

    Cho văn phạm GGG gồm nnn luật sinh được đánh số 1,…,n1,\dots,n1,…,n theo thứ tự trong input, hãy tìm TẤT CẢ các ô xung đột của bảng LL(1)LL(1)LL(1): với mỗi kí hiệu chưa kết thúc AAA và kí hiệu kết thúc aaa (kể cả $) sao cho ô M[A,a]M[A,a]M[A,a] có từ 2 luật sinh trở lên, báo cáo cặp (A,a)(A, a)(A,a) cùng danh sách CHỈ SỐ (1-based, theo thứ tự input) của các luật sinh gây xung đột tại đó.

    Ví dụ: với văn phạm dangling-else

    S -> if E then S S1
    S1 -> else S
    S1 -> eps
    E -> id
    

    ô M[S1,else]M[S1, else]M[S1,else] có cả luật sinh 2 (S1→else SS1 \to \text{else } SS1→else S, vì else ∈FIRST\in \text{FIRST}∈FIRST của vế phải) và luật sinh 3 (S1→εS1 \to \varepsilonS1→ε, vì else ∈FOLLOW(S1)\in \text{FOLLOW}(S1)∈FOLLOW(S1)) — đây là xung đột duy nhất.

    • Định dạng đầu vào:
      • Dòng đầu tiên chứa số nguyên nnn (1≤n≤2001 \le n \le 2001≤n≤200) — số luật sinh (production) của văn phạm.
      • nnn dòng tiếp theo, mỗi dòng có dạng A -> X1 X2 ... Xk (giữa A và ->, giữa -> và X1X_1X1​, giữa các XiX_iXi​ luôn có khoảng trắng); AAA là kí hiệu ở vế trái, X1,…,XkX_1,\dots,X_kX1​,…,Xk​ là các kí hiệu ở vế phải. Nếu vế phải là chuỗi rỗng ε\varepsilonε, dòng có dạng A -> eps (đúng một kí hiệu eps).
      • Một kí hiệu là kí hiệu CHƯA KẾT THÚC (nonterminal) nếu nó xuất hiện ở vế trái của ít nhất một trong nnn luật sinh; mọi kí hiệu khác xuất hiện trong văn phạm (khác eps) là kí hiệu KẾT THÚC (terminal). Kí hiệu bắt đầu (start symbol) của văn phạm là vế trái của luật sinh ở dòng đầu tiên (dòng thứ hai của input). Có thể có nhiều luật sinh cùng vế trái, nằm ở các dòng khác nhau, không nhất thiết liền kề.
      • Kí hiệu kết thúc chuỗi vào (end-of-input marker), dùng khi tính FOLLOW, được kí hiệu là $.
    • Định dạng đầu ra:

      Nếu văn phạm KHÔNG có ô xung đột nào (là LL(1)LL(1)LL(1)), in ra đúng một dòng LL(1). Ngược lại, dòng đầu tiên in số nguyên CCC — tổng số ô xung đột. CCC dòng tiếp theo, mỗi dòng ứng với một ô xung đột, có dạng A a: i1 i2 ... trong đó AAA là kí hiệu chưa kết thúc, aaa là kí hiệu kết thúc (hoặc $) gây xung đột, và i1<i2<…i_1 < i_2 < \dotsi1​<i2​<… là chỉ số (tăng dần) của các luật sinh xung đột tại ô đó, cách nhau đúng một khoảng trắng. Các dòng xung đột được sắp xếp tăng dần trước hết theo tên AAA (thứ tự từ điển), sau đó theo aaa (thứ tự từ điển, riêng $ luôn xếp SAU cùng mọi kí hiệu kết thúc khác của cùng một AAA).

    Ví dụ:

    Đầu vào:

    4
    S -> if E then S S1
    S1 -> else S
    S1 -> eps
    E -> id

    Đầu ra:

    1
    S1 else: 2 3
    

    Đầu vào:

    4
    E -> T X
    X -> + T X
    X -> eps
    T -> id

    Đầu ra:

    LL(1)
    

    Đang tải editor...