Trình biên dịch quản lý biến theo ngăn xếp phạm vi (scope stack): mỗi khối BEGIN ... END tạo một phạm vi mới; biến khai báo trong phạm vi trong che khuất (shadow) biến cùng tên ở phạm vi ngoài; khi khối kết thúc (END), phạm vi trong bị hủy hoàn toàn.
Chương trình là một dãy lệnh, mỗi lệnh một dòng:
BEGIN: mở một phạm vi mới.END: đóng phạm vi hiện tại (đề bài đảm bảo BEGIN/END luôn cân bằng; phạm vi toàn cục tồn tại từ đầu và không bao giờ bị END).DECL <tên> <kiểu>: khai báo biến kiểu int/float/bool/string trong phạm vi hiện tại. Nếu tên đã tồn tại trong chính phạm vi hiện tại (không tính các phạm vi ngoài), in ERROR (khai báo trùng, khai báo cũ được giữ nguyên); ngược lại in OK và biến được thêm vào phạm vi hiện tại.EXPR <biểu thức>: tính kiểu của biểu thức theo luật ép kiểu như bài toán suy diễn kiểu (toán tử + - * /; + nối được string; các toán tử số học chỉ nhận int/float; lỗi lan truyền). Biến trong biểu thức được tra cứu từ phạm vi hiện tại ra ngoài dần (lấy khai báo gần nhất); nếu không tìm thấy ở phạm vi nào, đó là lỗi (biến chưa khai báo). In ra kiểu kết quả hoặc ERROR.Chỉ lệnh DECL và EXPR sinh dòng output (mỗi lệnh đúng một dòng, theo đúng thứ tự xuất hiện); BEGIN/END không in gì.
Ví dụ
Input:
6
DECL x int
BEGIN
DECL x float
EXPR x
END
EXPR x
Output:
OK
OK
float
int
BEGIN, END, DECL <tên> <kiểu>, hoặc EXPR <biểu thức> (biểu thức có thể chứa hằng số, true/false, chuỗi "...", biến, + - * /, dấu ngoặc (), khoảng trắng).In ra các dòng kết quả tương ứng với các lệnh DECL (OK/ERROR) và EXPR (kiểu kết quả hoặc ERROR), theo đúng thứ tự xuất hiện trong chương trình.
Ví dụ:
Đầu vào:
3
DECL a int
DECL a float
EXPR a
Đầu ra:
OK
ERROR
int
Đầu vào:
6
DECL x int
BEGIN
DECL x float
EXPR x
END
EXPR x
Đầu ra:
OK
OK
float
int
Đang tải editor...