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] Đếm xung đột FIRST/FIRST và FIRST/FOLLOW

    Cho một văn phạm phi ngữ cảnh (CFG) với ký hiệu bắt đầu SSS (không đảm bảo là LL(1)).

    Quy ước biểu diễn văn phạm phi ngữ cảnh (CFG) dùng chung cho đề này:

    • Mỗi ký hiệu chưa kết thúc (non-terminal) là một chữ cái in hoa (A-Z).
    • Mọi token khác (chữ thường, số, hoặc ký hiệu như (, ), +, *, id, num, ...) là ký hiệu kết thúc (terminal); terminal có thể dài nhiều ký tự nhưng không chứa khoảng trắng.
    • Token đặc biệt e ở vế phải nghĩa là luật sinh sinh ra chuỗi rỗng ε\varepsilonε (ví dụ A -> e).
    • Ký hiệu kết thúc đầu vào (end-of-input) được ký hiệu là $ khi cần dùng tới FOLLOW.
    • Đảm bảo mọi ký hiệu chưa kết thúc xuất hiện ở vế phải của bất kỳ luật sinh nào cũng đều có ít nhất một luật sinh định nghĩa nó (văn phạm "đóng", không có non-terminal mồ côi).

    Với mỗi ký hiệu chưa kết thúc AAA có các luật sinh A→α1,…,A→αmA \to \alpha_1, \ldots, A \to \alpha_mA→α1​,…,A→αm​ (m≥2m \ge 2m≥2), xét mọi cặp chỉ số i<ji<ji<j. Gọi SELECT(A→αi)=FIRST(αi)∖{ε}SELECT(A \to \alpha_i) = FIRST(\alpha_i)\setminus\{\varepsilon\}SELECT(A→αi​)=FIRST(αi​)∖{ε}, cộng thêm FOLLOW(A)FOLLOW(A)FOLLOW(A) nếu ε∈FIRST(αi)\varepsilon \in FIRST(\alpha_i)ε∈FIRST(αi​). Nếu SELECT(A→αi)∩SELECT(A→αj)≠∅SELECT(A\to\alpha_i) \cap SELECT(A\to\alpha_j) \neq \emptysetSELECT(A→αi​)∩SELECT(A→αj​)=∅ thì cặp luật sinh này xung đột. Phân loại xung đột đó thành 2 nhóm:

    • FIRST/FIRST: nếu (FIRST(αi)∖{ε})∩(FIRST(αj)∖{ε})≠∅(FIRST(\alpha_i)\setminus\{\varepsilon\}) \cap (FIRST(\alpha_j)\setminus\{\varepsilon\}) \neq \emptyset(FIRST(αi​)∖{ε})∩(FIRST(αj​)∖{ε})=∅ (hai luật sinh có ký hiệu bắt đầu terminal trùng nhau thật sự).
    • FIRST/FOLLOW: nếu không thuộc trường hợp trên (xung đột chỉ phát sinh do một trong hai luật sinh có thể sinh ε\varepsilonε và phần giao nằm trong FOLLOW(A)FOLLOW(A)FOLLOW(A)).

    Hãy đếm tổng số cặp luật sinh xung đột trên toàn bộ văn phạm, tách riêng theo 2 loại trên (mỗi cặp (i,j)(i,j)(i,j) chỉ thuộc đúng một trong hai loại).

    Ví dụ

    Với văn phạm S -> F, F -> id, F -> id, F -> num: cặp (luật sinh 1, luật sinh 2) của FFF (hai lần id) xung đột kiểu FIRST/FIRST; cặp còn lại với num không xung đột. Kết quả: 1 0.

    • Định dạng đầu vào:
      • Dòng 1: ký hiệu bắt đầu SSS.
      • Dòng 2: số luật sinh nnn (1≤n≤301 \le n \le 301≤n≤30).
      • nnn dòng luật sinh dạng A -> X1 X2 ... Xk hoặc A -> e.

      Quy ước biểu diễn văn phạm phi ngữ cảnh (CFG) dùng chung cho đề này:

      • Mỗi ký hiệu chưa kết thúc (non-terminal) là một chữ cái in hoa (A-Z).
      • Mọi token khác (chữ thường, số, hoặc ký hiệu như (, ), +, *, id, num, ...) là ký hiệu kết thúc (terminal); terminal có thể dài nhiều ký tự nhưng không chứa khoảng trắng.
      • Token đặc biệt e ở vế phải nghĩa là luật sinh sinh ra chuỗi rỗng ε\varepsilonε (ví dụ A -> e).
      • Ký hiệu kết thúc đầu vào (end-of-input) được ký hiệu là $ khi cần dùng tới FOLLOW.
      • Đảm bảo mọi ký hiệu chưa kết thúc xuất hiện ở vế phải của bất kỳ luật sinh nào cũng đều có ít nhất một luật sinh định nghĩa nó (văn phạm "đóng", không có non-terminal mồ côi).
    • Định dạng đầu ra:

      In ra đúng một dòng gồm 2 số nguyên cách nhau bởi một khoảng trắng: số cặp luật sinh xung đột loại FIRST/FIRST, và số cặp luật sinh xung đột loại FIRST/FOLLOW (theo định nghĩa nêu trên).

    Ví dụ:

    Đầu vào:

    S
    3
    S -> A a
    A -> a
    A -> e

    Đầu ra:

    0 1
    

    Đầu vào:

    E
    8
    E -> T X
    X -> + T X
    X -> e
    T -> F Y
    Y -> * F Y
    Y -> e
    F -> ( E )
    F -> id

    Đầu ra:

    0 0
    

    Đang tải editor...