Chapter 4 - WordPress.com

Download Report

Transcript Chapter 4 - WordPress.com

CHƯƠNG 4
PHÂN TÍCH CÚ PHÁP
1
Vai trò của bộ phân tích cú pháp
2
Vai trò của bộ phân tích cú pháp
Bộ phân tích cú pháp nhận chuổi các token từ bộ
phân tích từ vựng để tạo ra cấu trúc cú pháp của
chương trình nguồn.
 Tồn tại ba loại bộ phân tích cú pháp:
 Phương pháp tổng quát:

•
•
Cocke-Younger-Kasami.
Earley.
 Phương pháp thông dụng: Phân tích từ trên xuống
hay phân tích từ dưới lên.
3
Xây dựng văn phạm cho ngôn
ngữ lập trình
Loại bỏ sự không tường minh
Ví dụ: Cho văn phạm sau
stmt -> if exp then stmt
| if exp then stmt else stmt
| other
Ta thấy văn phạm này không tường minh khi phân
tích phát biểu:
if E1then if E2 then S1 else S2
vì tồn tại hai cây cú pháp cho phát biểu.

4
Xây dựng văn phạm cho ngôn
ngữ lập trình
5
Xây dựng văn phạm cho ngôn
ngữ lập trình
6
Xây dựng văn phạm cho ngôn
ngữ lập trình
Loại bỏ sự không tường minh bằng cách sửa lại
văn phạm bằng cách: Khớp mỗi else với một then
chưa khớp gần nhất trước đó.
stmt -> matched-stmt | unmatched-stmt
matched-stmt-> if exp then matched-stmt else
matched-stmt | other
unmatched-stmt -> if exp then stmt
|if exp then matched-stmt else
unmatched-stmt

7
Xây dựng văn phạm cho ngôn
ngữ lập trình



Loại bỏ đệ quy trái:
Một văn phạm là đệ qui trái (left recursive) nếu nó
có một ký hiệu chưa kết thúc A sao cho có một dẫn
xuất ,
với α là một chuỗi nào đó.
Các phương pháp phân tích từ trên xuống không
thể nào xử lý văn phạm đệ qui trái, do đó cần phải
dùng một cơ chế biến đổi tương đương để loại bỏ
các đệ qui trái.
8
Xây dựng văn phạm cho ngôn
ngữ lập trình
9
Xây dựng văn phạm cho ngôn
ngữ lập trình
10
Xây dựng văn phạm cho ngôn
ngữ lập trình

Thí dụ 4.1: Loại bỏ đệ quy trái cho văn phạm:
E -> E + T | T
T -> T * F | F
F -> (E) | id
11
Xây dựng văn phạm cho ngôn
ngữ lập trình

Giải thuật 4.1: Loại bỏ đệ quy trái
Nhập: Văn phạm G không có vòng lặp hoặc luật
sinh rỗng.
Xuất: Văn phạm tương đương G’ không có đệ quy
trái.
Phương pháp: G’ không còn đệ quy trái nhưng có
thể có luật sinh rỗng.
12
Xây dựng văn phạm cho ngôn
ngữ lập trình
13
Xây dựng văn phạm cho ngôn
ngữ lập trình

Thí dụ: Chúng ta có áp dụng giải thuật 4.1 vào văn
phạm sau để loại bỏ đệ quy trái.
S ->Aa | b
A -> Ac | Sd | 
14
Thừa số trái


Thí dụ: Ta có hai luật sinh:
stmt -> if exp then stmt else stmt
| if exp then stmt
Cả hai luật sinh đều có if dẫn đầu nên ta sẽ không
biết chọn luật sinh nào để triển khai. Vì thế để làm
chậm lại quyết định lựa chọn chúng ta sẽ tạo ra
thừa số trái.
15
Tạo văn phạm có thừa số trái
Nhập: Cho văn phạm G.
Xuất: Văn phạm G’ có thừa số trái tương đương.
Phương pháp: Tìm chuỗi dẫn đầu chung của các vế
phải luật sinh, thí dụ:
 là chuỗi không bắt đầu bởi . Ta thay các luật
trên bằng các luật
A -> A’ | 
A’-> 1 | 2 | 3 … | n
16
Thừa số trái


Thí dụ: Cho văn phạm như sau
S -> iEtS | iEtSeS | a
E -> b
Áp dụng giải thuật trên cho văn phạm phát biểu if,
ta có văn phạm yếu tố trái như sau.
S -> iEtSS’ | a
S’-> eS | 
E -> b
17
Phân tích cú pháp từ trên xuống


Phân tích cú pháp đệ quy.
Phân tích cú pháp không đệ quy.
18
Phân tích cú pháp đệ quy đi xuống


Thí dụ: Cho văn phạm G:
S -> cAd
A -> ab | a
Các bước phân tích cú pháp từ trên xuống:
19
Phân tích cú pháp đệ quy đi xuống
20
Phân tích cú pháp đoán
nhận trước đệ quy







Hãy loại bỏ đệ quy trái cho văn phạm mà chúng ta thiết kế.
Hãy tạo văn phạm có thừa số trái nếu cần thiết.
Sơ đồ dịch cho bộ phân tích đoán nhận trước.
Sơ đồ này có đặc điểm như sau:
Mỗi ký hiệu không kết thúc có một sơ đồ.
Tên các cạnh là token và các ký hiệu không kết thúc.
Sự truyền trên token sẽ được thực hiện nếu ký hiệu nhập
trùng với token đó.
Nếu có sự truyền trên ký hiệu không kết thúcA thì ta thực
hiện một lệnh gọi thủ tục A.
21
Phân tích cú pháp đoán
nhận trước đệ quy



