Kỹ thuật backpatching dùng để dịch biểu thức logic có đánh giá ngắn mạch (short-circuit) thành mã ba địa chỉ mà không cần biết trước nhãn đích, bằng cách để trống trường goto rồi vá (backpatch) sau. Mỗi biểu thức con E mang hai thuộc tính tổng hợp: E.truelist — danh sách chỉ số các lệnh nhảy cần vá tới nơi thực thi khi E đúng, và E.falselist — tương tự khi E sai. Văn phạm và luật ngữ nghĩa (mở rộng đầy đủ với NOT, AND, OR lồng nhau tuỳ ý, và toán tử so sánh bất kỳ trong {<,>,==,!=,≤,≥}):
nextinstr: (i): if a op b goto _ và (i+1): goto _; E.truelist={i}, E.falselist={i+1}.nextinstr lúc đó; backpatch(E1.truelist,M); E.truelist=E2.truelist, E.falselist=E1.falselist∪E2.falselist.Sau khi dịch xong toàn bộ E, đề bài cho hai nhãn đích Ltrue,Lfalse (chỉ số lệnh mà chương trình sẽ nhảy tới khi E đúng/sai); thực hiện backpatch(E.truelist,Ltrue) và backpatch(E.falselist,Lfalse). In ra toàn bộ dãy lệnh đã sinh (đã vá đầy đủ, không còn chỗ trống nào).
Biểu thức được cho ở dạng tiền tố (prefix), token cách nhau bởi khoảng trắng, ví dụ AND REL a < b REL c < d tương ứng a<b&&c<d.
Dòng 1: số nguyên start — chỉ số của lệnh đầu tiên sẽ sinh ra (nextinstr ban đầu).
Dòng 2: biểu thức tiền tố, chỉ gồm các từ khoá REL a op b, NOT E, AND E1 E2, OR E1 E2 (lồng nhau tuỳ ý), với a, b là định danh/hằng không chứa khoảng trắng và op ∈{<,>,==,!=,≤,≥} được biểu diễn bằng đúng các ký hiệu < > == != <= >=.
Dòng 3: hai số nguyên Ltrue Lfalse.
In mỗi lệnh trên một dòng, theo đúng thứ tự chỉ số tăng dần, dạng <i>: if <a> <op> <b> goto <target> hoặc <i>: goto <target>, với <target> là giá trị đã được backpatch (không còn dấu _).
Ví dụ:
Đầu vào:
10
NOT OR REL a == b REL c != d
50 60
Đầu ra:
10: if a == b goto 60
11: goto 12
12: if c != d goto 60
13: goto 50
Đầu vào:
100
AND REL a < b REL c < d
200 300
Đầu ra:
100: if a < b goto 102
101: goto 300
102: if c < d goto 200
103: goto 300
Đang tải editor...