Biên dịch và giải thích
Đã giới thiệu| English | Ý nghĩa |
|---|---|
| compiler/kəmˈpaɪlə/ | trình biên dịch |
| interpreter/ɪnˈtɜːprɪtə/ | trình giải thích |
| lexical analysis/ˈleksɪkl əˈnæləsɪs/ | lexical analysis: phân tích từ vựng |
| tokens/ˈtəʊkənz/ | tokens: đơn vị từ vựng |
| syntax analysis/ˈsɪntæks əˈnæləsɪs/ | syntax analysis: phân tích cú pháp |
| abstract syntax tree/ˈæbstrækt ˈsɪntæks triː/ | abstract syntax tree: cây cú pháp trừu tượng |
| syntax error/ˈsɪntæks ˈerə/ | lỗi cú pháp |
| semantic analysis/səˈmæntɪk əˈnæləsɪs/ | semantic analysis: phân tích ngữ nghĩa |
| code generation/kəʊd ˌdʒenəˈreɪʃn/ | code generation: sinh mã |
| code optimisation/kəʊd ˌɒptɪmaɪˈzeɪʃn/ | code optimisation: tối ưu hóa mã |
Lỗi làm mất một tàu vũ trụ, được phát hiện bởi dấu phẩy
- Mariner 1 của NASA bị phá hủy 293 giây sau khi phóng năm 1962. Sự cố thường được quy cho một ký tự sai duy nhất trong phần mềm điều hướng.
- Câu chuyện này được kể lại rất nhiều lần vì đó là nỗi sợ mà mọi lập trình viên đều biết: một trình biên dịch vui vẻ chuyển đổi một chương trình chứa ý nghĩa bạn không hề muốn.
- Một trình biên dịch không phải là một tiến trình mà là năm quá trình, và mỗi quá trình bắt được một loại lỗi khác nhau. Việc biết giai đoạn nào bắt loại lỗi gì sẽ giúp bạn xác định nguồn gốc của bất kỳ lỗi cụ thể nào.
- Bài học này minh họa cách một trình giải thích chạy chương trình mà không tạo ra file thực thi, cùng năm giai đoạn mà một trình biên dịch trải qua.
Cách trình giải thích chạy một chương trình
- Trình giải thích dịch và chạy mã nguồn cùng lúc, từng câu lệnh một.
- Với mỗi câu lệnh, nó đọc dòng, phân tích, kiểm tra kiểu dữ liệu, sau đó thực thi hành động ngay lập tức và chuyển sang dòng tiếp theo.
- Nó không tạo ra file thực thi: quá trình dịch chỉ tồn tại trong bộ nhớ và bị xóa bỏ. Đó chính xác là điểm của chương trình học, là nó có thể thực thi một chương trình mà không tạo ra phiên bản đã dịch.
- Nó báo cáo lỗi ngay khi đến dòng gây ra vấn đề và thường dừng lại, mang lại phản hồi nhanh trong quá trình phát triển. Mỗi lần chạy đều dịch lại, nên nó chậm hơn, và cả mã nguồn lẫn trình giải thích đều phải có mặt.

