Các lượt nộp
    Danh sách bài
    Trang chủ
    Báo lỗi

    solution

    Đề bài: [Trình biên dịch] So khớp dài nhất và phát hiện lỗi từ vựng

    Xét một ngôn ngữ mini với 3 loại token:

    • NUMBER: khớp biểu thức chính quy digit+( . digit+)?\text{digit}^+(\,.\,\text{digit}^+)?digit+(.digit+)? (số nguyên hoặc số thực, không hỗ trợ ký hiệu mũ khoa học ở bài này);
    • IDENT: khớp (letter ∣ _)(letter ∣ digit ∣ _)∗(\text{letter}\,|\,\_)(\text{letter}\,|\,\text{digit}\,|\,\_)^*(letter∣_)(letter∣digit∣_)∗;
    • Toán tử/dấu ngoặc đơn ký tự: mỗi ký tự trong + - * / ( ) là một token riêng biệt.

    Cho một xâu SSS liên tục (không chứa khoảng trắng). Hãy quét SSS từ trái sang phải theo nguyên tắc so khớp dài nhất (maximal munch): tại mỗi vị trí, nếu ký tự hiện tại là chữ số, nuốt chuỗi dài nhất khớp mẫu NUMBER; nếu là chữ cái hoặc _, nuốt chuỗi dài nhất khớp mẫu IDENT; nếu là một trong +-*/(), nuốt đúng 1 ký tự đó làm token tương ứng.

    Nếu tại một vị trí, ký tự hiện tại không khớp bất kỳ trường hợp nào ở trên (ví dụ ký tự đặc biệt như @, #, $, hoặc dấu chấm thứ hai liên tiếp trong một số như ở 1.2.3 sau khi đã nuốt 1.2), đây là một lỗi từ vựng (lexical error): hãy in ra tất cả token đã nhận diện được trước đó, sau đó in thêm đúng 1 dòng LEXICAL ERROR AT POSITION p với ppp là vị trí (1-indexed) của ký tự gây lỗi, rồi dừng xử lý ngay, không xét tiếp phần còn lại của SSS.

    Ví dụ 1: Input 1.2.3 → Output:

    NUMBER 1.2
    LEXICAL ERROR AT POSITION 4
    

    (Sau khi nuốt 1.2, ký tự tiếp theo là dấu . ở vị trí 4, không khớp mẫu nào nên báo lỗi tại vị trí 4.)

    Ví dụ 2: Input x1+42*(y-3.5) → 9 dòng token, không có lỗi (token cuối là RPAREN).

    • Định dạng đầu vào:

      Một dòng duy nhất chứa xâu SSS (0≤∣S∣≤3000 \le |S| \le 3000≤∣S∣≤300), gồm các ký tự chữ cái, chữ số, _, ., các ký tự trong +-*/(), và có thể chứa các ký tự khác dùng để kiểm tra lỗi từ vựng; không chứa khoảng trắng.

    • Định dạng đầu ra:

      In ra danh sách token nhận diện được (mỗi token một dòng, dạng NUMBER value, IDENT value, hoặc một trong PLUS/MINUS/TIMES/DIVIDE/LPAREN/RPAREN), theo đúng thứ tự; nếu gặp lỗi từ vựng, in thêm dòng cuối LEXICAL ERROR AT POSITION p rồi dừng. Nếu SSS rỗng, không in token nào (không có lỗi).

    Ví dụ:

    Đầu vào:

    1.2.3
    

    Đầu ra:

    NUMBER 1.2
    LEXICAL ERROR AT POSITION 4
    

    Đầu vào:

    x1+42*(y-3.5)
    

    Đầu ra:

    IDENT x1
    PLUS
    NUMBER 42
    TIMES
    LPAREN
    IDENT y
    MINUS
    NUMBER 3.5
    RPAREN
    

    Đang tải editor...