2012-02-24 22 views
5

Tôi đang tìm cách thực hiện trình đọc S-biểu thức (được sử dụng sau này với cả trình thông dịch Scheme và trình biên dịch), nhưng tôi đã tự hỏi làm cách nào (nếu có) tôi nên viết một AST cho nó.Cách chính xác để phân tích biểu thức S trong OOP

Tôi đã đọc SICP và điều này khá đơn giản từ bên trong Đề án, nhưng tôi đang tìm cách triển khai trình biên dịch và trình biên dịch trong C++, theo kiểu OO. Vui lòng ghi nhớ rằng tôi đang làm điều này chỉ vì mục đích học tập, vì vậy tôi không thực sự tìm cách dễ nhất hoặc nhanh nhất để làm việc này, mà đúng hơn là cách sử dụng lại chính xác và có thể sử dụng lại được.

Tôi đã nhìn thấy trong một số triển khai Đề án mà mọi người phân tích s-biểu thức và các tế bào khuyết điểm dễ dàng đầu ra, một cái gì đó như thế này:

struct Sexpr 
    { 
    }; 

    struct Cons : public Sexpr 
    { 
    Sexpr* left; 
    Sexpr* right; 
    }; 

    struct IntAtom : Sexpr 
    { 
    int value; 
    }; 

Và một lớp con của Sexpr cho từng loại Scheme Atom, hoặc cái gì đó dọc những dòng đó.

Tôi không chắc chắn, nhưng điều này có vẻ như một hack với tôi ... Công việc này không nên được thực hiện bởi một thông dịch viên hơn là người đọc?

Điều tôi muốn biết là nếu điều này được coi là cách tốt nhất (hoặc chính xác) của việc đọc biểu thức S, hay đây là công việc của người thông dịch nhiều hơn trình phân tích cú pháp? Nếu trình phân tích cú pháp có AST riêng của nó thay vì dựa vào các ô chống lại?

+0

Nếu tôi đọc quyền này, câu hỏi không liên quan gì đến việc phân tích cú pháp. Thay vào đó, tôi nghĩ rằng bạn đang yêu cầu: đại diện thích hợp nhất cho kiểu dữ liệu biểu thức s là gì. Bạn có đồng ý không? – dyoo

+0

@dyoo Có và không. Có, bạn nói đúng, tôi đang tìm đại diện thích hợp nhất cho biểu thức s. Và không, bạn sai, câu hỏi này rõ ràng không liên quan đến phân tích cú pháp. Nếu tôi chỉ tìm kiếm đại diện thích hợp nhất cho sexpr, sẽ không có nghi ngờ rằng nó sẽ là tế bào khuyết điểm. Tuy nhiên, tôi đang tìm đại diện thích hợp nhất của sexpr cụ thể ** để phân tích cú pháp **. – ivanmp

+0

. Làm rõ. Sau đó: một điều có thể phân biệt nhiệm vụ phân tích cú pháp là sự cần thiết cho thông tin vị trí nguồn. Các ô khuyết điểm đơn giản không nhớ chúng xuất phát từ nguồn gốc ở đâu. Trong khi phân tích cú pháp, bạn có thể muốn hỗ trợ thông báo lỗi có thể trỏ đến nguồn. Chúng ta có thể cần những thứ gì khác để phân tích cú pháp? – dyoo

Trả lời

3

Để theo dõi từ phía Scheme/vợt của hàng rào:

vợt (và một số triển khai Đề án khác) sử dụng một đại diện phong phú hơn cho các đối tượng cú pháp, để họ có thể có tài sản gắn liền với họ chỉ ra (trong vợt , ít nhất) bối cảnh mà chúng bị ràng buộc, vị trí nguồn đến từ đâu, thông qua trình biên dịch đã chèn chúng, và bất kỳ thông tin nào khác mà bạn có thể muốn lưu trữ (xem "thuộc tính cú pháp" trong Racket).

Thông tin bổ sung này cho phép những thứ như thông báo lỗi với con trỏ đến nguồn và macro hợp vệ sinh.

Xin lưu ý rằng tôi có nghĩa là "phong phú hơn" ở đây chỉ đơn giản là trong ý nghĩa "chứa nhiều giá trị hơn", không theo bất kỳ cách nào không có giá trị trung lập.

Tôi cũng nên thêm --- trước khi rơi vào Turing Tar Pit --- bạn cũng có thể đại diện cho thông tin chính xác này sử dụng bảng ở bên cạnh; giả sử bạn có so sánh con trỏ, không có sự khác biệt rõ ràng giữa việc đặt một giá trị bên trong một cấu trúc và sử dụng một bảng để kết hợp cấu trúc với giá trị.

3

Nếu bạn muốn trở thành hơi hoàn toàn trong cú pháp của bạn, bạn sẽ cần phải hỗ trợ

sexpr ::= atom | sexpr sexpr 
atom ::= nil | intatom | etc. 

