Vasya và Hệ thống kiểu
Đề bài
Mô tả
Ngôn ngữ lập trình giả định &K* có hệ thống kiểu rất mạnh. Bạn cần viết một trình phân tích nhỏ cho hệ thống này.
Ngôn ngữ chỉ có hai kiểu cơ bản: void và errtype. Trên mỗi kiểu, ta có hai phép toán:
- Phép con trỏ: thêm dấu
*vào bên phải kiểu tạo ra kiểu mới . - Phép giải tham chiếu: thêm dấu
&vào bên trái kiểu . Nếu là một kiểu con trỏ thì kết quả là kiểu mà trỏ tới; nếu giải tham chiếu void thì kết quả là errtype.
Quy tắc đặc biệt:
- Phép con trỏ có độ ưu tiên cao hơn phép giải tham chiếu. Do đó biểu thức
&T*luôn bằng (khi không phải errtype). - Với errtype, đẳng thức sau luôn đúng:
errtype* = &errtype = errtype. - Sử dụng một định danh chưa từng được định nghĩa cũng cho kết quả errtype.
Có hai loại lệnh:
typedef A B— định nghĩa kiểu mới tương đương với kiểu tại thời điểm hiện tại (đưa về dạng chuẩnvoid**...*hoặcerrtyperồi gán cho ). có thể chứa các dấu*và&; là một định danh đơn (không có*hay&, khác void và errtype). Có thểtypedeflại một tên đã định nghĩa — chỉ định nghĩa mới nhất là có hiệu lực, nhưng các kiểu khác đã được định nghĩa dựa trên giá trị cũ thì không thay đổi.typeof A— in ra kiểu của ở dạngvoid**...*(số dấu*có thể bằng ) hoặcerrtype.
Các lệnh được thực thi tuần tự. Ví dụ, sau hai lệnh typedef &void a rồi typedef a* b: bước đầu trở thành errtype, do đó errtype* = errtype, không phải &void* = void.
Dữ liệu vào
- Dòng đầu chứa số nguyên — số lệnh.
- dòng tiếp theo, mỗi dòng chứa một lệnh dạng
typedef A Bhoặctypeof A.
Dữ liệu ra
Với mỗi lệnh typeof, in ra một dòng chứa kết quả.
Ràng buộc
- Mọi tên kiểu là chuỗi không rỗng gồm tối đa chữ cái Latin thường.
- Trong mỗi lần xuất hiện, số dấu
*và số dấu&không vượt quá mỗi loại; nhưng khi quy về dạngvoid**...*thì số*có thể lớn hơn .
Ví dụ
| Input | Output | Giải thích |
|---|---|---|
| 5 typedef void* ptv typeof ptv typedef &&ptv node typeof node typeof &ptv |
void* errtype void |
ptv = void*. &&ptv = &&(void*) = &void = errtype, nên node = errtype. &ptv = &(void*) = void. |
| 2 typedef void errtypea typeof errtypea |
void | errtypea là một định danh bình thường, không phải kiểu đặc biệt errtype. Sau lệnh đầu, errtypea = void. |
| 17 typedef void* b typedef b* c typeof b typeof c typedef &b b typeof b typeof c typedef &&b* c typeof c typedef &b* c typeof c typedef &void b typeof b typedef b******* c typeof c typedef &&b* c typeof c |
void* void** void void** errtype void errtype errtype errtype |
Xem ghi chú dưới đây. |
Lưu ý cho ví dụ thứ ba: sau hai lệnh typedef đầu, void* và void**. Lệnh typedef &b b đổi thành &void* = void (giá trị cũ của giữ nguyên). Sau typedef &&b* c: &&void* = &void = errtype. Lệnh typedef &b* c đặt &void* = void. Tiếp đến typedef &void b đưa thành errtype, kéo theo typedef b******* c ⇒ errtype******* = errtype, và lệnh cuối cùng tương tự.
Bình luận