Để xây dựng sơ đồ chúng ta sẽ tiến hành các bước
sau đây:
Tạo trạng thái bắt đầu và kết thúc.
Với mỗi luật sinh có dạng:
A -> X1X2…Xn ta xây dựng đường đi từ trạng
thái bắt đầu đến trạng thái kết thúc sao cho các
cạnh có tên X1, X2, X3…Xn.
22
Phân tích cú pháp đoán
nhận trước đệ quy
Thí dụ 4.3: Chúng ta hãy tạo sơ đồ dịch cho văn phạm G
E→E+T|T
T→T*F|F
F → (E) | id


Loại bỏ đệ quy trái trong văn phạm, ta được văn phạm
tương đương sau :
E -> TE’
E’-> + TE’| 
T -> FT’
T’-> *FT’| 
F -> (E) | id
Sơ đồ dịch của các ký hiệu không kết thúc của G
23
Sơ đồ dịch của các ký hiệu
không kết thúc của G
24
Sơ đồ dịch của các ký hiệu
không kết thúc của G
25
Sơ đồ dịch của các ký hiệu không kết
thúc của G, đã được thu giảm
26
Giải thuật
27
Giải thuật
28
Phân tích cú pháp đoán nhận
trước không đệ quy

Cấu tạo của bộ phân tích cú pháp:
29
Hoạt động của bộ phân tích




Ở trạng thái bắt đầu, stack chỉ chứa các ký hiệu
mục tiêu của văn phạm nằm trên $, trên đỉnh stack.
Bảng phân tích M là ma trận. Hai ký hiệu X và a sẽ
xác định hành vi của bộ phân tích. Bộ phân tích có
ba hành vi như sau:
Nếu X = a = $ bộ phân tích dừng và báo thành
công.
Nếu X = a <> $ bộ phân tích sẽ đẫy X ra khỏi
Stack dịch đầu đọc đến ký hiệu nhập kế tiếp.
Nếu X là ký hiệu không kết thúc bộ phân tích sẽ
xét bảng ma trận để tìm luật sinh hoặt lỗi.
30
Giải thuật



Nhập: Chuỗi nhập w và bảng phân tích M cho văn
phạm G.
Xuất: Nếu w thuộc L(G), sẽ tạo ra dẫn xuất trái của
w, ngược lại sẽ báo lỗi.
Phương pháp: Lúc đầu cấu hình của bộ phân tích là
($S, w$) với S là ký hiệu mục tiêu của G. Đặt ip (là
con trỏ hoặc còn gọi là đầu đọc của bộ phân tích)
vào ký hiệu nhập đầu tiên của w$.
31
Giải thuật
32
Phân tích cú pháp đoán nhận
trước không đệ quy
Thí dụ 4.4: Giả sử chúng ta có văn phạm G.
E -> E + T | T
T -> T *F | F
F -> (E) | id
Chúng ta sẽ thực hiện loại bỏ đệ quy trái, nhận được G’:
E -> TE’
E’-> +TE’ | 
T -> FT’
T’ ->*FT’| 
F -> (E) | id

33
Phân tích cú pháp đoán nhận
trước không đệ quy
Bây giờ chúng ta sẽ phân tích cú pháp cho câu nhập w
= id + id * id bằng bảng phân tích M cho trước.
34
Các bước phân tích cú pháp câu
id + id *id
35
Xây dựng bảng phân tích M






first() là tập c ký hiệu kết thúc a, dẫn đầu các chuỗi được
dẫn xuất từ ,  ->a. Nếu  ->  thì  thuộc first ().
follow(A) là tập các ký hiệu kết thúc a, xuất hiện ngay bên
phải A trong dạng câu.
Các quy tắc tính first(X) với X là ký hiệu văn phạm:
Nếu X là ký hiệu kết thúc thì first(X) = {X}
Nếu X->  là luật sinh thì ta thêm  vào first(X)
Nếu X là ký hiệu không kết thúc và X ->X1X2X3..Xn là
luật sinh thì cho a vào first(X) nếu với i thì a thuộc first(Xi)
và ký hiệu  ở trong tất cả first(X1) …first(Xi-1)
36
Xây dựng bảng phân tích M




Các quy tắc tính follow(A) cho tất cả các ký hiệu
không kết thúc A.
Cho ký hiệu $ vào follow(S), S là ký hiệu mục
tiêu, $ là ký hiệu kết thúc chuổi nhập.
Tồn tại luật A-> B, tất cả các ký hiệu thuộc
first() sẽ cho vào follow(B) trừ .
Tồn tại luật A-> B hoặc A-> B mà first() =
{} thì tất cả các ký hiệu follow(A) sẽ cho vào
follow(B).
37
Xây dựng bảng phân tích M


