Văn phạm chính quy (rg : REGULAR GRAMMAR)
Nội dung chính :Trong chương này, ta sẽ đề cập đến lớp văn phạm chính quy (dạng văn phạm tuyến tính trái hoặc phải) - một phương tiện khác để xác định ngôn ngữ và ta lại thấy rằng lớp ngôn ngữ do chúng sinh ra vẫn là lớp ngôn ngữ ...
Nội dung chính :Trong chương này, ta sẽ đề cập đến lớp văn phạm chính quy (dạng văn phạm tuyến tính trái hoặc phải) - một phương tiện khác để xác định ngôn ngữ và ta lại thấy rằng lớp ngôn ngữ do chúng sinh ra vẫn là lớp ngôn ngữ chính quy. Điều này được thể hiện bởi mối tương quan giữa văn phạm chính quy và ôtômát hữu hạn. Tiếp sau đó, ta sẽ nghiên cứu một số tính chất của lớp ngôn ngữ chính quy, cũng như các giải thuật xác định tập chính quy.
Mục tiêu cần đạt:Cuối chương, sinh viên cần phải nắm vững :
Định nghĩa một biểu thức chính quy ký hiệu cho tập ngôn ngữ.
Mối liên quan giữa ôtômát hữu hạn và biểu thức chính quy.
Các tính chất của tập chính quy.
Xây dựng ôtômát từ biểu thức chính quy
Viết văn phạm chính quy sinh ra cùng tập ngôn ngữ được cho bởi ôtômát.
Kiến thức cơ bản: Để tiếp thu tốt nội dung của chương này, sinh viên cần nắm vững các thành phần tổng quát của một văn phạm cấu trúc, các dạng luật sinh; hiểu biết về ngôn ngữ tự nhiên; cơ chế đoán nhận ngôn ngữ từ ôtômát hữu hạn và cách phát sinh một lớp ngôn ngữ thông qua biểu thức chính quy; …
Tài liệu tham khảo :
V.J. Rayward-Smith – A First course in Formal Language Theory (Second Editor) – McGraw-Hill Book Company Europe – 1995 (Chapter 3 : Regular Language I )
Hồ Văn Quân – Giáo trình lý thuyết ôtômát và ngôn ngữ hình thức – Nhà xuất bản Đại học quốc gia Tp. Hồ Chí Minh – 2002 (Chương 4 : Văn phạm chính quy)
From Wikipedia, the free encyclopedia - Regular Grammar:
http://en.wikipedia.org/wiki/Regular_grammar
Như trong chương 3 ta đã biết, lớp ngôn ngữ được chấp nhận bởi ôtômát hữu hạn được gọi là ngôn ngữ chính quy và chúng có thể được ký hiệu một cách đơn giản bằng việc dùng một biểu thức chính quy. Chương này giới thiệu một cách khác để mô tả ngôn ngữ chính quy thông qua cơ chế sản sinh ngôn ngữ - đó là văn phạm chính quy.
Xét một định nghĩa cho văn phạm sinh ra các số nguyên không dấu (unsigned interger) bắt đầu bằng một chữ số, theo sau bởi một chuỗi các số (digit sequence) thường dùng trong các ngôn ngữ lập trình như sau:
<digit sequence> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
| 0 <digit sequence> | 1 <digit sequence>
| 2 <digit sequence> | 3 <digit sequence>
| 4 <digit sequence> | 5 <digit sequence>
| 6 <digit sequence> | 7 <digit sequence>
| 8 <digit sequence> | 9 <digit sequence>
<unsighed integer> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
| 1 <digit sequence> | 2 <digit sequence>
| 3 <digit sequence> | 4 <digit sequence>
| 5 <digit sequence> | 6 <digit sequence>
| 7 <digit sequence> | 8 <digit sequence>
| 9 <digit sequence>
Trong ví dụ trên, ta thấy mỗi vế phải hoặc là một ký hiệu kết thúc hoặc có dạng của một ký hiệu kết thúc theo sau là một biến. Trong hầu hết mọi ngôn ngữ lập trình, tất cả các ký hiệu cơ bản (số nguyên, tên biến, toán hạng, từ khóa, các ký hiệu hết câu,…) đều có thể định nghĩa bởi những quy luật ngắn dạng này. Vì phần lớn thời gian tiêu tốn trong một trình biên dịch là dùng để nhận dạng các ký hiệu cơ bản, cho nên việc khảo sát lớp văn phạm với các luật sinh dạng như trên là rất cần thiết.
Văn phạm tuyến tính
Một văn phạm G(V, T, P, S) được gọi là tuyến tính trái (left - linear) nếu tất cả các luật sinh của nó có dạng :
A → Bw
A → w
trong đó A, B là các biến ∈ V; w là một chuỗi các ký hiệu kết thúc ∈ T* (có thể rỗng).
Một văn phạm G(V, T, P, S) được gọi là tuyến tính phải (right - linear) nếu tất cả các luật sinh của nó có dạng :
A → wB
A → w
Một văn phạm được gọi là văn phạm chính quy nếu nó thuộc dạng văn phạm tuyến tính trái hoặc tuyến tính phải.
Thí dụ 4.1 : Văn phạm sinh ra các số nguyên không dấu như đã nêu ở trên là văn phạm chính quy vì các luật sinh của nó có dạng tuyến tính phải.
Thí dụ 4.2 : Các văn phạm sau đây là văn phạm chính quy :
Văn phạm G1 ({S}, {a, b}, P1, S) với các luật sinh được cho như sau :
S → abS | a
là văn phạm tuyến tính phải.
Văn phạm G2 ({S, A, B}, {a, b}, P2, S) với các luật sinh được cho như sau : S → Aab
A → Aab | B
B → a
là văn phạm tuyến tính trái.
Thí dụ 4.3 : Ngôn ngữ được ký hiệu bởi biểu thức chính quy 0(10)* được sinh bởi văn phạm tuyến tính phải có các luật sinh sau :
S → 0A (1)
A → 10A | ε
Và bởi văn phạm tuyến tính trái :
S → S10 | 0 (2)
Sự tương đương giữa văn phạm chính quy và ôtômát hữu hạn
Văn phạm chính quy mô tả tập hợp chính quy trong ngữ cảnh một ngôn ngữ là chính quy khi và chỉ khi nó được sinh ra từ văn phạm tuyến tính trái hoặc văn phạm tuyến tính phải. Kết quả này được xác định bởi hai định lý sau :
ĐỊNH LÝ 4.1 : Nếu L được sinh ra từ một văn phạm chính quy thì L là tập hợp chính quy.
Chứng minh
Trước hết, ta giả sử L = L(G) với một văn phạm tuyến tính phải G(V, T, P, S). Ta xây dựng một NFA có chứa ε-dịch chuyển M (Q, T, δ, [S], [ε]) mô phỏng các dẫn xuất trong G.
Q bao gồm các trạng thái có dạng [α] với α là S hoặc chuỗi hậu tố của vế phải một luật sinh nào đó trong P.
Ta định nghĩa δ như sau :
- Nếu A là một biến, thì δ([A], ε) = {[α] | A → α là một luật sinh}
- Nếu a thuộc T và α thuộc T* T*V, thì δ([aα], a) = {[α]}
Sau đó, ta có thể dễ dàng chứng minh quy nạp theo độ dài của dẫn xuất rằng δ ([S], w ) chứa [ α ] khi và chỉ khi có chuỗi dẫn xuất S ⇒ * xA ⇒ xy α với A → y α là một luật sinh trong P và xy = w, hay nếu α = S thì w = ε . Khi [ ε ] là trạng thái kết thúc duy nhất, M chấp nhận w khi và chỉ khi S ⇒ * xA ⇒ w. Nhưng vì mọi chuỗi dẫn xuất cho một chuỗi ký hiệu kết thúc qua ít nhất 1 bước, nên ta thấy rằng M chấp nhận w khi và chỉ khi G sinh ra w. Vì vậy, mọi văn phạm tuyến tính phải đều sinh ra một tập hợp chính quy.
Bây giờ, giả sử G(V, T, P, S) là một văn phạm tuyến tính trái. Đặt văn phạm G’(V, T, P’, S) với P’ chứa các luật sinh của P có vế phải đảo ngược, nghĩa là :
P’ = { A → α | A → αR ∈ P }
Nếu ta đảo ngược chuỗi vế phải các luật sinh trong một văn phạm tuyến tính trái, ta có văn phạm tuyến tính phải, và ngược lại. Do đó, hiển nhiên chúng ta có G’ là một văn phạm tuyến tính phải, và cũng dễ dàng để chỉ ra rằng L(G’) = L(G)R. Theo chứng minh trên, ta có L(G’) là một tập chính quy. Mà thông thường một tập chính quy cũng vẫn còn giữ nguyên tính chất khi áp dụng phép đảo ngược nên L(G’)R = L(G) cũng là một tập chính quy.
Vậy, mọi văn phạm tuyến tính trái hay phải đều sinh ra một tập hợp chính quy.
Thí dụ 4.3 : NFA được xây dựng từ Định lý 4.1 cho văn phạm tuyến tính phải (1) ở thí dụ 4.2 có dạng như hình 4.1 sau :
Xét văn phạm tuyến tính trái (2) ở thí dụ 4.2, nếu đảo ngược các vế phải luật sinh, ta có:
Hình 4.1 - NFA chấp nhận ngôn ngữ 0(10) *
Áp dụng các bước xây dựng NFA cho văn phạm này theo Định lý 4.1, ta có sơ đồ chuyển như Hình 4.2 (a). Nếu chúng ta đảo ngược các cạnh của NFA này và chuyển đổi vị trí các trạng thái bắt đầu và kết thúc, chúng ta sẽ có một NFA khác chấp nhận ngôn ngữ 0(10)*
Hình 4.2 - Xây dựng NFA cho 0(10) * từ văn phạm tuyến tính trái
ĐỊNH LÝ 4.2 : Nếu L là một tập hợp chính quy, thì L được sinh từ một văn phạm tuyến tính trái hoặc một văn phạm tuyến tính phải nào đó.
Chứng minh
Đặt L = L(M) với DFA M(Q, Σ, δ, q0, F).
Trước hết, ta giả sử rằng trạng thái q0 không phải là trạng thái kết thúc. Kế tiếp, ta đặt L = L(G) với văn phạm tuyến tính phải G(V, Σ, P, q0), trong đó P chứa các luật sinh dạng p → aq nếu δ(p, a) = q và luật sinh dạng p → a nếu δ(p, a) là một trạng thái kết thúc. Rõ ràng δ(p, w) = q khi và chỉ khi có chuỗi dẫn xuất p ⇒*wq. Nếu wa được chấp nhận bởi M, ta đặt δ(q0, w) = p, suy ra dẫn xuất q0⇒*wq. Tương tự, nếu δ(p, a) là trạng thái kết thúc, vì p → a là một luật sinh, nên q0⇒*wa. Ngược lại, đặt q0⇒*x. Ta có x = wa và q0⇒*wq ⇒wa với mọi p. Và vì δ(q0, w) = p và δ(p, a) là trạng thái kết thúc nên do đó x ∈ L(M). Hay nói cách khác : L(M) = L(G) = L.
Bây giờ, xét q0∈ F, vì thế chuỗi rỗng ε thuộc L. Lưu ý rằng văn phạm G vừa định nghĩa ở trên chỉ sinh ra ngôn ngữ L – {ε}. Chúng ta có thể sửa đổi G bằng cách thêm vào một ký hiệu bắt đầu S mới với luật sinh S → q0 | ε. Văn phạm thu được vẫn có dạng tuyến tính phải và phát sinh ngôn ngữ L.
Để phát sinh một văn phạm tuyến tính trái cho L, ta bắt đầu với một NFA cho LR và sau đó đảo ngược chuỗi vế phải cho tất cả mọi luật sinh của văn phạm tuyến tính phải vừa thu được.
Thí dụ 4.4 : Trong Hình 4.3 ta thấy sơ đồ chuyển DFA cho 0(10)*
Văn phạm tuyến tính phải sinh từ DFA này có dạng :
A → 0B|1D|0
B → 0D|1C
C → 0B|1D|0
D → 0D|1D
Trong văn phạm trên, biến D không có ích nên ta có thể loại bỏ D và tất cả các luật sinh liên quan tới D, rút gọn văn phạm thành :
A → 0B|0
B → 1C
C → 0B|0
Hình 4.3 - DFA cho 0(10) *