Dịch một lần và giữ lại, hoặc dịch rồi chạy và quên đi
Một trình giải thích:
Difficulty 1/5 · 100 coins + a small bonus on first completion today
Nó hoạt động dòng theo dòng, báo cáo lỗi khi gặp phải; không có gì được lưu dưới dạng file thực thi, và nó nói chung chậm hơn.
Một trình giải thích có thể thực thi chương trình mà không tạo ra phiên bản đã dịch của nó.
Difficulty 1/5 · 100 coins + a small bonus on first completion today
Sự dịch chuyển chỉ tồn tại trong bộ nhớ, câu lệnh theo câu lệnh, và bị loại bỏ. Đó là lý do trình giải thích phải hiện diện mỗi khi chương trình chạy.
Giai đoạn 1: phân tích từ vựng
- Phân tích từ vựng gộp các ký tự đơn lẻ của mã nguồn thành các token: từ khóa, danh hiệu (identifier), toán tử và hằng số (literal).
- Khoảng trắng và chú thích bị loại bỏ, vì chúng vô nghĩa đối với trình biên dịch, và các danh hiệu được đưa vào bảng ký hiệu.
- Vì vậy
total ← count * 2trở thành chuỗi token: danh hiệu, phép gán, danh hiệu, toán tử, hằng số. Bộ phân tích từ vựng không biết cũng không quan tâm liệu điều đó có hợp lý hay không.
Phân tích từ vựng (trình phân tích từ vựng) biến:
Difficulty 1/5 · 100 coins + a small bonus on first completion today
Trình phân tích từ vựng nhóm các ký tự thành token và loại bỏ khoảng trắng/chú thích; phân tích sau đó xây dựng cây.
Phân tích từ vựng nhóm các ký tự nguồn thành ____ và loại bỏ khoảng trắng và chú thích.
Difficulty 1/5 · 100 coins + a small bonus on first completion today
Từ khóa, tên định danh, toán tử và hằng số. Trình phân tích từ vựng không đưa ra phán đoán về việc dãy đó có phải là chương trình hợp lệ hay không.
Giai đoạn 2: phân tích cú pháp
- Phân tích cú pháp, hay parse, kiểm tra xem chuỗi token có phù hợp với ngữ pháp của ngôn ngữ hay không, và xây dựng một cây cú pháp trừu tượng biểu diễn cấu trúc.
- Một ngoặc thiếu, một
ENDIFbị thiếu hoặc từ khóa ở vị trí sai sẽ bị bắt ở đây: đó chính là lỗi cú pháp, và đó là lý do trình biên dịch có thể báo cáo lỗi mà chưa cần chạy chương trình.

Ngữ pháp mà bộ parse kiểm tra
Giai đoạn 3: phân tích ngữ nghĩa
- Phân tích ngữ nghĩa kiểm tra xem một chương trình đúng về mặt cú pháp có thực sự hợp lý hay không: mọi biến phải được khai báo trước khi sử dụng, các kiểu dữ liệu hai vế của phép gán phải tương thích, hàm được gọi với đúng số tham số.
total ← "seven" * 2hoàn toàn đúng về mặt cú pháp nhưng vô nghĩa hoàn toàn. Chỉ giai đoạn này mới bắt được nó.- Đây là sự phân biệt mà đề thi kiểm tra: cú pháp là hình thức, ngữ nghĩa là ý nghĩa.
Trong số những điều sau, điều nào được kiểm tra bởi phân tích ngữ nghĩa thay vì phân tích cú pháp?
Difficulty 1/5 · 100 coins + a small bonus on first completion today
Dấu ngoặc là ngữ pháp, nên thuộc về cú pháp; khoảng trắng thuộc về trình phân tích từ vựng; thanh ghi thuộc về tạo mã. Khai báo và kiểu dữ liệu là vấn đề ngữ nghĩa.
Giai đoạn 4 và 5: sinh mã và tối ưu hóa
- Sinh mã duyệt qua cây và xuất mã máy đích, chọn thanh ghi và bố trí dữ liệu.
- Tối ưu hóa mã cải thiện mã đó mà không thay đổi những gì nó làm: loại bỏ công việc thừa, tính toán biểu thức hằng ở thời gian biên dịch, và sắp xếp lại chỉ thị để phù hợp với pipeline.
- Kết quả đầu ra là một file thực thi độc lập chạy mà không cần trình biên dịch có mặt.

