2008-12-10 33 views
9

Bạn sẽ xác định quy tắc phân tích cú pháp và quy tắc lexer của mình để phân tích cú pháp ngôn ngữ sử dụng thụt lề để xác định phạm vi.Làm cách nào để phân tích cú pháp thụt lề (kiểu python)?

Tôi đã googled và tìm thấy một cách tiếp cận thông minh để phân tích cú pháp bằng cách tạo ra các mã thông báo INDENT và DEDENT trong lexer.

Tôi sẽ đi sâu hơn về vấn đề này và đăng câu trả lời nếu tôi đến một điều gì đó thú vị, nhưng tôi muốn thấy các cách tiếp cận khác cho vấn đề.

EDIT: Như Charlie đã chỉ ra, there is already another thread very similar if not the same. Tôi có nên xóa bài đăng của mình không?

Trả lời

1

Ngoài ra, bạn có thể theo dõi một nơi nào đó trong lexer số lượng mục nhận diện trước dòng đầu tiên và chuyển nó tới trình phân tích cú pháp. Nếu trình phân tích cú pháp của bạn sử dụng lookahead (ở đây tôi có nghĩa là trình phân tích cú pháp có thể truy vấn cho số lượng mã thông báo trước khi nó thực sự khớp với), sau đó cố gắng chuyển nó qua một biến toàn cầu là ý tưởng rất xấu (vì lexer có thể trượt trên dòng tiếp theo và thay đổi giá trị của bộ đếm thụt lề trong khi trình phân tích cú pháp vẫn đang cố phân tích cú pháp dòng trước đó). Ngoài ra globals là ác trong nhiều trường hợp khác;) Đánh dấu dòng đầu tiên 'thực sự' token trong cách nào đó với counter indent là hợp lý hơn. Tôi không thể cung cấp cho bạn ví dụ chính xác (tôi thậm chí không biết trình tạo phân tích cú pháp và trình tạo lexer nào bạn sẽ sử dụng nếu có ...) nhưng giống như lưu trữ dữ liệu trên mã thông báo đầu tiên (có thể không thoải mái nếu bạn có thể) t dễ dàng nhận được mã thông báo từ trình phân tích cú pháp) hoặc lưu dữ liệu tùy chỉnh (bản đồ liên kết mã thông báo tới thụt lề, mảng trong đó mọi dòng trong mã nguồn dưới dạng chỉ mục và giá trị thụt lề như giá trị phần tử) có vẻ là đủ. Một nhược điểm của phương pháp này là sự phức tạp bổ sung đối với trình phân tích cú pháp cần phân biệt giữa các giá trị nhận dạng và thay đổi hành vi của nó dựa trên nó. Một cái gì đó như LOOKAHEAD ({yourConditionInJava}) cho JavaCC có thể hoạt động ở đây nhưng nó là NOT một ý tưởng rất hay. Rất nhiều thẻ bổ sung trong cách tiếp cận của bạn dường như ít điều xấu hơn để sử dụng :)

Như một giải pháp thay thế khác, tôi khuyên bạn nên kết hợp hai phương pháp này. Bạn chỉ có thể tạo thêm mã thông báo khi bộ đếm thụt lề thay đổi giá trị của nó trên dòng tiếp theo. Nó giống như BEGIN và END token nhân tạo. Bằng cách này, bạn có thể giảm số lượng mã thông báo 'nhân tạo' trong luồng của mình được đưa vào trình phân tích cú pháp từ lexer. Chỉ cần điều chỉnh ngữ pháp phân tích cú pháp của bạn để hiểu thêm các mã thông báo ...

Tôi đã không thử (không có kinh nghiệm thực sự với phân tích ngôn ngữ như vậy), chỉ chia sẻ suy nghĩ của tôi về các giải pháp khả thi. Việc kiểm tra các trình phân tích cú pháp đã được tạo sẵn cho các loại ngôn ngữ này có thể có giá trị lớn cho bạn. Mã nguồn mở là bạn của bạn;)

10

Đây là loại giả thuyết, vì nó phụ thuộc vào công nghệ bạn có cho lexer và phân tích cú pháp của bạn, nhưng cách dễ nhất có vẻ là có BEGINBLOCK và thẻ ENDBLOCK tương tự với dấu ngoặc trong C. Sử dụng số điện thoại "offsides rule" của bạn cần theo dõi một loạt các cấp độ bồi thường. Khi mức thụt lề tăng, hãy phát ra BEGINBLOCK cho trình phân tích cú pháp; khi mức thụt đầu dòng giảm, phát ra ENDBLOCK và các mức pop trong ngăn xếp.

Here's another discussion trong số này trên SO, btw.

Các vấn đề liên quan