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] Gộp trạng thái LR(1) thành LALR(1) và phát hiện xung đột phát sinh

    Mục LR(1) có dạng [A→α⋅β, a][A \to \alpha \cdot \beta,\ a][A→α⋅β, a] với aaa là một ký hiệu kết thúc (lookahead) cụ thể. Phép closure(I)(I)(I) cho LR(1): với mỗi mục [A→α⋅Bβ, a]∈I[A \to \alpha \cdot B \beta,\ a] \in I[A→α⋅Bβ, a]∈I (BBB là non-terminal), với mỗi luật sinh B→γB \to \gammaB→γ và mỗi b∈FIRST(βa)b \in \mathrm{FIRST}(\beta a)b∈FIRST(βa) (FIRST\mathrm{FIRST}FIRST của chuỗi β\betaβ nối thêm aaa ở cuối), thêm mục [B→⋅γ, b][B \to \cdot \gamma,\ b][B→⋅γ, b]. Phép goto(I,X)(I, X)(I,X) định nghĩa tương tự LR(0) nhưng giữ nguyên lookahead. Họ tập mục chính tắc LR(1) bắt đầu từ \mathrm{closure}(\{[S' \to \cdot S,\ \]})(với(với(vớiG'laˋva˘nphạmmởrộngthe^mlà văn phạm mở rộng thêmlaˋva˘nphạmmởrộngthe^mS' \to S$), xây dựng bằng closure/goto lặp lại như thường lệ.

    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).

    Hai trạng thái LR(1) có cùng lõi (core) nếu bỏ lookahead đi thì tập mục LR(0) tương ứng giống hệt nhau. Phương pháp LALR(1) gộp tất cả các trạng thái LR(1) có cùng lõi thành một trạng thái duy nhất, với tập lookahead của mỗi mục là hợp các tập lookahead từ mọi trạng thái được gộp. Việc gộp có thể làm phát sinh xung đột reduce-reduce mới vốn không tồn tại ở bất kỳ trạng thái LR(1) riêng lẻ nào trước khi gộp: xảy ra khi, tại một ký hiệu kết thúc ttt, sau khi hợp lookahead có từ 2 luật sinh khác nhau trở lên cùng muốn reduce trên ttt trong trạng thái đã gộp, nhưng không có trạng thái LR(1) gốc nào (trước khi gộp) tự nó đã có từ 2 luật sinh muốn reduce trên ttt (nếu đã có sẵn xung đột ở một trạng thái gốc, xung đột đó không phải do gộp gây ra).

    Cho văn phạm phi ngữ cảnh GGG với ký hiệu bắt đầu SSS, hãy tính: (1) số trạng thái sau khi gộp thành LALR(1) (chính là số lõi phân biệt), và (2) số cặp (trạng thái đã gộp, ký hiệu kết thúc ttt) mà tại đó xung đột reduce-reduce chỉ phát sinh do quá trình gộp như mô tả ở trên.

    Ví dụ kinh điển: văn phạm S -> a A d | b B d | a B e | b A e, A -> c, B -> c có 13 trạng thái sau khi gộp, và việc gộp làm phát sinh đúng 2 xung đột reduce-reduce mới (tại ký hiệu d và tại ký hiệu e, trong trạng thái gộp từ hai trạng thái LR(1) ứng với c được đọc sau a và sau b).

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

      Dòng đầu tiên là số nguyên nnn (1≤n≤401 \le n \le 401≤n≤40) — số luật sinh. 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. Dòng cuối cùng là ký hiệu bắt đầu SSS.

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

      In ra hai dòng: dòng thứ nhất là số trạng thái LALR(1) sau khi gộp; dòng thứ hai là số xung đột reduce-reduce phát sinh thuần tuý do quá trình gộp (theo định nghĩa ở đề bài).

    Ví dụ:

    Đầu vào:

    6
    E -> E + T
    E -> T
    T -> T * F
    T -> F
    F -> ( E )
    F -> id
    E
    

    Đầu ra:

    12
    0
    

    Đầu vào:

    1
    S -> a
    S
    

    Đầu ra:

    3
    0
    

    Đang tải editor...