Năm giai đoạn, và mỗi giai đoạn bắt được thứ mà giai đoạn trước đó không thể
Các giai đoạn của biên dịch
Đi qua những gì trình biên dịch làm với mã nguồn của bạn. Mỗi giai đoạn chuyển đầu ra cho giai đoạn tiếp theo — ký tự trở thành token, token trở thành cây, cây trở thành mã máy được tối ưu hóa.
Nối mỗi giai đoạn của trình biên dịch với chức năng của nó.
Difficulty 2/5 · 140 coins + a small bonus on first completion today
Mỗi giai đoạn biến đổi chương trình thêm một bước: token, sau đó là cây, sau đó được kiểm tra, rồi mã được tối ưu hóa.
Sắp xếp lại các giai đoạn của trình biên dịch theo thứ tự.
Difficulty 3/5 · 200 coins + a small bonus on first completion today
Từ vựng → Cú pháp → Ngữ nghĩa → Tạo mã → Tối ưu hóa.
Tối ưu hóa mã nhằm mục đích:
Difficulty 1/5 · 100 coins + a small bonus on first completion today
Tối ưu hóa cải thiện mã đã tạo ra (gộp hằng số, loại bỏ redundancy, sắp xếp lại cho pipeline).
Ví dụ minh họa: giai đoạn nào bắt lỗi nào
x ← 5 +: các token không phù hợp với ngữ pháp, một toán tử không có toán tử phải, nên phân tích cú pháp.x ← y + 1nơiychưa bao giờ được khai báo: biểu thức đúng về mặt cú pháp nhưng sai về ý nghĩa, do đó cần phân tích ngữ nghĩa.IF a > b THEN OUTPUT akhông cóENDIF: phân tích cú pháp một lần nữa.- Một chương trình chạy và in ra giá trị trung bình sai: không giai đoạn nào bắt được. Đó là lỗi logic, và chỉ có thử nghiệm mới tìm ra. Hãy nêu tên giai đoạn và lý do tại sao các giai đoạn trước đó đã để nó lọt qua.
Nối mỗi dòng sai với giai đoạn trình biên dịch bắt được lỗi đó.
Difficulty 2/5 · 140 coins + a small bonus on first completion today
Cú pháp là hình thức, ngữ nghĩa là ý nghĩa, và một lỗi logic hợp lệ về cả hai mặt nhưng sai về mục đích.
Ví dụ minh họa: so sánh hai công cụ dịch
- Nêu hai điểm khác biệt giữa cách trình biên dịch và trình giải thích xử lý một chương trình. [4]
- Trình biên dịch dịch toàn bộ chương trình trước khi chạy và tạo ra một file thực thi, sau đó chạy mà không cần trình biên dịch; trình giải thích dịch và thực thi từng câu lệnh một và tạo ra không có file thực thi, nên trình giải thích phải có mặt trong mỗi lần chạy.
- Trình biên dịch báo cáo tất cả các lỗi cùng nhau sau khi dịch; trình giải thích báo cáo lỗi đầu tiên khi đến dòng đó và sau đó dừng lại.
- Mỗi điểm là một cặp: hãy nói cái này làm gì và cái kia làm gì thay thế.
Điểm số dễ mất
- Trình giải thích tạo ra không có phiên bản đã dịch. Đó chính là cụm từ mà chương trình học sử dụng và điểm số mà nó trao.
- Bộ phân tích từ vựng tạo ra tokens và loại bỏ khoảng trắng và chú thích; nó không kiểm tra xem chương trình có hợp lệ hay không.
- Cú pháp là hình thức, ngữ nghĩa là ý nghĩa. Một biến chưa khai báo là lỗi ngữ nghĩa, không phải lỗi cú pháp.
- Tối ưu hóa không được thay đổi những gì chương trình làm, chỉ tốc độ hoặc độ gọn gàng của việc đó.
Bạn đã nắm vững
- một trình giải thích dịch và thực thi từng câu lệnh một, tạo ra không có file thực thi, báo cáo lỗi đầu tiên tại dòng đó, và dịch lại trong mỗi lần chạy
- Phân tích từ (lexeme) tạo ra các token và loại bỏ khoảng trắng cùng chú thích; phân tích cú pháp kiểm tra ngữ pháp và xây dựng cây cú pháp trừu tượng, bắt lỗi cú pháp
- Phân tích ngữ nghĩa kiểm tra ý nghĩa: các khai báo, kiểu dữ liệu, số lượng tham số truyền vào
- Sinh mã phát sinh mã máy và tối ưu hóa cải thiện hiệu suất mà không làm thay đổi hành vi, tạo ra một file thực thi độc lập