7

Tôi đang tham gia một lớp thiết kế trình biên dịch, nơi chúng tôi phải thực hiện trình biên dịch riêng của chúng tôi (sử dụng flex và bison). Tôi đã có kinh nghiệm phân tích cú pháp (viết các trình phân tích cú pháp gốc và đệ quy của EBNF), nhưng đây là lần đầu tiên tôi viết trình biên dịch.Tạo mã trung gian trong trình biên dịch. Có phải cây AST hoặc phân tích cú pháp luôn cần thiết khi xử lý các điều kiện?

Thiết kế ngôn ngữ khá mở (giáo sư đã để nó cho chúng tôi). Trong lớp, giáo sư đã tạo ra mã trung gian. Ông nói rằng chúng ta không cần thiết phải xây dựng một cây cú pháp trừu tượng hay một cây phân tích cú pháp trong khi phân tích cú pháp, và chúng ta có thể tạo ra mã trung gian khi chúng ta đi.

Tôi thấy điều này gây nhầm lẫn vì hai lý do:

  • gì nếu bạn đang gọi một hàm trước nó được xác định? Làm thế nào bạn có thể giải quyết các mục tiêu chi nhánh? Tôi đoán bạn sẽ phải làm cho nó một quy tắc mà bạn phải xác định chức năng trước khi bạn sử dụng chúng, hoặc có thể xác định trước chúng (như C không?)

  • Làm thế nào bạn sẽ đối phó với điều kiện? Nếu bạn có if-else hoặc thậm chí chỉ là if, làm cách nào bạn có thể giải quyết mục tiêu chi nhánh cho if khi điều kiện là false (nếu bạn đang tạo mã khi bạn đi)?

Tôi đã lên kế hoạch tạo AST và sau đó đi bộ cây sau khi tạo, để giải quyết địa chỉ của hàm và mục tiêu chi nhánh. Đây có phải là chính xác hoặc tôi thiếu một cái gì đó?

Trả lời

7

Giải pháp chung cho cả hai vấn đề của bạn là giữ một danh sách các địa chỉ cần được "vá". Bạn tạo mã và để lại lỗ hổng cho các địa chỉ còn thiếu hoặc bù đắp. Vào cuối đơn vị biên soạn, bạn đi qua danh sách các lỗ và điền chúng vào.

Trong FORTH, "danh sách" các bản vá được lưu giữ trên ngăn điều khiển và không bị ngắt khi mỗi cấu trúc điều khiển kết thúc. Xem FORTH Dimensions

Giai thoại: trình biên dịch Lisp sớm (Tôi tin rằng đó là Lisp) đã tạo ra một danh sách các mã máy có định dạng ký hiệu với tham chiếu tới danh sách mã máy cho mỗi nhánh của điều kiện. Sau đó, nó tạo ra mã nhị phân đi bộ trong danh sách về phía sau. Bằng cách này, vị trí mã cho tất cả các nhánh phía trước đã được biết khi lệnh chi nhánh cần được phát ra.

+0

Điều đó có ý nghĩa - cảm ơn một nhóm! –

+0

Cách khác bạn có thể phát ra mã lắp ráp và để cho người lắp ráp lo lắng về phần đó của vấn đề. Hay đó là gian lận? – dmckee

+0

Chắc chắn, sau đó lắp ráp sẽ cần phải thực hiện hai đi (hoặc một và một nửa nếu nó sử dụng vá) trên mã. Nhiều trình biên dịch, FORTH nói riêng, nhắm mục tiêu mã máy nhị phân trực tiếp. Điều này có thể cho hiệu suất (cả tốc độ và không gian) hoặc các lý do thực dụng khác (chẳng hạn như không có bộ lắp ráp sẵn có). –

1

Crenshaw tutorial là ví dụ cụ thể về không sử dụng bất kỳ loại AST nào. Nó xây dựng một trình biên dịch làm việc (bao gồm các điều kiện, rõ ràng) với việc tạo mã ngay lập tức nhắm mục tiêu đến lắp ráp m68k.

Bạn có thể đọc qua tài liệu vào buổi chiều và rất đáng giá.

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