2012-03-07 38 views
5

Tôi đang viết một thông dịch viên C# từ đầu cho trải nghiệm học tập, và cho đến nay mọi thứ đã diễn ra suôn sẻ. Tôi có đầy đủ chức năng C# lexer mà kết quả đầu ra tất cả các loại thẻ để phân tích cú pháp. Tôi biết làm thế nào tôi sẽ phân tích các thẻ, nhưng tôi không chắc làm thế nào tôi nên cấu trúc AST của tôi (cây cú pháp trừu tượng).Làm cách nào để thiết kế các phần của cây cú pháp trừu tượng?

Ví dụ, nếu tôi có một đoạn mã đơn giản:

using System.Xml; 

gì cây sẽ trông như thế khi phân tích cú pháp?

Như thế này?

UsingDirective 
    Identifier(System) 
     Identifier(Xml) 

hoặc như thế này?

UsingDirective 
    Identifier(System) 
    Identifier(Xml) 

Nếu tôi có thể nhận được một số đề xuất và/hoặc ví dụ như làm thế nào tôi có thể cấu trúc thứ như định danh với dấu chấm trong họ, nếu/else if/else, khai báo biến/chuyển nhượng kết hợp trong một tuyên bố (int i = 0;), định nghĩa chức năng, v.v. sẽ hữu ích. Tôi chỉ cần có một ý tưởng tốt hơn về cách cấu trúc cây và tôi có thể tự mình tìm ra phần còn lại. Cảm ơn.

+0

Đó sẽ là một trải nghiệm học tập lâu dài, nếu bạn muốn thực hiện tất cả C# :-) – svick

+0

Tôi sẽ loại bỏ phần lớn thư viện lớp học. Về cơ bản, tôi chỉ triển khai thực hiện những gì cần được triển khai cho các định nghĩa lớp/chức năng cơ bản, tạo/sử dụng biến và các cuộc gọi hàm. –

Trả lời

2

Tôi đã viết một vài phân tích cú pháp trong quá khứ, và tôi nói chung sẽ đi cho một cái gì đó như thế này:

UsingDirective 
    IdentifierList 
    Identifier (LeftNode) (System) 
    Identifier (RightNode) (Xml) 

Trong trường hợp này using System.Collections.Generic

UsingDirective 
    IdentifierList 
     IdentifierList (LeftNode) 
      Identifier (LeftNode) (System) 
      Identifier (RightNode) (Collections) 
     Identifier (RightNode) (Generic) 

Không giống như Roslyn, tôi thích giữ AST của tôi ánh sáng bằng cách không bao gồm các thẻ như là dấu chấm phẩy, từ khóa using vv vì trình biên dịch không cần đến chúng.

Trình phân tích cú pháp mà tôi đã viết riêng cho IDE trông khác nhau - chúng mang theo tất cả những thứ bổ sung này cùng với nhiều thông tin hơn như số dòng và cột.

+0

Tại sao bạn tạo 'IdentifierList' chỉ có hai con? Tại sao không có một 'IdentifierList' duy nhất với nhiều trẻ em khi cần thiết? – svick

+0

Vâng, tôi nghĩ rằng một IdentifierList đơn với những đứa trẻ không giới hạn sẽ tốt hơn. Trong mọi trường hợp, cảm ơn câu trả lời của bạn xbonez. –

+0

Tôi chắc chắn rằng nó sẽ hoạt động tốt. Cá nhân tôi tìm thấy nó dễ dàng hơn để đi qua nó theo cách này (đệ quy), hơn nếu nó chỉ là một danh sách các ý tưởng. Tôi muốn thiết lập một hàm 'traverIdentList':' if (identlist.leftnode là identlistnode) {traverseIdentList (leftnode); } else {traverseident (leftnode); } traverseident (rightnode), ' – xbonez

2

Bạn có thể xem cách Microsoft đang làm điều này với Roslyn. Bạn có thể thấy ở đó họ đã khai báo cây cú pháp như thế nào cho C# (và VB.NET) và thậm chí bạn có thể sử dụng nó thay vì các phần của trình thông dịch của bạn trước khi bạn viết chúng.

Cụ thể, Roslyn cây cú pháp cho thị using của bạn trông như thế này:

UsingDirective 
    UsingKeyword 
    QualifiedName 
     IdentifierName (System) 
     DotToken 
     IdentifierName (Xml) 
    SemicolonToken 

Vì vậy, tương tự như phiên bản thứ hai của bạn, nhưng chi tiết hơn.

Tôi nghĩ rằng phiên bản đầu tiên của bạn không có ý nghĩa nhiều. Xml không phải là con của System ở cấp độ cú pháp (mặc dù bạn có thể có khái niệm "không gian tên cha" sau này ở cấp ngữ nghĩa).

+0

Nhưng đó không phải là một cây cú pháp trừu tượng, nó là một cây cú pháp cụ thể, vì nó bao gồm các phần của mã nguồn như dấu chấm và dấu chấm phẩy. –

+0

Vâng, bạn nói đúng. Nhưng tôi nghĩ bạn có thể căn cứ AST của bạn về điều này. – svick

+0

Vâng, cảm ơn câu trả lời của bạn! Nó đã giúp đỡ. –

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