Một trình biên dịch mini kiểm tra ngữ nghĩa cơ bản trên n dòng lệnh, mỗi dòng có 1 trong 2 dạng:
DECL x — khai báo biến x.USE x — sử dụng biến x.Có 2 loại lỗi ngữ nghĩa:
DECL x khi x đã được khai báo (bởi DECL hoặc do phục hồi ở mục 2) trước đó.USE x khi x chưa từng được khai báo tính đến thời điểm đó.Nếu mỗi lần dùng biến chưa khai báo đều báo lỗi độc lập, một biến bị quên khai báo nhưng được dùng nhiều lần sẽ gây ra hiệu ứng lỗi dây chuyền (cascading errors) — rất nhiều lỗi giả chỉ vì 1 nguyên nhân gốc. Để tránh điều này, trình biên dịch áp dụng phục hồi: ngay khi báo lỗi "biến chưa khai báo" cho x, nó coi x là đã được khai báo ngầm định kể từ dòng đó trở đi, nên các lần USE x sau này sẽ không bị báo lỗi lại. Lưu ý: lỗi "khai báo trùng" thì không được phục hồi kiểu bỏ qua — mỗi lần DECL x khi x đã tồn tại đều tính là 1 lỗi riêng (khai báo trùng đó bị bỏ qua, không ảnh hưởng gì thêm tới trạng thái đã khai báo của x).
Cho n dòng lệnh theo thứ tự, in ra: tổng số lỗi, và danh sách chỉ số dòng (đánh số từ 1) xảy ra lỗi, theo thứ tự tăng dần.
Ví dụ: 5 dòng: DECL x / USE x / USE y / DECL y / USE y. Dòng 1: khai báo x. Dòng 2: dùng x, hợp lệ. Dòng 3: dùng y nhưng y chưa khai báo → lỗi, đồng thời y được coi là đã khai báo ngầm định. Dòng 4: khai báo y nhưng y đã "khai báo" (ngầm định) → lỗi trùng. Dòng 5: dùng y, hợp lệ. Tổng: 2 lỗi, ở các dòng 3 và 4.
Dòng 1: số nguyên n (0≤n≤105). n dòng tiếp theo, mỗi dòng có dạng DECL <tên> hoặc USE <tên> (tên biến là chuỗi chữ-số-gạch dưới không chứa khoảng trắng).
Dòng 1: tổng số lỗi. Dòng 2: các chỉ số dòng bị lỗi, tăng dần, cách nhau 1 dấu cách (dòng trống nếu không có lỗi).
Ví dụ:
Đầu vào:
5
DECL x
USE x
USE y
DECL y
USE y
Đầu ra:
2
3 4
Đầu vào:
0
Đầu ra:
0
Đang tải editor...