1 CHƢƠNG III Phân tích cú pháp Mục tiêu: -Nắm đƣợc vai trò của giai đoạn phân tích cú pháp - Văn phạm phi ngữ cảnh (context- free grammar),cách phân tích cú pháp từ dƣới lên- từ trên xuống (top-down and bottom-up parsing) -Bộ phân tích cú pháp LR CuuDuongThanCong.com https://fb.com/tailieudientucntt
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
1
CHƢƠNG IIIPhân tích cú pháp
Mục tiêu:
-Nắm đƣợc vai trò của giai đoạn phân tích cú pháp
- Văn phạm phi ngữ cảnh (context- free grammar),cách phân tích cú pháp từ dƣới lên- từ trên xuống (top-down and bottom-up parsing)
• Các phƣơng pháp phân tích cú pháp (PTCP) chia làm hai loại: Phân tích từ trên xuống (top- down parsing) và phân tích từ dƣới lên (bottom- up parsing)
• Trong quá trình biên dịch xuất hiện nhiều lỗi trong giai đoạn PTCP do đó bộ phân tích cú pháp phải phát hiện và thông báo lỗi chính xác cho ngƣời lập trình đồng thơi không làm chậm những chƣơng trình đƣợc viết đúng
w, w đƣợc gọi là một câu (sentence) của văn phạm G
• Một ngôn ngữ đƣợc sinh bởi văn phạm phi ngữ cảnh đƣợc gọi là ngôn ngữ phi ngữ cảnh (context- free language)
• Hai văn phạm đƣợc gọi là tƣơng đƣơng nếu sinh ra cùng một ngôn ngữ
• Nếu S * ( có thể chứa kí hiệu chƣa kết thúc) thí ta nói là một dạng câu (sentence form) của G. Một câu là một dạng câu không chứa kí hiệu chƣa kết thúcCuuDuongThanCong.com https://fb.com/tailieudientucntt
Ví dụ 3.2: Xâu –(id+id) là một câu của văn phạm trong ví dụ 3.1 vì
E -E -(E) -(E+E) -(id+E) (id+id)
• Một dẫn xuất đƣợc gọi là trái nhất (leftmost) nếu tại mỗi bƣớc kí hiệu chƣa kết thúc ngoài cùng bên trái đƣợc thay thế, kí hiệu lm. Nếu S *lm thì đƣợc gọi là dạng câu trái
• Tƣơng tự ta có dẫn xuất phải nhất (rightmost) hay còn gọi là dẫn xuất chính tắc, kí hiệu rm
• Tính mơ hồ của văn phạm (ambiguity): Một văn phạm sinh ra nhiều hơn một parse tree cho một câu đƣợc gọi là văn phạm mơ hồ. Nói cách khác một văn phạm mơ hồ sẽ sinh ra nhiều hơn một dẫn xuất trái nhất hoặc dẫn xuất phải nhất cho cùng một câu.
• Loại bỏ sự mơ hồ của văn phạm: Ta xét ví dụ văn phạm sau
• Ðể loại bỏ sự mơ hồ này ta đƣa ra qui tắc "Khớp mỗi else với một then chƣa khớp gần nhất trƣớc đó". Với qui tắc này, ta viết lại văn phạm trên nhƣ sau :
• Loại bỏ đệ qui trái: Một văn phạm đƣợc gọi là đệ qui trái (left recursion) nếu tồn tại một dẫn xuất có dạng A + A (A là 1 kí hiệu chƣa kết thúc, là một xâu).
• Các phƣơng pháp phân tích từ trên xuống không thể xử lí văn phạm đệ qui trái, do đó cần phải biến đổi văn phạm để loại bỏ các đệ qui trái
• Ðệ qui trái có hai loại :
Loại trực tiếp: Có dạng A + A
Loại gián tiếp: Gây ra do dẫn xuất của hai hoặc nhiều bƣớc CuuDuongThanCong.com https://fb.com/tailieudientucntt
• Tạo ra nhân tố trái (left factoring) là một phép biến đổi văn phạm rất có ích để có đƣợc một văn phạm thuận tiện cho việc phân tích dự đoán
• Ý tƣởng cơ bản là khi không rõ luật sinh nào trong hai luật sinh khả triển có thể dùng để khai triển một ký hiệu chƣa kết thúc A, chúng ta có thể viết lại các A- luật sinh nhằm "hoãn" lại việc quyết định cho đến khi thấy đủ yếu tố cho một lựa chọn đúng.
• Phân tích cú pháp (PTCP) từ trên xuống đƣợc xem nhƣ một cố gắng tìm kiếm một dẫn xuất trái nhất cho chuỗi nhập. Nó cũng có thể xem nhƣ một cố gắng xây dựng cây phân tích cú pháp bắt đầu từ nút gốc và phát sinh dần xuống lá
• PTCP từ trên xuống đơn giản hơn PTCP từ dƣới lên nhƣng bị giới hạn về mặt hiệu quả
• Có một số kĩ thuật PTCP từ trên xuống nhƣ: PTCP đệ qui lùi, PTCP đoán trƣớc, PTCP đoán trƣớc đệ qui. Ta sẽ xét trƣờng
• Predictive parsing program hoạt động nhƣ sau: Chƣơng trình xét ký hiệu X trên đỉnh Stack và ký hiệu nhập hiện hành a
1. Nếu X = a = $ thì quá trình PTCP kết thúc thành công
2. Nếu X = a $, đẩy X ra khỏi Stack và đọc ký hiệu nhập tiếp theo.
3. Nếu X là ký hiệu chƣa kết thúc thì chƣơng trình truy xuất đến phần tử M[X,a] trong Parsing table M:
- Nếu M[X,a] là một luật sinh có dạng X UYV thì đẩy X ra khỏi đỉnh Stack và đẩy V, Y, U vào Stack (với U trên đỉnh Stack), đồng thời bộ xuất ra OUTPUT luật sinh X UYV
- Nếu M[X,a] = error, gọi chƣơng trình phục hồi lỗi.
• Hàm FIRST và FOLLOW: Là các hàm xác định các tập hợp cho phép xây dựng bảng phân tích M và phục hồi lỗi
• Nếu là một xâu thì FIRST( ) là tập hợp các ký hiệu kết thúc mà nó bắt đầu một chuỗi dẫn xuất từ . Nếu * thì thuộc FIRST( )
• Nếu A là một kí hiệu chƣa kết thúc thì FOLLOW(A) là tập các kí hiệu kết thúc mà nó xuất hiện ngay bên phải A trong một dạng câu . Nếu S * A thì $ thuộc FOLLOW(A)
• Giới thiệu một kiểu phân tích cú pháp từ dƣới lên tổng quát gọi là phân tích cú pháp Shift –Reduce
• Một phƣơng pháp tổng quát hơn của kỹ thuật Shift - Reduce là phân tích cú pháp LR (LR parsing) sẽ đƣợc thảo luận
• Shift –Reduce parsing sẽ cố gắng xây dựng một parse tree cho một xâu nhập vào từ nút lá lên nút gốc. Nói cách khác ta "reducing" từng bƣớc xâu nhập vào đến khi thu đƣợc kí hiệu bắt đầu của văn phạm
Với cùng một biểu thức id+id*id sẽ có hai dẫn xuất phải nhất (các handle đƣợc gạch chân). Cùng một right sentence form E+E*id3 trong trƣờng hợp đầu id3 là handle còn trƣờng hợp thứ 2 handle là E+E
• Cấu hình (configuration) của một bộ phân tích cú pháp LR là một cặp thành phần(s0 X1 s1 X2 s2... Xm sm, ai ai+1 ... an $). Cấu hình biểu diễn right- sentential form X1 X2... Xmai ai+1 ... an
• Sự thay đổi cấu hình theo hàm action nhƣ sau:
- Nếu action[sm, ai] = shift s, cấu hình chuyển thành
(s0 X1 s1 X2 s2... Xm sm ai s, ai+1 ... an $), trong đó
s=action[sm, ai]
- Nếu action[sm, ai] = reduce A , cấu hình chuyển thành
(s X s X s ... X s A s, a a ... a $), trong đó CuuDuongThanCong.com https://fb.com/tailieudientucntt
• Có 3 phƣơng pháp xây dựng một bảng phân tích cú pháp LR từ văn phạm là Simple LR (SLR), Canonical LR và Lookahead- LR (LALR), các phƣơng pháp khác nhau về tính hiệu quả cũng nhƣ tính dễ cài đặt
• Phƣơng pháp SLR, là phƣơng pháp yếu nhất nếu tính theo số lƣợng văn phạm có thể xây dựng thành công, nhƣng đây lại là phƣơng pháp dễ cài đặt nhất
• Một văn phạm có thể xây dựng đƣợc SLR parser đƣợc gọi là một văn phạm SLR
• Văn phạm tăng cƣờng (Augmented Grammar): G là một văn phạm với ký hiệu bắt đầu S, thêm một ký hiệu bắt đầu mới S'
và luật sinh S' S để đƣợc văn phạm mới
G' gọi là văn phạm tăng cƣờng
• Phép toán bao đóng (Closure): Giả sử I là một tập các mục của văn phạm G thì bao đóng closure(I) là tập các mục đƣợc xây dựng từ I nhƣ sau:
1. Tất cả các mục của I đƣợc thêm vào closure(I).
2. Nếu A .B closure(I) và B là một luật sinh thì thêm B . vào closure(I) nếu nó chƣa có trong đó. Lặp lại bƣớc này cho đến khi không thể thêm vào closure(I) đƣợc nữa
1. Xây dựng họ tập hợp các mục của G': C = { I0, I1, ..., In }
2. Trạng thái i đƣợc xây dựng từ Ii .Các action tƣơng ứng trạng thái i xác định nhƣ sau:
a) Nếu A .a Ii và goto (Ii, a) = Ij thì action[i, a] = "shift j",
a là ký hiệu kết thúc
b) Nếu A . Ii thì action[i, a] = "reduce (A )", với mọi a FOLLOW(A), A S'
c) Nếu S' S · Ii thì action[i, $] = "accept".
Nếu một action đụng độ đƣợc sinh ra bởi các luật trên, ta nói văn phạm không phải là SLR(1). Giải thuật thất bạiCuuDuongThanCong.com https://fb.com/tailieudientucntt
• Phép toán bao đóng (Closure): Giả sử I là một tập các mục LR(1) của văn phạm G thì bao đóng closure(I) là tập các mục đƣợc xây dựng từ I nhƣ sau:
1. Tất cả các mục của I đƣợc thêm vào closure(I).
2. Nếu [A .B , a] closure(I), B là một luật sinh và b FIRST( a) thì thêm [B . , b]vào closure(I) nếu nó chƣa có trong đó. Lặp lại bƣớc này cho đến khi không thể thêm vào closure(I) đƣợc nữa
• Phép toán goto: Nếu I là một tập các mục và X là một ký hiệu văn phạm thì goto(I, X) là bao đóng của tập hợp các mục [A
• LALR là phƣơng pháp canonical parsing trong đó các trạng thái đƣợc nhóm lại với nhau nhờ đó bảng phân tich cấu trúc có kích thƣớc nhỏ hơn (có thể so sánh với SLR)
• Hạt nhân (core) của một tập hợp mục LR(1) có dạng {[A . , a]}, trong đó A là một luật sinh và a là ký hiệu kết thúc có hạt nhân (core) là tập hợp {A . }.
• Trong họ tập hợp các mục LR(1) C = {I0, I1,..., In} có thể có các tập hợp các mục có chung một hạt nhân.
1. Xây dựng họ tập hợp các mục LR(1) của G': C = {I0, I1,.., In }
2. Nhóm các mục có cùng core trong C đƣợc C' = {J0, J1,.., Jm }
3. Trạng thái i đƣợc xây dựng từ Ji .Các action tƣơng ứng trạng thái i xác định tƣơng tự nhƣ canonical LR
Nếu một action đụng độ đƣợc sinh ra bởi các luật trên, ta nói văn phạm không phải là LALR(1). Giải thuật thất bại
3. Xây dựng bảng goto : Giả sử J = I1 I2 . Ik . Vì I1, I2, ... Ik có chung hạt nhân nên goto (I1,X), goto (I2,X), ..., goto (Ik,X) cũng có chung hạt nhân.
Ðặt K bằng hợp tất cả các tập hợp có chung hạt CuuDuongThanCong.com https://fb.com/tailieudientucntt
• Giống nhƣ Lex, Yacc (yet another compiler compiler) là câu lệnh sẵn có của UNIX và là một công cụ hữu hiệu cho phép xây dựng bộ phân tích cú pháp một cách tự động
• Yacc đƣợc tạo bởi S. C. Johnson vào những năm đầu của thập kỉ 70