Thí dụ 4.5: Cho văn phạm G.
E -> TE’
E’-> +TE’ | 
T -> FT’
T’ ->*FT’| 
F -> (E) | id
Toàn bộ các hàm first và follow của các ký hiệu văn phạm
của G:
first(E) = first(T) = first(F) = {(, id}
first(E’) = {+, }; first(T’) = {*, }
follow(E) = follow(E’) = {$, )}
follow(T) = follow(T’) = {+, $, )}
follow(F) = {*, +, $, )}
38
Xây dựng bảng phân tích M







Nhập: Văn phạm G.
Xuất: Bảng phân tích M.
Phương pháp:
Với mỗi luật sinh A ->  hãy thực thi bước 2 và 3.
Với mỗi ký hiệu kết thúc a thuộc first(), thêm
A ->  vào M[A, a].
Nếu ký hiệu  thuộc first(), thêm A ->  vào
M[A, b] sao cho b thuộc follow(A). Nếu $ thuộc
follow(A) thì thêm A ->  vào M [A, $].
Những phần tử của bảng M trống, hãy đánh dấu
lỗi.
39
Văn phạm LL(1)

Thí dụ 4.7: Cho văn phạm G.
S -> iEtSS’ | a
S’-> eS’ | 
E -> b
first(S) = {i,a}, first(S’) = {e,}, first(E) = {b}
follow(S) = {e,$}, follow(S’) = {e,$}, follow(E) =
{t}
40
Bảng phân tích M cho thí dụ
41
Bảng phân tích M cho thí dụ


Nguyên nhân vì e vừa thuộc first(S’) = {e,} vừa
thuộc follow(S’) = {e,$}.
Văn phạm không có phần tử nào của bảng phân
tích M có nhiều hơn một trị thì được gọi là văn
phạm LL(1).
42
Khắc phục lỗi trong phân tích cú
pháp đoán nhận trước


Lỗi xuất hiện trong các trường hợp sau: Một là ký
hiệu kết thúc trên stack không trùng với ký hiệu
nhập đang được đọc. Hai là A là ký hiệu không kết
thúc trên đỉnh stack, a trên chuỗi nhập, được đọc,
mà M[A, a] là trống.
Một số heuristics được áp dụng cho việc khắc phục
lỗi.
43
Khắc phục lỗi trong phân tích cú
pháp đoán nhận trước


Ta cho tất cả các ký hiệu trong follow(A) vào tập
token đồng bộ của A. Chúng ta làm như vậy cho
mỗi ký hiệu không kết thúc A.
Khi phân tích cú pháp có xuất hiện lỗi, chúng ta sẽ
bỏ qua các ký hiệu kết thúc trên chuổi nhập cho
đến khi xuất hiện token trên chuổi nhập, thuộc
follow(A) thì ta loại A ra khỏi stack.
Khi phân tích cú pháp có xuất hiện lỗi, và A ở trên
stack thì bộ phân tích sẽ loại bỏ các ký hiệu nhập
cho đến khi xuất hiện token trên chuổi nhập, thuộc
first(A)
44
Khắc phục lỗi trong phân tích cú
pháp đoán nhận trước

Thí dụ 4.8: Cho văn phạm
45
Phân tích M có ký hiệu khắc phục lỗi
46
Phân tích M có ký hiệu khắc phục lỗi
47
Thí dụ
48
Thí dụ

Phân tích và khắc phục lỗi cho chuỗi nhập:
W = )id*+id
49
Phân tích cú pháp từ dưới lên


Phân tích cú pháp từ dưới lên được hiểu là phân
tích đẩy và thu giảm (Shift-Reduce parsing) là
phương pháp phân tích LR (L có nghĩa là bộ phân
tích sẽ đọc ký hiệu nhập từ trái sang, R có nghĩa là
bộ phân tích sẽ tạo ra dẫn xuất phải ngược) .
Thí dụ 4.9. Cho văn phạm G.
S ->aABe
A ->Abc|b
B ->d
Phân tích câu w = abbcde.
50
Phân tích cú pháp từ dưới lên


Tóm tắt các bước thu giảm như sau:
Quá trình thu giảm nếu theo chiều ngược lại thì đó
chính là quá trình dẫn xuất phải.
Quá trình này đã sinh cây cú pháp của câu phân
tích từ dưới lên.
51
Thí dụ
52
Thí dụ
53
Handle

Handle của chuỗi ký tự là một chuổi con, mà nó so
trùng với vế phải luật sinh sao cho việc thu giảm
chuổi con này về ký hiệu không kết thúc là một
trong các bước của quá trình dẫn xuất.
Tìm kiếm handle:
Bắt đầu từ chuỗi cần phân tích w, ta đặt w = n. n
là dạng câu được dẫn xuất ở lần thứ n.
54
Handle
Xây dựng dẫn xuất phải ngược từ w = n.
Ta tìm ßn trong n sao cho ßn là vế phải luật sinh An
-> ßn.
Thay ßn trong n bằng An, ta nhận được dạng câu
thứ (n –1) là (n –1).
Quá trình thu giảm cứ tiếp tục như vậy cho đến khi
đạt được 0 chỉ còn là một ký hiệu không kết thúc
và là ký hiệu mục tiêu.
55
Phân tích cú pháp thứ tự yếu

