25/05/2018, 09:32

Dịch trực tiếp cú pháp (Syntax - Directed Translation)

Ðể dịch một kết cấu ngôn ngữ lập trình, trong quá trình dịch, bộ biên dịch cần lưu lại nhiều đại lượng khác cho việc sinh mã ngoài mã lệnh cần tạo ra cho kết cấu. Chẳng hạn nó cần biết kiểu (type) của kết cấu, địa chỉ của lệnh đầu tiên trong ...

Ðể dịch một kết cấu ngôn ngữ lập trình, trong quá trình dịch, bộ biên dịch cần lưu lại nhiều đại lượng khác cho việc sinh mã ngoài mã lệnh cần tạo ra cho kết cấu. Chẳng hạn nó cần biết kiểu (type) của kết cấu, địa chỉ của lệnh đầu tiên trong mã đích, số lệnh phát sinh,v.v Vì vậy ta nói một cách ảo về thuộc tính (attribute) đi kèm theo kết cấu. Một thuộc tính có thể biểu diễn cho một đại lượng bất kỳ như một kiểu, một chuỗi, một địa chỉ vùng nhớ, v.v

Chúng ta sử dụng định nghĩa trực tiếp cú pháp (syntax - directed definition) nhằm đặc tả việc phiên dịch các kết cấu ngôn ngữ lập trình theo các thuộc tính đi kèm với thành phần cú pháp của nó. Chúng ta cũng sẽ sử dụng một thuật ngữ có tính thủ tục hơn là lược đồ dịch (translation scheme) để đặc tả quá trình dịch. Trong chương này, ta sử dụng lược đồ dịch để dịch một biểu thức trung tố thành dạng hậu tố.

Ký pháp hậu tố (Postfix Notation)

Ký pháp hậu tố của biểu thức E có thể được định nghĩa quy nạp như sau:

  1. Nếu E là một biến hay hằng thì ký pháp hậu tố của E chính là E.
  2. Nếu E là một biểu thức có dạng E1 op E2 trong đó op là một toán tử hai ngôi thì ký pháp hậu tố của E là E1’ E2’ op. Trong đó E1’, E2’ tương ứng là ký pháp hậu tố của E1, E2.
  3. Nếu E là một biểu thức dạng (E1) thì ký pháp hậu tố của E là ký pháp hậu tố của E1.

Trong dạng ký pháp hậu tố, dấu ngoặc là không cần thiết vì vị trí và số lượng các đối số chỉ cho phép xác định một sự giải mã duy nhất cho một biểu thức hậu tố.

Ví dụ 2.6: Dạng hậu tố của biểu thức (9 - 5) + 2 là 9 5 - 2 +

Dạng hậu tố của biểu thức 9 - (5 + 2) là 9 5 2 + -

Ðịnh nghĩa trực tiếp cú pháp (Syntax - Directed Definition)

Ðịnh nghĩa trực tiếp cú pháp sử dụng văn phạm phi ngữ cảnh để đặc tả cấu trúc cú pháp của dòng input nhập. Nó liên kết mỗi ký hiệu văn phạm với một tập các thuộc tính và mỗi luật sinh kết hợp với một tập các quy tắc ngữ nghĩa (semantic rule) để tính giá trị của thuộc tính đi kèm với những ký hiệu có trong luật sinh văn phạm. Văn phạm và tập các quy tắc ngữ nghĩa tạo nên định nghĩa trực tiếp cú pháp.

Phiên dịch (translation) là một ánh xạ giữa input - output (input - output mapping). Output cho mỗi input x được xác định theo cách sau. Trước hết xây dựng cây phân tích cú pháp cho x. Giả sử nút n trong cây phân tích cú pháp có nhãn là ký hiệu văn phạm X. Ta viết X.a để chỉ giá trị của thuộc tính a của X tại nút đó. Giá trị của X.a tại n được tính bằng cách sử dụng quy tắc ngữ nghĩa cho thuộc tính a kết hợp với luật sinh cho X tại nút n. Cây phân tích cú pháp có thể hiện rõ giá trị của thuộc tính tại mỗi nút gọi là cây phân tích cú pháp chú thích (annotated parse tree).

Thuộc tính tổng hợp (Synthesized Attributes)

Một thuộc tính được gọi là tổng hợp nếu giá trị của nó tại một nút trên cây cú pháp được xác định từ các giá trị của các thuộc tính tại các nút con của nút đó.

Ví dụ 2.7: Ðịnh nghĩa trực tiếp cú pháp cho việc dịch các biểu thức các số cách nhau bởi dấu + hoặc - thành ký pháp hậu tố như sau:

