Giai đoạn tiền xử lý của một lexer cần loại bỏ chú thích khỏi mã nguồn, nhưng phải tôn trọng chuỗi ký tự (string literal): chú thích chỉ được nhận diện khi nó nằm ngoài một chuỗi ký tự.
Mã nguồn được quét từ trái sang phải theo đúng một trong bốn trạng thái sau:
", chuyển sang trạng thái STRING (ký tự " được giữ lại). Nếu gặp //, chuyển sang LINE_COMMENT (hai ký tự này bị loại bỏ). Nếu gặp /*, chuyển sang BLOCK_COMMENT (hai ký tự này bị loại bỏ). Ngược lại, ký tự được giữ nguyên.\ và còn ký tự tiếp theo, giữ nguyên cả hai ký tự (escape) và ở lại STRING. Nếu gặp ", giữ lại và quay về CODE. Ngược lại giữ nguyên ký tự, kể cả khi ký tự đó tạo thành chuỗi // hay /* — bên trong STRING các chuỗi này không được coi là chú thích.\n, giữ lại ký tự xuống dòng đó và quay về CODE. Ngược lại, ký tự bị loại bỏ.*/, loại bỏ hai ký tự này và quay về CODE. Nếu gặp \n, giữ lại ký tự xuống dòng (để không làm lệch số dòng của phần còn lại) rồi tiếp tục ở BLOCK_COMMENT. Ngược lại, ký tự bị loại bỏ.Nếu mã nguồn kết thúc (EOF) khi đang ở LINE_COMMENT hoặc BLOCK_COMMENT (chú thích không đóng), phần còn lại coi như thuộc về chú thích đó. Nếu EOF xảy ra khi đang ở STRING (chuỗi không đóng), toàn bộ phần còn lại được giữ nguyên như nội dung chuỗi (không có gì bị loại bỏ).
Cho mã nguồn, hãy tính:
//, /*, */, nhưng không tính các ký tự \n được giữ lại bên trong BLOCK_COMMENT).Toàn bộ nội dung stdin (đọc tới EOF, có thể nhiều dòng, có thể rỗng) là mã nguồn cần xử lý.
In ra một dòng gồm 2 số nguyên cách nhau một dấu cách: số ký tự bị loại bỏ vì là chú thích, và số dòng không rỗng còn lại sau khi loại bỏ chú thích.
Ví dụ:
Đầu vào:
Đầu ra:
0 0
Đầu vào:
// hello world
Đầu ra:
14 0
Đang tải editor...