Văn phạm có tính chất: không có luật sinh nào có
vế phải là chuỗi rỗng (A -> ) hoặc ở vế phải
không có hai ký hiệu không kết thúc đứng kề nhau
gọi là văn phạm thứ tự yếu.
56
Phân tích cú pháp thứ tự yếu
57
Phân tích cú pháp thứ tự yếu
2. Hoạt động
Thí dụ 4.10. Cho văn phạm của phát biểu gán
< assign stmt > -> id = < exp >
< exp > -> < exp > + < term > | <term>
< term > -> < term > * < factor > | < factor >
< factor > -> id | (< exp >)
Ký hiệu <assign stmt> là ký hiệu mục tiêu.
58
Bảng phân tích S-R cho văn phạm ở thí
dụ
59
Giải thuật phân tích cú pháp thứ tự
yếu
Lúc đầu stack trạng thái chỉ có ký hiệu $. Stack nhập chứa
chuỗi nhập, được kết thúc bởi dấu $ ; c: = false ;
repeat
if Ký hiệu mục tiêu ở trên đỉnh stack và ký hiệu $ ở đáy
stack trạng thái, đồng thời stack nhập chỉ chứa $ then
c:=true /*phântíchthànhcông, câycúphápxâydựngxong*/
else begin
-X ở trên đỉnh stack trạng thái, Y ở trên đỉnh stack nhập.
-Giả sửT là trị của phần tử S-R [X, Y];
if T là rỗng then error ()
60
Giải thuật phân tích cú pháp thứ tự
yếu
else if T = R then
If trên đỉnh stack có chứa vế phải của luật sinh nào
đó then begin
Gọi A ->X1X2…Xn là luật sinh nào có vế phải
dài nhất so trùng với chuỗi trên stack trạng thái:
(a) Giải tỏa X1 X2…Xn ra khỏi stack;
(b) ThayA lên stack.
(c) Tạo nút mới A trên cây cú pháp, có các con
là X1X2…Xn
end
61
Giải thuật phân tích cú pháp thứ tự
yếu
else error () //Không tìm ra luật sinh
else begin
(a) Giải tỏa Y ra khỏi stack nhập;
(b) Đẩy Y lên đỉnh stack trạng thái;
(c) Tao nút mới tên Y trên cây cú pháp;
end;
end;
until c;
62
Xây dựng bảng phân tích S-R


Định nghĩa các quan hệ <•, =, •>:
Chúng ta nói X <•Y nếu và chỉ nếu tồn tại một luật
sinh mà vế phải có dạng …XA với A là ký hiệu
không kết thúc và sinh ra một chuỗi bắt đầu bằng
Y (A ->Y…) như vậy X là biên trái của handle.
X •>Y nếu và chỉ nếu tồn tại một luật sinh mà vế
phải có dạng …AB. A sinh ra một chuỗi ký hiệu
được kết thúc bằng X (A-> …X). B sinh ra một
chuỗi được bắt đầu bằngY (B ->Y…), hoặc B = Y.
Ở đây có hai trường hợp xảy ra trong quá trình tìm
các mối quan hệ cho cặp (X, Y).
63
Xây dựng bảng phân tích S-R



X = Y nếu và chỉ nếu tồn tại một luật sinh mà vế
phải có dạng …XY...
Nhận xét: (Nếu khi phân tích cú pháp X trên đỉnh
stack trạng thái, Y trên stack nhập)
X •>Y thì bộ phân tích sẽ thực hiện một hành vi
thu giảm.
X <=•Y thì bộ phân tích sẽ thực hiện một hành vi
đẩy.
64
Nguyên tắc tính quan hệ <=•



Tồn tại $ <=• A với A là ký hiệu mục tiêu của văn
phạm cho trước.
Nếu vế phải luật sinh có X nằm kề ngay Y về phía
trái (…XY…) thì X <=•Y
Nếu X <=•Y mà tồn tại một luật sinh Y -> Z1
…Zn thì X <=•Z1
65
Nguyên tắc tính quan hệ •>




Tồn tại A •> $ với A là ký hiệu mục tiêu.
Nếu X <=•Y và tồn tại một luật sinh X -> Z1…Zn
thì Zn •> Y
Nếu X •>Y và tồn tại một luật sinh X -> Z1…Zn
thì Zn •> Y
Nếu X •>Y và tồn tại một luật sinh Y -> Z1…Zn
thì X •> Z1
66
Ví dụ

Với chuỗi nhập id = id + id * id, hãy cho biết quá
trình phân tích.
67
Bộ phân tích cú pháp LR


Các tính chất của phương pháp phân tích LR:
Bộ phân tích LR có thể nhận dạng được cấu trúc cú
pháp của các ngôn ngữ lập trình do văn phạm phi
ngữ cảnh tạo ra.
Phương pháp LR là phương pháp tổng quát nhất
của phương pháp phân tích đẩy và thu giảm, không
bị quay lui từ trước đến giờ.
68
Bộ phân tích cú pháp LR


Lớp văn phạm được phân tích bằng phương pháp
LR là lớp văn phạm cha, bao trùm lớp văn phạm
được phân tích bởi phương pháp đoán nhận trước.
Bộ phân tích có khả năng phát hiện lỗi sớm nhất
khi nó rà đến ký hiệu nhập từ trái sang phải.
69
Cấu tạo bộ phân tích cú pháp LR
70
Hoạt động