Chẳng hạn, một quy tắc ngữ nghĩa E.t := E1.t || T.t || ‘+’ kết hợp với luật sinh xác định giá trị của thuộc tính E.t bằng cách ghép các ký pháp hậu tố của E1.t và T.t và dấu ‘+’. Dấu || có nghĩa như sự ghép các chuỗi.

Ta có cây phân tích cú pháp chú thích cho biểu thức 9 - 5 + 2 như sau :

Giá trị của thuộc tính t tại mỗi nút được tính bằng cách dùng quy tắc ngữ nghĩa kết hợp với luật sinh tại nút đó. Giá trị thuộc tính tại nút gốc là ký pháp hậu tố của chuỗi được sinh ra bởi cây phân tích cú pháp.

Duyệt theo chiều sâu (Depth - First Traversal)

Quá trình dịch được cài đặt bằng cách đánh giá các luật ngữ nghĩa cho các thuộc tính trong cây phân tích cú pháp theo một thứ tự xác định trước. Ta dùng phép duyệt cây theo chiều sâu để đánh giá quy tắc ngữ nghĩa. Bắt đầu từ nút gốc, thăm lần lượt (đệ qui) các con của mỗi nút theo thứ tự từ trái sang phải.

Procedure visit (n : node);

begin

for với mỗi nút con m của n, từ trái sang phải do

visit (m);

Ðánh giá quy tắc ngữ nghĩa tại nút n;

end

Lược đồ dịch (Translation Scheme)

Một lược đồ dịch là một văn phạm phi ngữ cảnh, trong đó các đoạn chương trình gọi là hành vi ngữ nghĩa (semantic actions) được gán vào vế phải của luật sinh. Lược đồ dịch cũng như định nghĩa trực tiếp cú pháp nhưng thứ tự đánh giá các quy tắc ngữ nghĩa được trình bày một cách rõ ràng. Vị trí mà tại đó một hành vi được thực hiện được trình bày trong cặp dấu ngoặc nhọn { } và viết vào vế phải luật sinh.

Ví dụ 2.8: rest → + term {print (‘+’)} rest1.

Lược đồ dịch tạo ra một output cho mỗi câu nhập x sinh ra từ văn phạm đã cho bằng cách thực hiện các hành vi theo thứ tự mà chúng xuất hiện trong quá trình duyệt theo chiều sâu cây phân tích cú pháp của x. Chẳng hạn, xét cây phân tích cú pháp với một nút có nhãn rest biểu diễn luật sinh nói trên. Hành vi ngữ nghĩa { print(‘+’) } được thực hiện sau khi cây con term được duyệt nhưng trước khi cây con rest1 được thăm.

Phát sinh bản dịch (Emitting a Translation)

Trong chương này, hành vi ngữ nghĩa trong lược đồ dịch sẽ ghi kết quả của quá trình phiên dịch vào một tập tin, mỗi lần một chuỗi hoặc một ký tự. Chẳng hạn, khi dịch 9 - 5 + 2 thành 9 5 - 2 + bằng cách ghi mỗi ký tự trong 9 - 5 + 2 đúng một lần mà không phải ghi lại quá trình dịch của các biểu thức con. Khi tạo ra output dần dần theo cách này, thứ tự in ra các ký tự sẽ rất quan trọng.

Chú ý rằng các định nghĩa trực tiếp cú pháp đều có đặc điểm sau: chuỗi biểu diễn cho bản dịch của ký hiệu chưa kết thúc ở vế trái của mỗi luật sinh là sự ghép nối của các bản dịch ở vế phải theo đúng thứ tự của chúng trong luật sinh và có thể thêm một số chuỗi khác xen vào giữa. Một định nghĩa trực tiếp cú pháp theo dạng này được xem là đơn giản.

Ví dụ 2.9: Với định nghĩa trực tiếp cú pháp như hình 2.3, ta xây dựng lược đồ dịch như sau :

Ta có các hành động dịch biểu thức 9 - 5 + 2 thành 9 5 - 2 + như sau :

Xem như một quy tắc tổng quát, phần lớn các phương pháp phân tích cú pháp đều xử lý input của chúng từ trái sang phải, trong lược đồ dịch đơn giản (lược đồ dịch dẫn xuất từ một định nghĩa trực tiếp cú pháp đơn giản), các hành vi ngữ nghĩa cũng được thực hiện từ trái sang phải. Vì thế, để cài đặt một lược đồ dịch đơn giản, chúng ta có thể thực hiện các hành vi ngữ nghĩa trong lúc phân tích cú pháp mà không nhất thiết phải xây dựng cây phân tích cú pháp.

0