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] Giải quyết xung đột shift-reduce bằng độ ưu tiên toán tử

    Trong thực tế (như công cụ yacc/bison), thay vì viết lại văn phạm để loại bỏ xung đột shift-reduce của các toán tử hai ngôi, người ta thường gán cho mỗi ký hiệu kết thúc (toán tử) một mức ưu tiên (số nguyên, càng lớn càng ưu tiên) và một tính kết hợp (L — trái, R — phải, N — không kết hợp). Mức ưu tiên của một luật sinh được quy ước là mức ưu tiên của ký hiệu kết thúc cuối cùng (phải nhất) xuất hiện ở vế phải của nó; nếu vế phải không chứa ký hiệu kết thúc nào có khai báo ưu tiên, luật sinh được xem là không có ưu tiên xác định.

    Cho một xung đột shift-reduce tại trạng thái sss với ký hiệu nhìn trước aaa (đang muốn dịch chuyển) và luật sinh số ppp (đang muốn rút gọn), quyết định được đưa ra theo quy tắc:

    1. Nếu aaa không có khai báo ưu tiên, hoặc luật sinh ppp không có ưu tiên xác định: mặc định chọn shift (ký hiệu S).
    2. Nếu mức ưu tiên của aaa lớn hơn mức ưu tiên của luật sinh ppp: chọn shift (S).
    3. Nếu mức ưu tiên của aaa nhỏ hơn mức ưu tiên của luật sinh ppp: chọn reduce (R).
    4. Nếu bằng nhau: dùng tính kết hợp của aaa — trái (L) thì chọn reduce (R); phải (R) thì chọn shift (S); không kết hợp (N) thì báo lỗi (E, không hợp lệ về mặt cú pháp).

    Cho bảng ưu tiên/kết hợp của các toán tử, danh sách các luật sinh liên quan (chỉ cần vế phải để xác định ký hiệu kết thúc phải nhất), và danh sách các xung đột shift-reduce cần giải quyết, hãy đưa ra quyết định cho từng xung đột theo đúng thứ tự cho trong đầu vào.

    Ví dụ: + mức 1 trái, * mức 2 trái; luật E -> E + E. Xung đột tại trạng thái 1, ký hiệu +, luật này: cùng mức ưu tiên, + kết hợp trái ⇒\Rightarrow⇒ quyết định R.

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

      Dòng 1: số nguyên ttt — số ký hiệu kết thúc có khai báo ưu tiên. ttt dòng tiếp theo: terminal level assoc (level là số nguyên, assoc ∈{L,R,N}\in \{L, R, N\}∈{L,R,N}). Dòng tiếp theo: số nguyên ppp — số luật sinh được khai báo. ppp dòng tiếp theo: id s1 s2 ... sk với id là số hiệu luật sinh (số nguyên, không nhất thiết liên tục từ 1) và s1…sks_1 \ldots s_ks1​…sk​ là các ký hiệu ở vế phải (chỉ cần liệt kê đủ để xác định ký hiệu kết thúc phải nhất có ưu tiên; ký hiệu chưa kết thúc có thể xuất hiện lẫn trong danh sách và được bỏ qua khi tìm ký hiệu kết thúc). Dòng tiếp theo: số nguyên ccc — số xung đột cần giải quyết. ccc dòng tiếp theo: state terminal prodId — trạng thái, ký hiệu nhìn trước đang xung đột, và số hiệu luật sinh muốn rút gọn.

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

      In ra đúng ccc dòng theo thứ tự cho trong đầu vào, mỗi dòng dạng state terminal decision với decision ∈{S,R,E}\in \{S, R, E\}∈{S,R,E} là quyết định giải quyết xung đột tương ứng.

    Ví dụ:

    Đầu vào:

    1
    < 1 N
    1
    1 E < E
    1
    1 < 1

    Đầu ra:

    1 < E
    

    Đầu vào:

    5
    + 1 L
    - 1 L
    * 2 L
    / 2 L
    ^ 3 R
    7
    1 E + E
    2 E - E
    3 E * E
    4 E / E
    5 E ^ E
    6 ( E )
    7 id
    5
    1 + 1
    2 * 1
    3 + 3
    4 ^ 5
    5 ) 7

    Đầu ra:

    1 + R
    2 * S
    3 + R
    4 ^ S
    5 ) S
    

    Đang tải editor...