Stack được dùng để chứa chuỗi ký hiệu có dạng
s0X1s1X2…Xmsm, với sm nằm trên đỉnh stack,
Xi được gọi là ký hiệu văn phạm, si là trạng thái.
Cặp(si, Xi) sẽ xác định một trị được lưu chứa trong
bảng phân tích. Bảng phân tích gồm hai phần biểu
thị bởi hàm action và goto.
Cấu hình (configuration) của bộ phân tích LR là
một cặp (nội dung stack nội dung còn lại của chuỗi
nhập)
Ví dụ: (s0X1s1…Xisi…Xmsm, aiai+1…an$).
71
Phân tích cú pháp LR



Nhập: chuỗi nhập w, bảng phân tích action goto
của văn phạm G.
Xuất: nếu w thuộc L (G), nó tạo ra sự phân tích từ
dưới lên. Ngược lại, bộ phân tích sẽ báo lỗi.
Phương pháp:
Thời điểm ban đầu stack có trạng thái s0.
Chuỗi w$ nằm trên bộ đệm nhập.
Bộ phân tích đặt đầu đọc (con trỏ ip) vào ký hiệu
nhập đầu tiên của w.
72
Phân tích cú pháp LR
73
Ví dụ
Cho văn phạmG
(1) E -> E + T
(2) E -> T
(3) T -> T * F
(4) T -> F
(5) F -> (E)
(6) F -> id
Phân tích câu w = id *id + id
74
Bảng phân tích cho văn phạm G
75
Ví dụ
76
Xây dựng bảng phân tích SLR
Định nghĩa: thực thể LR (0) gọi tắt là thực thể của
văn phạm G là luật sinh của G với các điểm chấm
ở các vị trí nào đó của vế phải.
Thí dụ: G có luật sinh A -> XYZ, sẽ cho bốn thực
thể:
A->•XYZ
A->X•YZ
A->XY•Z
A->XYZ•
Nếu A ->  sẽ cho ta thực thể A ->•
77
Giải thuật tính bao đóng–Closure.
Function closure (I : item) : item;
begin J := I;
repeat
for với mỗi thực thể A -> a.Bß trong J và với mỗi luật
sinh
B ->  trong G sao cho
thực thể B -> • chưa có trong J do
thêm B -> • vào J;
until không thể thêm thực thể mới vào J;
closure := J;
end;
78
Ví dụ

