Tôi đang viết một trình phân tích cú pháp cho một ngôn ngữ đánh dấu mà tôi đã tạo (viết bằng python, nhưng điều đó không thực sự liên quan đến câu hỏi này - thực tế nếu đây có vẻ là một ý tưởng tồi, tôi thích một gợi ý cho một con đường tốt hơn) .
Tôi đang đọc về các trình phân tích cú pháp ở đây: http://www.ferg.org/parsing/index.html và tôi đang viết lexer, nếu tôi hiểu chính xác, hãy chia nội dung thành các thẻ. Điều tôi gặp khó khăn trong việc hiểu là loại mã thông báo nào tôi nên sử dụng hoặc cách tạo chúng. Ví dụ: các loại mã thông báo trong ví dụ tôi liên kết đến là:
- CHUỖI
- XÁC NHẬN
- CON SỐ
- VÒI
- BÌNH LUẬN
- EOF
- Nhiều biểu tượng như {và (được tính là loại mã thông báo của riêng họ
Vấn đề tôi gặp phải là các loại mã thông báo tổng quát hơn có vẻ hơi độc đoán đối với tôi. Ví dụ: tại sao CHUINGI loại mã thông báo riêng của nó so với IDENTIFIER. Một chuỗi có thể được biểu diễn dưới dạng STRING_START + (IDENTIFIER | WHITESPACE) + STRING_START.
Điều này cũng có thể phải làm với những khó khăn trong ngôn ngữ của tôi. Ví dụ, khai báo biến được viết {var-name var value}
và triển khai với {var-name}
. Có vẻ như '{'
và '}'
nên là mã thông báo của riêng họ, nhưng các loại mã thông báo đủ điều kiện VAR_NAME và VAR_VALUE, hoặc cả hai loại này đều thuộc IDENTIFIER? Thêm nữa là VAR_VALUE thực sự có thể chứa khoảng trắng. Khoảng trắng sau var-name
được sử dụng để biểu thị sự bắt đầu của giá trị trong khai báo .. bất kỳ khoảng trắng nào khác là một phần của giá trị. Liệu khoảng trắng này trở thành mã thông báo của riêng nó? Khoảng trắng chỉ có ý nghĩa đó trong bối cảnh này. Hơn nữa, {
có thể không phải là khởi đầu của một khai báo biến .. nó phụ thuộc vào ngữ cảnh (lại có từ đó!). {:
bắt đầu khai báo tên và{
thậm chí có thể được sử dụng như một phần của một số giá trị.
Ngôn ngữ của tôi tương tự như Python trong các khối được tạo ra với thụt lề. Tôi đã đọc về cách Python sử dụng từ vựng để tạo mã thông báo INDENT và DEDENT (phục vụ ít nhiều như những gì {
và }
sẽ làm trong nhiều ngôn ngữ khác). Python tuyên bố là không có ngữ cảnh, điều đó có nghĩa với tôi rằng ít nhất là người từ chối không quan tâm đến vị trí của nó trong luồng trong khi tạo mã thông báo. Làm thế nào để lexer của Python biết rằng nó đang xây dựng mã thông báo INDENT có độ dài cụ thể mà không biết về các ký tự trước đó (ví dụ: dòng trước đó là một dòng mới, vì vậy hãy bắt đầu tạo khoảng trắng cho INDENT)? Tôi hỏi vì tôi cũng cần biết điều này.
Câu hỏi cuối cùng của tôi là câu hỏi ngu ngốc nhất: tại sao một từ vựng thậm chí còn cần thiết? Dường như với tôi rằng trình phân tích cú pháp có thể đi từng nhân vật và tìm ra vị trí của nó và những gì nó mong đợi. Liệu lexer thêm lợi ích của sự đơn giản?