Nhưng đó là tổng quát hơn so với hầu hết sexpr bạn sẽ gặp phải. Dạng đơn giản nhất và phổ biến nhất của S-expr trong LISP/Scheme giống như (a b c d) trong đó mỗi a, b, c, d là các nguyên tử hoặc danh sách. Ở dạng cặp, đây là [a [b [c [d nil]]]], có nghĩa là tất cả các mặt bên phải trong danh sách của bạn là danh sách.

Vì vậy, nếu bạn đang đi cho sạch, bạn có thể chỉ làm

class sexpr {}; 
class atom : sexpr {}; 
class s_list : forward_list<smart_ptr<sexpr>> {}; 
+0

bạn có thể định dạng câu trả lời của mình không? – ivanmp

+0

đang cố gắng, xin lỗi :-) –

+0

Không sao cả! Đó là một cái gì đó dọc theo dòng suy nghĩ của tôi, nhưng tôi có hai câu hỏi: 1) có nghĩa là tôi không nên lo lắng về 'các ô khuyết điểm 'tại điểm này (phân tích cú pháp) và để nó như một vấn đề cho người thông dịch, và sử dụng loại AST này như bạn đã trình bày thay thế? 2) Tôi có thể đã nhận được một cái gì đó sai, nhưng không nên s_list kế thừa từ Sexpr? – ivanmp

3

Trong khi người ta có lẽ có thể tranh luận qua lại hơn những gì các phương pháp tiếp cận “đúng” là, theo ý kiến ​​của tôi, cách tiếp cận bạn đề nghị-sử dụng các cấu trúc dữ liệu tương tự để đọc, biên dịch, đánh giá, xử lý — là phương pháp sẽ dạy bạn nhiều nhất về những gì Lisp và câu thần chú "mã là dữ liệu", và cụ thể là nhà điều hành quote thực sự có nghĩa là gì (đó là một điều khá sâu sắc).

Nó cũng là, tình cờ, cách hầu hết các Lisps (thú vị, không bao gồm Đề án) truyền thống làm việc.

Vì vậy, có, để người đọc tạo dữ liệu Lisp: conses, symbols, Lisp numbers, strings, et cetera, chính xác những thứ mà mã Lisp cấp người dùng sẽ xử lý. Nó sẽ làm cho phần còn lại của việc thực hiện đơn giản hơn và mang tính hướng dẫn hơn.

+0

Cảm ơn bạn đã trả lời! Mục tiêu chính của tôi là tìm hiểu nhiều nhất về trình biên dịch và thông dịch nói chung, không nhất thiết là Lisps, đó là lý do tại sao tôi tự hỏi về cách tiếp cận chính xác nhất cho điều này.Tôi đã chọn Đề án vì tôi nghĩ đó là một ngôn ngữ khá đơn giản để bắt đầu (ít nhất là một phần nhỏ của nó), tôi đã làm việc với nó và, cuối cùng nhưng không kém phần quan trọng, tôi cũng thích nó. :) Bạn có ý gì bởi dòng cuối cùng của bạn? – ivanmp

+0

@ivanmp Tôi có nghĩa là nếu bạn đang cố gắng tìm hiểu về Lisp, nó sẽ hướng dẫn * nhiều hơn để làm theo cách này. Vâng, * instructive * là từ tôi đang tìm kiếm. :) Việc triển khai cũng sẽ đơn giản hơn vì bạn không phải xử lý các cấu trúc dữ liệu khác nhau cho các giai đoạn khác nhau và một số dữ liệu có thể chỉ đơn giản là "chuyển qua" các giai đoạn mà không phải chuyển đổi chúng thành bất kỳ thứ gì khác (như trong trường hợp 'quote'). Mặt khác, nếu bạn đang cố gắng tìm hiểu về trình biên dịch nói chung, không phải Lisp nói riêng, dù bằng cách nào cũng có thể là tốt. –

+1

Tôi có nghĩa là dòng này: _Đó là, tình cờ, cách Lisps nhất (** thú vị, không bao gồm Đề án **) truyền thống làm việc._ – ivanmp

1

Bạn có thể muốn xem this c/c++ s-expr parser library để biết ví dụ về cách thực hiện.

Dường như các đại diện cơ sở là:

struct elt { 
    int type; 
    char *val; 
    struct elt *list; 
    struct elt *next; 
}; 

Và tôi trích dẫn từ tài liệu của họ:

Từ một yếu tố có thể là một danh sách hoặc nguyên tử, cấu trúc phần tử có một chỉ số loại có thể là LIST hoặc VALUE. Nếu chỉ báo kiểu là LIST, thì thành viên cấu trúc "list" sẽ là một con trỏ tới phần đầu của danh sách được biểu diễn bởi phần tử này. Nếu chỉ báo loại là VALUE, thì thành viên cấu trúc "val" sẽ chứa nguyên tử được biểu diễn bằng phần tử dưới dạng chuỗi. Trong cả hai trường hợp, con trỏ "tiếp theo" sẽ trỏ đến phần tử tiếp theo của biểu thức s hiện tại.

Ngoài ra here là danh sách toàn bộ các triển khai khác của người đọc s-expr bằng nhiều ngôn ngữ có thể quan tâm.

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