Xét văn phạm gia tố của biểu thức:
E' → E
E→E+T|T
T→T*F|F
F → (E) | id
79
Ví dụ
Nếu I là tập hợp chỉ gồm văn phạm { E'→ • E } thì
closure(I) bao gồm:
E' → • E
E→•E+T
E→•T
T→•T*F
T→•F
F → • (E)
F → • id
80
Giải thuật tính goto
Goto(I, X), trong đó I là một tập các mục và X là
một ký hiệu văn phạm là bao đóng của tập hợp các
mục A → αX•β sao cho A → α•Xβ  I.
 Cách tính goto(I, X):
1. Tạo một tập I' = ∅.
2. Nếu A → α•Xβ  I thì đưa A→ αX•β vào I', tiếp tục
quá trình này cho đến khi xét hết tập I.
3. Goto(I, X) = closure(I')

81
Ví dụ


Giả sử I = { E' → E•, E → E • + T }.
Tính goto (I, +) ?
Ta có I' = { E→ E + • T }
( goto (I, +) = closure(I') bao gồm các mục :
E → E + • T (Luật 1)
T → • T * F (Luật 2)
T → • F (Luật 2)
F → • (E) (Luật 2)
F → • id (Luật 2)
82
Giải thuật tính tập tuyển
các tập thực thể
Procedure items (G’);
begin
C := {closure ({S’->•S}}}
repeat
for với mỗi tập thực thể I trong C và với mỗi ký
hiệu văn phạm X sao cho phép goto(I, X) không
rỗng và không có trong C do
thêm goto(I, X) vào C;
until không thể thêm tập thực thể mới vào C;
end;
83
Xây dựng bảng phân tích
Nhập: văn phạm gia tố G’

Xuất: bảng phân tích SLR với hàm action và goto cho văn
phạm G’

Phương pháp:
1. Xây dựng C = {Io, I1, …In}.
2. i là trạng thái đại diện cho tập thực thể Ii.
a. Nếu A -> •aß là thực thể ở trong Ii và goto(Ii, a) = Ij thì
phần tử action[i, a] = shift(j), với a phải là ký hiệu kết thúc.
b. Nếu A -> • ở trong Ii thì action[i, a] = reduce(A -> )
với a là tất cả các ký hiệu nằm trong follow(A). A không
phải là S’(ký hiệu mục tiêu mới).

84
Xây dựng bảng phân tích
c. Nếu S’->S• ở trong Ii thì action [i, $] = accept.
3. Cho tất cả các ký hiệu không kết thúc A. Nếu
goto[Ii, A] = Ij thì hàm goto[i, A] = j.
4. Tất cả các phần tử của bảng phân tích không được
xác định bằng quy tắc 2 và 3, chúng ta coi là lỗi.
5 Trạng thái bắt đầu của bộ phân tích là tập thực thể có
chứa thực thể S’-> •S.
85
Ví dụ
Cho văn phạm gia tố G’
E’-> E
E -> E + T
E -> T
T -> T* F
T -> F
F -> (E)
F -> id
Hãy tìm tập C và sơ đồ DFA.
Xây dựng bảng phân tích SLR
86
Ví dụ

Văn phạm gia tố G’:
(0) E'→ E
(1) E → E + T
(2) E → T
(3) T → T * F
(4) T → F
(5) F → (E)
(6) F → id
87
Xây dựng tập C
I0 : E'→ • E
E→•E+T
E→•T
T→•T*F
T→•F
F → • (E)
F → • id
88
Xây dựng tập C
89
Xây dựng tập C
90
Xây dựng tập C
91
Tính Follow



FOLLOW(E) = {+, ), $}
FOLLOW(T) = {*, +, ), $}
FOLLOW(F) = {*, +, ), $}
92
Xây dựng bảng phân tích


Trước tiên xét tập mục I0 : Mục F → • (E) cho ra
action[0, (] = "shift 4", và mục F → • id cho
action[0, id] = "shift 5". Các mục khác trong I0
không sinh được hành động nào.
Bây giờ xét I1 : Mục E'→ E • cho action[1, $] =
"accept", mục E → E • + T cho action[1, +] =
"shift 6".
93
Xây dựng bảng phân tích



Kế đến xét I2 : E → T •
T→T•*F
Vì FOLLOW(E) = {+, ), $}, làm cho action[2, $] =
action[2,+] = action[2,)] = "reduce 2". Mục thứ hai
làm cho action[2,*] = "shift 7".
Tiếp tục theo cách này, ta thu được bảng phân tích
cú pháp SLR đã trình bày.
94
Ví dụ
Cho văn phạm G
(1) S  L = R
(2) S  R
(3) L  * R
(4) L  id
(5) R  L
Xây dựng bảng phân tích SLR cho văn phạm trên
95
Ví dụ
 Ta nhận thấy đụng độ khi action [2, =] = s6 đồng
thời action [2, =] = r5 và action [2, $] = r5. Do đó
tại phần tử action [2, =] có hai trị s6 và r5. Như vậy
G không phải là văn phạm SLR.
96
Xây dựng bảng phân tích
Canonical LR
 Dạng tổng quát của thực thể là [A  αβ, a] với A
 αβ là luật sinh và a là ký hiệu kết thúc hoặc dấu
$.
 Thực thể có dạng như thế được gọi là thực thể LR
(1). Nếu β = ∈ thì thực thể sẽ có dạng [A  α, a].
Lúc này chúng ta thực hiện thu giảm bằng luật sinh
A  α chỉ với điều kiện ký hiệu nhập kế tiếp là a.
97
Phép tính closure
Function Closure(I)
begin
Repeat
For Mỗi mục [A → αBβ, a] trong I, mỗi luật sinh B
→ γ trong G' và mỗi ký hiệu kết thúc b ∈ FIRST
(βa) sao cho [B → γ, b] ∉ I do
Thêm [B → •γ, b] vô I;
Until Không còn mục nào có thể thêm cho I được nữa;
return I;
end;
98
Phép tính goto
Function goto (I, X)
begin
Gọi J là tập hợp các mục [A → αXβ, a] sao cho
[A → α•Xβ, a]∈ I;
return Closure(J);
end;
99
Xây dựng tập tuyển các tập thực thể
Procedure Items (G')
begin
C := Closure ({[S' → S, $]})
Repeat
For Mỗi tập các mục I trong C và mỗi ký hiệu văn
phạm X sao cho goto(I, X) ≠  và goto(I, X)  C do
Thêm goto(I, X) vô C;
Until Không còn tập các mục nào có thể thêm cho C;
end;
100
Xây dựng bảng phân tích
Canonical LR
1. Xây dựng C = {I0, I1, .... In} là tập tuyển các tập
thực thể LR(1)
2. Trạng thái thứ i được xây dựng từ Ii. Các action
tương ứng trạng thái i được xác định như sau:
1. Nếu [A → αaβ,b]  Ii và goto(Ii, a) = Ij thì
action[i, a] = “shift j”. Ở đây a phải là ký hiệu
kết thúc.
2. Nếu [A → α, a]  Ii, A  S' thì action[i, a] =
“reduce (A → α)”.
3. Nếu [S' → S,$]  Ii thì action[i, $] = “accept”.
101
Xây dựng bảng phân tích
Canonical LR
Nếu có một sự đụng độ giữa các luật nói trên thì ta
nói văn phạm không phải là LR(1) và giải thuật sẽ
thất bại.
3. Nếu goto(Ii, A) = Ij thì goto[i,A] = j
4. Tất cả các ô không xác định được bởi 2 và 3 đều là
“error”
5. Trạng thi khởi đầu của bộ phân tích cú pháp được
xây dựng từ tập các mục chứa [S' → •S, $]
102
Xây dựng bảng phân tích LR(1)
chính tắc
Bảng phân tích xác định bởi giải thuật trên gọi là
bảng phân tích LR(1) chính tắc của văn phạm G,
bộ phân tích LR sử dụng bảng LR(1) gọi là bộ
phân tích LR(1) chính tắc và văn phạm có một
bảng LR(1) không có các action đa trị thì được gọi
là văn phạm LR(1).
103
Ví dụ
Cho văn phạm G
(1) S  L = R
(2) S  R
(3) L  * R
(4) L  id
(5) R  L
Xây dựng bảng phân tích Canonical LR cho văn phạm
trên
104
Ví dụ
Văn phạm gia tố của văn phạm G
(0) S’  S
(1) S  L = R
(2) S  R
(3) L  * R
(4) L  id
(5) R  L
105
Xây dựng tập tuyển các tập thực thể
I0 : Closure([S' → S, $])
={S’ → S, $
S → L = R, $
S → R, $
L → * R, = | $
L → id, = | $
R → L, $}
106
Xây dựng tập tuyển các tập thực thể
Goto(I0, S) = I1 : {S' → S, $}
Goto(I0, L) = I2 : {S → L= R, $
R → L, $}
Goto(I0, R) = I3 : {S → R, $ }
Goto(I0,*) = I4 : {L → *R, = | $
R → L, = | $
L → *R, = | $
L → id, = | $}
Goto(I0, id) = I5 : {L → id, = | $}
107
Xây dựng tập tuyển các tập thực thể
Goto(I2 ,=) = I6 : {S → L=R, $
R → L, $
L → *R, $
L → id, $}
Goto(I4, R) = I7 : {L → *R, = | $}
Goto(I4, L) = I8 : {R→ L, = | $}
Goto(I4, *) = I4
Goto(I4, id) = I5
108
Xây dựng tập tuyển các tập thực thể
Goto(I6, R) = I9 : {S → L = R, $}
Goto(I6, L) = I10 : {R → L, $}
Goto (I6, *) = I11 : {L → *R, $
R → L, $
L → *R, $
L → id, $}
Goto (I6, id) = I12 : {L → id, $}
Goto (I11, R) = I13 : {R → *R, $}
109
Xây dựng tập tuyển các tập thực thể
Goto(I11, L) = I10
Goto (I11, *) = I11
Goto (I11, id) = I12
110
Xây dựng bảng phân tích LR chính
tắc cho văn phạm trên
111
Nhận xét
 Mỗi văn phạm SLR(1) là một văn phạm LR(1), tuy
nhiên bộ phân tích cú pháp LR chính tắc có thể có
nhiều trạng thái hơn so với bộ phân tích cú pháp
SLR cho văn phạm đó.
112
Xây dựng bảng phân tích
cú pháp LALR
 Phần này giới thiệu phương pháp cuối cùng để xây
dựng bộ phân tích cú pháp LR.
 LALR (Lookahead-LR), phương pháp này thường
được sử dụng trong thực tế bởi vì những bảng
LALR thu được nói chung là nhỏ hơn nhiều so với
các bảng LR chính tắc và phần lớn các kết cấu cú
pháp của ngôn ngữ lập trình đều có thể được diễn
tả thuận lợi bằng văn phạm LALR.
113
Hạt nhân (core)
 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.
114
Thuật toán xây dựng bảng phân
tích cú pháp LALR
 Xây dựng họ tập hợp các mục LR(1) C = {I0, I1, .... In}
 Với mỗi hạt nhân tồn tại trong tập các mục LR(1) tìm
trên tất cả các tập hợp có cùng hạt nhân này và thay thế
các tập hợp này bởi hợp của chúng.
 Ðặt C' = {J0, J1, .... Jm} là kết quả thu được từ C bằng
cách hợp các tập hợp có cùng hạt nhân. Action tương
ứng với trạng thái i được xây dựng từ Ji theo cách thức
như giải thuật xây dựng bảng phân tích LR chính tắc.
 Nếu có một sự đụng độ giữa các action thì giải thuật
xem như thất bại và ta nói văn phạm không phải là văn
phạm LALR(1).
115
Thuật toán xây dựng bảng phân
tích cú pháp LALR
 Bảng goto được xây dựng như sau:
Giả sử J = I1 ∪ I2 ∪ ... ∪ Ik. Vì I1, I2, ... Ik có chung một
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 nhân với goto (I1, X) ⇒ goto(J, X) =
K.
116
Ví dụ
Cho văn phạm G
(1) S  L = R
(2) S  R
(3) L  * R
(4) L  id
(5) R  L
Xây dựng bảng phân tích LALR cho văn phạm trên
117
Ví dụ
Văn phạm gia tố của văn phạm G
(0) S’  S
(1) S  L = R
(2) S  R
(3) L  * R
(4) L  id
(5) R  L
118
Ví dụ
 Với ví dụ trên, ta có họ tập hợp mục C' như sau
C' = {I0, I1, I2, I3, I411, I512, I6, I713, I810, I9 }
119
Xây dựng tập tuyển các tập thực thể
I0 : Closure([S' → S, $])
={S’ → S, $
S → L = R, $
S → R, $
L → * R, = | $
L → id, = | $
R → L, $}
120
Xây dựng tập tuyển các tập thực thể
Goto(I0, S) = I1 : {S' → S, $}
Goto(I0, L) = I2 : {S → L= R, $
R → L, $}
Goto(I0, R) = I3 : {S → R, $ }
Goto(I0,*), Goto(I6,*) = I411 :
{L → *R, = | $
R → L, = | $
L → *R, = | $
L → id, = | $}
Goto(I0, id), Goto(I6, id) = I512 : {L → id, = | $}
121
Xây dựng tập tuyển các tập thực thể
Goto(I2 ,=) = I6 : {S → L=R, $
R → L, $
L → *R, $
L → id, $}
Goto(I411, R) = I713 : {L → *R, = | $}
Goto(I411, L), Goto(I6, L) = I810 : {R→ L, = | $}
Goto(I6, R) = I9 : {S → L = R, $}
122
Bảng phân tích cú pháp LALR
123
Sử dụng các văn phạm mơ hồ
 Như chúng ta đã nói trước đây rằng mọi văn phạm
mơ hồ đều không phải là LR. Tuy nhiên có một số
văn phạm mơ hồ lại rất có ích cho việc đặc tả và
cài đặt ngôn ngữ.
 Chẳng hạn văn phạm mơ hồ cho kết cấu biểu thức
đặc tả được một cách ngắn gọn và tự nhiên hơn bất
kỳ một văn phạm không mơ hồ nào khác.
 Vì các văn phạm là đa nghĩa nên chúng ta sẽ đưa
thêm các quy tắc khử mơ hồ để chỉ cho phép chọn
một cây phân tích cú pháp cho mỗi một câu nhập.
Theo cách này, đặc tả ngôn ngữ về tổng thể vẫn là
124
đơn nghĩa.
Sử dụng độ ưu tiên và tính kết hợp
của các toán tử để giải quyết đụng độ
 Xét văn phạm của biểu thức số học với hai toán tử
+ và * :
E  E + E | E * E | (E) | id (1)
 Ðây là một văn phạm mơ hồ vì nó không xác định
độ ưu tiên và tính kết hợp của các tóan tử + và *.
Trong khi đó ta có văn phạm tương đương không
mơ hồ cho biểu thức có dạng như sau:
EE+T|T
TT*F|F
(2)
F  (E) | id
125
Sử dụng độ ưu tiên và tính kết hợp
của các toán tử để giải quyết đụng độ
 Văn phạm này xác định rằng + có độ ưu tiên thấp
hơn * và cả hai toán tử đều kết hợp trái. Tuy nhiên
có 2 lý do để chúng ta sử dụng văn phạm (1) chứ
không phải là (2):
 Dễ dàng thay đổi tính kết hợp và độ ưu tiên của + và *
mà không phá hủy các luật sinh và số các trạng thái của
bộ phân tích.
 Bộ phân tích cho văn phạm (2) sẽ mất thời gian thu gọn
bởi các luật sinh E  T và T  F. Hai luật sinh này
không nói lên được tính kết hợp và độ ưu tiên.
126
Sử dụng độ ưu tiên và tính kết hợp
của các toán tử để giải quyết đụng độ
 Nhưng với văn phạm (1) thì làm thế nào để tránh
sự đụng độ? Trước hết chúng ta hãy thành lập bộ
sưu tập C các tập mục LR(0) của văn phạm tăng
cường của nó. Sau đó xây dựng bảng SLR như sau:
127
Bảng phân tích cú pháp SLR
128
Phân tích
 Nhìn vào bảng SLR trong hình trên, ta thấy có sự
đụng độ tại action [7, +] và action [7,*]; action [8,
+] và action [8,*].
 Chúng ta sẽ giải quyết sự đụng độ này bằng quy
tắc kết hợp và độ ưu tiên của các toán tử. Xét chuỗi
nhập id + id * id
129
Phân tích
130
Phân tích
 Bây giờ đến ô đụng độ action[7, *] nên lấy r1 hay
s5?
 Lúc này chúng ta đã phân tích qua phần chuỗi id *
id. Nếu ta chọn r1 tức là thu gọn bởi luật sinh E 
E + E, có nghĩa là chúng ta đã thực hiện phép cộng
trước.
 Do vậy nếu ta muốn toán tử * có độ ưu tiên cao
hơn + thì phải chọn s5.
131
Phân tích
 Nếu chuỗi nhập là id + id + id thì quá trình phân
tích văn phạm dẫn đến hình trạng hiện tại là :
Stack
Output
0E1+4E7
+ id $
 Sẽ phải xét action [7, +] nên chọn r1 hay s4?
 Nếu ta chọn r1 tức là thu gọn bởi luật sinh E  E +
E tức là + thực hiện trước hay toán tử + có kết hợp
trái => action [7, +] = r1
132
Phân tích
 Sau khi đã giải quyết được sự đụng độ đó ta có
được bảng phân tích SLR đơn giản hơn bảng phân
tích của văn phạm tương đương (2) (chỉ sử dụng
10 trạng thái thay vì 12 trạng thái).
 Tương tự, ta có thể xây dựng bảng phân tích LR
chính tắc và LALR cho văn phạm (1).
133
Ví dụ
 Giải quyết trường hợp văn phạm mơ hồ IF THEN
ELSE
 Xét văn phạm cho lệnh điều kiện:
Stmt  if exp then stmt else stmt
| if exp then stmt
| other
134
Ví dụ
 Ðể đơn giản ta viết i thay cho if exp then, S thay
cho stmt, e thay cho else và a thay cho other, ta có
văn phạm gia tố viết lại như sau:
S’ S
S  i S e S (1)
S  iS (2)
S  a (3)
135
Bảng phân tích SLR
136
Phân tích
 Ðể giải quyết đụng độ tại action[4, e]. Trường hợp
này xảy ra trong tình trạng chuỗi ký hiệu if exp
then stmt nằm trong Stack và else là ký hiệu nhập
hiện hành.
 Sử dụng nguyên tắc kết hợp mỗi else với một then
chưa kết hợp gần nhất trước đó nên ta phải Shift
else vào Stack để kết hợp với then nên action[4, e]
= s5.
137