Một dịch giả là... Các loại dịch giả. Chuyển đổi và phát sóng chương trình. Nếu tập hợp các trạng thái kết quả không chứa xung đột LR(1) và do đó cho phép xây dựng trình phân tích cú pháp LR(1), thì ngữ pháp được cho là có thuộc tính LALR(1). Mục đích

Người phiên dịch (English Translator – phiên dịch viên) là một chương trình dịch thuật. Nó chuyển đổi một chương trình được viết bằng một trong các ngôn ngữ cấp cao thành chương trình bao gồm các lệnh máy. Người dịch cũng thường chẩn đoán lỗi, tạo từ điển mã định danh, tạo văn bản chương trình để in, v.v. Ngôn ngữ mà chương trình đầu vào được trình bày được gọi là ngôn ngữ nguồn và chính chương trình đó được gọi là mã nguồn. Ngôn ngữ đầu ra được gọi là ngôn ngữ đích hoặc mã đối tượng.

Nhìn chung, khái niệm dịch thuật không chỉ áp dụng cho các ngôn ngữ lập trình mà còn cho các ngôn ngữ khác - cả ngôn ngữ máy tính chính thức (như ngôn ngữ đánh dấu như HTML) và ngôn ngữ tự nhiên (tiếng Nga, tiếng Anh, v.v.).

Các loại dịch giả

    Hộp thoại. Cung cấp việc sử dụng ngôn ngữ lập trình ở chế độ chia sẻ thời gian.

    Định hướng cú pháp (điều khiển cú pháp). Nhận làm đầu vào mô tả cú pháp và ngữ nghĩa của ngôn ngữ và văn bản trong ngôn ngữ được mô tả, được dịch theo mô tả đã cho.

    Đường chuyền đơn. Tạo thành một mô-đun đối tượng trong một lần xem tuần tự của chương trình nguồn.

    Nhiều đường chuyền. Tạo thành một mô-đun đối tượng qua một số khung nhìn của chương trình nguồn.

    Tối ưu hóa. Thực hiện tối ưu hóa mã trong mô-đun đối tượng được tạo.

    Bài kiểm tra. Một tập hợp các lệnh macro hợp ngữ cho phép bạn thiết lập các quy trình gỡ lỗi khác nhau trong các chương trình được viết bằng hợp ngữ.

    Mặt sau. Đối với một chương trình bằng mã máy, nó tạo ra một chương trình tương đương bằng bất kỳ ngôn ngữ lập trình nào (xem: trình dịch ngược, trình dịch ngược).

Trình dịch được thực hiện như trình biên dịch hoặc trình thông dịch. Về mặt thực hiện công việc, trình biên dịch và trình thông dịch khác nhau đáng kể.

Trình biên dịch (Trình biên dịch tiếng Anh - trình biên dịch, trình thu thập) đọc toàn bộ chương trình, dịch nó và tạo ra một phiên bản hoàn chỉnh của chương trình bằng ngôn ngữ máy, sau đó được thực thi. Thông tin đầu vào của trình biên dịch (mã nguồn) là mô tả thuật toán hoặc chương trình bằng ngôn ngữ hướng vấn đề và đầu ra của trình biên dịch là mô tả tương đương của thuật toán trong ngôn ngữ hướng máy (mã đối tượng).

Các loại trình biên dịch

    Vector hóa. Dịch mã nguồn thành mã máy trên máy tính được trang bị bộ xử lý vector.

    Linh hoạt. Được thiết kế theo kiểu mô-đun, được điều khiển bởi các bảng và được lập trình bằng ngôn ngữ cấp cao hoặc được triển khai bằng trình biên dịch các trình biên dịch.

    Hộp thoại. Xem: dịch đối thoại.

    Tăng dần. Truyền lại các đoạn chương trình và phần bổ sung vào nó mà không cần biên dịch lại toàn bộ chương trình.

    Giải thích (từng bước). Tuần tự thực hiện việc biên dịch độc lập từng câu lệnh (lệnh) riêng lẻ của chương trình nguồn.

    Trình biên dịch của các trình biên dịch. Trình dịch chấp nhận mô tả chính thức của ngôn ngữ lập trình và tạo trình biên dịch cho ngôn ngữ đó.

    Gỡ lỗi. Loại bỏ một số loại lỗi cú pháp.

    Người dân. Nó nằm vĩnh viễn trong RAM và có sẵn để sử dụng lại cho nhiều tác vụ.

    Tự biên soạn. Được viết bằng cùng ngôn ngữ mà chương trình phát sóng được thực hiện.

    Phổ quát. Dựa trên mô tả chính thức về cú pháp và ngữ nghĩa của ngôn ngữ đầu vào. Các thành phần của trình biên dịch như vậy là: kernel, bộ tải cú pháp và ngữ nghĩa.

Mục đích và mục tiêu của môn học. Các khái niệm và định nghĩa cơ bản. Đặc điểm chung của ngôn ngữ lập trình và trình dịch. Cấu trúc tổng quát của trình dịch. Tùy chọn tương tác của các khối dịch.

Mục đích và mục tiêu của môn học

Hiện nay, các ngôn ngữ nhân tạo sử dụng cách biểu diễn văn bản để mô tả một lĩnh vực chủ đề được sử dụng rộng rãi không chỉ trong lập trình mà còn trong các lĩnh vực khác. Với sự trợ giúp của họ, cấu trúc của tất cả các loại tài liệu, thế giới ảo ba chiều, giao diện người dùng đồ họa và nhiều đối tượng khác được sử dụng trong mô hình và trong thế giới thực sẽ được mô tả. Để các mô tả văn bản này được soạn thảo chính xác, sau đó được nhận dạng và giải thích chính xác, các phương pháp phân tích và chuyển đổi đặc biệt của chúng sẽ được sử dụng. Các phương pháp này dựa trên lý thuyết về ngôn ngữ và ngữ pháp hình thức, cũng như lý thuyết về máy tự động. Hệ thống phần mềm được thiết kế để phân tích và giải thích văn bản được gọi là dịch giả.

Mặc dù thực tế cho đến nay có hàng nghìn ngôn ngữ khác nhau và trình dịch của chúng đã được phát triển, quá trình tạo ra các ứng dụng mới trong lĩnh vực này vẫn không dừng lại. Điều này là do sự phát triển của công nghệ sản xuất hệ thống máy tính và nhu cầu giải quyết các vấn đề ứng dụng ngày càng phức tạp. Ngoài ra, các yếu tố của lý thuyết ngôn ngữ và ngữ pháp hình thức có thể áp dụng trong các lĩnh vực đa dạng khác, chẳng hạn như khi mô tả cấu trúc dữ liệu, tệp, hình ảnh, được trình bày không phải ở dạng văn bản mà ở định dạng nhị phân. Những phương pháp này cũng hữu ích khi phát triển các trình dịch của riêng bạn, ngay cả khi đã tồn tại các phương pháp tương tự. Sự phát triển như vậy có thể do nhiều nguyên nhân, đặc biệt là do hạn chế về chức năng, thiếu tính nội địa hóa và hiệu quả thấp. Ví dụ, một trong những phát triển mới nhất của Microsoft là ngôn ngữ lập trình C#, và một trong những lý do tạo ra nó là mong muốn giảm mức độ phổ biến của ngôn ngữ lập trình Java. Có nhiều ví dụ khác trong đó việc phát triển dịch giả của riêng bạn có thể phù hợp. Do đó, các nguyên tắc cơ bản của lý thuyết ngôn ngữ và ngữ pháp chính thức, cũng như các phương pháp thực tế để phát triển người dịch, nằm ở nền tảng của giáo dục kỹ thuật về khoa học máy tính và khoa học máy tính.

Tài liệu được đề xuất đề cập đến những điều cơ bản của phương pháp phát triển người dịch và chứa thông tin cần thiết để nghiên cứu logic hoạt động của họ và bộ máy toán học được sử dụng (lý thuyết về ngôn ngữ hình thức và ngữ pháp hình thức, ngôn ngữ kim loại). Nó được sử dụng như một phần của các khóa học giảng dạy kéo dài một học kỳ cho các chuyên ngành khác nhau tại Khoa Tin học và Khoa học Máy tính của Đại học Kỹ thuật Bang Krasnoyarsk. Trong quá trình làm việc trong phòng thí nghiệm, việc làm quen trực tiếp với các phương pháp tạo dịch giả riêng lẻ được thực hiện.

Mục đích của môn học: cung cấp kiến ​​thức cơ bản về lý thuyết ngôn ngữ và ngữ pháp hình thức, lý thuyết về automata, phương pháp phát triển người dịch.

Để đạt được mục tiêu này, các nhiệm vụ sau được giải quyết trong quá trình giảng dạy môn học:

  1. Khóa học nghiên cứu các nguyên tắc chung về tổ chức quá trình dịch thuật và cơ cấu của người dịch. Các nguyên tắc cơ bản của lý thuyết xây dựng dịch giả được nghiên cứu.
  2. Trong các lớp học trong phòng thí nghiệm và trong quá trình làm việc độc lập, kiến ​​thức lý thuyết thu được sẽ được củng cố một cách thực tế: một trình dịch cho ngôn ngữ lập trình đơn giản được phát triển.

Các khái niệm và định nghĩa cơ bản

Hầu hết các định nghĩa được xem xét đều được mượn từ [ARNFTS Từ điển giải thích Anh-Nga-Đức-Pháp về công nghệ máy tính và xử lý dữ liệu, 4132 thuật ngữ. Dưới. biên tập. A.A. Dorodnitsyna. M.: 1978. 416 trang.) ].

Người phiên dịch - một chương trình dịch vụ chuyển đổi chương trình nguồn được cung cấp bằng ngôn ngữ lập trình đầu vào thành chương trình làm việc được cung cấp bằng ngôn ngữ đối tượng.

Định nghĩa trên áp dụng cho tất cả các loại chương trình phát sóng. Tuy nhiên, mỗi chương trình này có thể có những đặc điểm riêng trong việc tổ chức quá trình phát sóng. Hiện nay, người dịch được chia làm 3 nhóm chính: người biên dịch, người biên dịch và người phiên dịch.

Người lắp ráp - một chương trình tiện ích hệ thống chuyển đổi các cấu trúc biểu tượng thành các hướng dẫn ngôn ngữ máy. Một tính năng cụ thể của trình biên dịch mã là chúng thực hiện dịch nguyên văn một lệnh ký hiệu thành một lệnh máy. Do đó, hợp ngữ (còn gọi là mã tự động) được thiết kế để tạo điều kiện thuận lợi cho việc nhận thức hệ thống lệnh của máy tính và tăng tốc độ lập trình trong hệ thống lệnh này. Việc lập trình viên ghi nhớ ký hiệu dễ nhớ của các lệnh máy sẽ dễ dàng hơn nhiều so với mã nhị phân của chúng. Do đó, lợi ích chính đạt được không phải bằng cách tăng sức mạnh của các mệnh lệnh riêng lẻ mà bằng cách tăng hiệu quả nhận thức của chúng.

Đồng thời, hợp ngữ, ngoài các tính chất tương tự của lệnh máy, còn chứa nhiều lệnh bổ sung, đặc biệt là tạo điều kiện thuận lợi cho việc quản lý tài nguyên máy tính, viết các đoạn lặp lại và xây dựng các chương trình đa mô-đun. Do đó, khả năng biểu đạt của ngôn ngữ phong phú hơn nhiều so với chỉ một ngôn ngữ mã hóa tượng trưng, ​​giúp cải thiện đáng kể hiệu quả lập trình.

Trình biên dịch - là một chương trình dịch vụ dịch chương trình được viết bằng ngôn ngữ lập trình nguồn sang ngôn ngữ máy. Giống như trình biên dịch chương trình, trình biên dịch chuyển đổi một chương trình từ ngôn ngữ này sang ngôn ngữ khác (thường là sang ngôn ngữ của một máy tính cụ thể). Đồng thời, các lệnh ngôn ngữ nguồn khác biệt đáng kể về tổ chức và sức mạnh so với các lệnh ngôn ngữ máy. Có những ngôn ngữ trong đó một lệnh của ngôn ngữ nguồn được dịch sang 7-10 lệnh máy. Tuy nhiên, cũng có những ngôn ngữ trong đó mỗi lệnh có thể có 100 lệnh máy trở lên (ví dụ: Prolog). Ngoài ra, các ngôn ngữ nguồn thường sử dụng cách nhập dữ liệu nghiêm ngặt, được thực hiện thông qua mô tả sơ bộ của chúng. Lập trình có thể không dựa vào việc mã hóa thuật toán mà dựa vào việc suy nghĩ cẩn thận về các cấu trúc hoặc lớp dữ liệu. Quá trình dịch từ các ngôn ngữ như vậy thường được gọi là biên dịch và ngôn ngữ nguồn thường được phân loại là ngôn ngữ lập trình cấp cao (hoặc ngôn ngữ cấp cao). Việc trừu tượng hóa ngôn ngữ lập trình khỏi hệ thống lệnh máy tính đã dẫn đến việc tạo ra nhiều loại ngôn ngữ độc lập tập trung vào việc giải quyết các vấn đề cụ thể. Ngôn ngữ đã xuất hiện để tính toán khoa học, tính toán kinh tế, truy cập cơ sở dữ liệu và các ngôn ngữ khác.

Thông dịch viên - một chương trình hoặc thiết bị thực hiện việc dịch thuật và thực thi chương trình gốc theo từng người vận hành. Không giống như trình biên dịch, trình thông dịch không tạo ra chương trình ngôn ngữ máy làm đầu ra. Sau khi nhận ra một lệnh trong ngôn ngữ nguồn, nó sẽ thực thi lệnh đó ngay lập tức. Cả trình biên dịch và trình thông dịch đều sử dụng cùng một phương pháp để phân tích mã nguồn của chương trình. Nhưng trình thông dịch cho phép bạn bắt đầu xử lý dữ liệu sau khi viết dù chỉ một lệnh. Điều này làm cho quá trình phát triển và gỡ lỗi chương trình trở nên linh hoạt hơn. Ngoài ra, việc không có mã máy đầu ra giúp không thể "làm lộn xộn" các thiết bị bên ngoài với các tệp bổ sung và bản thân trình thông dịch có thể khá dễ dàng thích ứng với bất kỳ kiến ​​​​trúc máy nào, chỉ phát triển nó một lần bằng ngôn ngữ lập trình được sử dụng rộng rãi. Vì vậy, các ngôn ngữ thông dịch như Java Script và VB Script đã trở nên phổ biến. Nhược điểm của trình thông dịch là tốc độ thực hiện chương trình thấp. Thông thường, các chương trình thông dịch chạy chậm hơn 50 đến 100 lần so với các chương trình gốc.

Giả lập - một chương trình hoặc phần mềm và công cụ phần cứng cung cấp khả năng thực thi trên một máy tính nhất định một chương trình sử dụng mã hoặc phương pháp thực hiện các hoạt động khác với máy tính nhất định mà không cần lập trình lại. Trình mô phỏng tương tự như trình thông dịch ở chỗ nó trực tiếp thực thi chương trình được viết bằng một ngôn ngữ nhất định. Tuy nhiên, thông thường nhất đó là ngôn ngữ máy hoặc mã trung gian. Cả hai đều thể hiện các hướng dẫn ở dạng mã nhị phân có thể được thực thi ngay sau khi mã hoạt động được nhận dạng. Không giống như các chương trình văn bản, không cần nhận dạng cấu trúc chương trình hoặc chọn toán hạng.

Trình giả lập được sử dụng khá thường xuyên cho nhiều mục đích khác nhau. Ví dụ: khi phát triển hệ thống máy tính mới, trước tiên, một trình mô phỏng sẽ được tạo để chạy các chương trình được phát triển cho các máy tính chưa tồn tại. Điều này cho phép bạn đánh giá hệ thống lệnh và phát triển phần mềm cơ bản ngay cả trước khi phần cứng tương ứng được tạo ra.

Rất thường xuyên, trình giả lập được sử dụng để chạy các chương trình cũ trên máy tính mới. Thông thường, các máy tính mới hơn sẽ nhanh hơn và có thiết bị ngoại vi tốt hơn. Điều này cho phép bạn mô phỏng các chương trình cũ hiệu quả hơn so với việc chạy chúng trên các máy tính cũ. Một ví dụ về phương pháp này là việc phát triển trình giả lập cho máy tính gia đình ZX Spectrum với bộ vi xử lý Z80. Vẫn có những người thích chơi trên một trình giả lập có chương trình trò chơi lỗi thời nhưng vẫn không mất đi sức hấp dẫn trước đây. Trình mô phỏng cũng có thể được sử dụng như một giải pháp tương tự rẻ hơn của các hệ thống máy tính hiện đại, đồng thời cung cấp hiệu suất chấp nhận được tương đương với các mô hình cấp thấp của một họ kiến ​​trúc nhất định. Một ví dụ là trình giả lập của các máy tính tương thích với IBM PC được triển khai trên các máy tính Apple mạnh hơn. Một số trình giả lập được viết cho IBM PC thay thế thành công nhiều máy chơi game khác nhau.

Trình mô phỏng biểu diễn trung gian cũng như trình thông dịch có thể dễ dàng chuyển từ kiến ​​trúc máy tính này sang kiến ​​trúc máy tính khác, cho phép tạo ra phần mềm di động. Chính đặc tính này đã định trước sự thành công của ngôn ngữ lập trình Java, từ đó chương trình được dịch sang mã trung gian. Máy ảo Java thực thi mã này không gì khác hơn là một trình giả lập chạy trong bất kỳ hệ điều hành hiện đại nào.

Bộ chuyển mã - một chương trình hoặc thiết bị phần mềm dịch các chương trình được viết bằng ngôn ngữ máy của một máy tính sang các chương trình bằng ngôn ngữ máy của máy tính khác. Nếu trình mô phỏng là một trình tương tự kém thông minh hơn của trình thông dịch thì bộ chuyển mã sẽ hoạt động với cùng khả năng so với trình biên dịch. Tương tự, mã máy nguồn (và thường là nhị phân) hoặc biểu diễn trung gian được chuyển đổi thành mã tương tự khác bằng một lệnh duy nhất và không có bất kỳ phân tích chung nào về cấu trúc của chương trình nguồn. Bộ chuyển mã rất hữu ích khi chuyển các chương trình từ kiến ​​trúc máy tính này sang kiến ​​trúc máy tính khác. Chúng cũng có thể được sử dụng để tái tạo lại văn bản chương trình ngôn ngữ cấp cao từ mã nhị phân hiện có.

Bộ xử lý vĩ mô - một chương trình thay thế một chuỗi ký tự bằng một chuỗi ký tự khác[Màu nâu]. Đây là một loại trình biên dịch. Nó tạo ra văn bản đầu ra bằng cách xử lý các phần chèn đặc biệt nằm trong văn bản nguồn. Những phần chèn này được thiết kế theo cách đặc biệt và thuộc về cấu trúc của một ngôn ngữ được gọi là ngôn ngữ vĩ mô. Bộ vi xử lý thường được sử dụng làm tiện ích bổ sung cho các ngôn ngữ lập trình, làm tăng chức năng của hệ thống lập trình. Hầu hết mọi trình biên dịch chương trình đều có bộ xử lý vĩ mô, giúp tăng hiệu quả phát triển các chương trình máy. Những hệ thống lập trình như vậy thường được gọi là macroassemblers.

Bộ xử lý vĩ mô cũng được sử dụng với các ngôn ngữ cấp cao. Chúng tăng cường chức năng của các ngôn ngữ như PL/1, C, C++. Bộ xử lý macro đặc biệt được sử dụng rộng rãi trong C và C++, giúp việc viết chương trình trở nên dễ dàng hơn. Một ví dụ về việc sử dụng rộng rãi các bộ xử lý vĩ mô là thư viện lớp Microsoft Foundation Class (MFC). Nó triển khai bản đồ thông báo và các đối tượng chương trình khác thông qua việc chèn macro. Đồng thời, bộ xử lý vĩ mô tăng hiệu quả lập trình mà không làm thay đổi cú pháp và ngữ nghĩa của ngôn ngữ.

Cú pháp - một bộ quy tắc của một ngôn ngữ nhất định xác định sự hình thành các thành phần của nó. Nói cách khác, điều này một bộ quy tắc để hình thành các chuỗi ký tự có ý nghĩa về mặt ngữ nghĩa trong một ngôn ngữ nhất định. Cú pháp được xác định bằng cách sử dụng các quy tắc mô tả các khái niệm của ngôn ngữ. Ví dụ về các khái niệm là: biến, biểu thức, toán tử, thủ tục. Trình tự các khái niệm và cách sử dụng được chấp nhận của chúng trong các quy tắc sẽ xác định cấu trúc đúng về mặt cú pháp tạo nên chương trình. Đó là thứ bậc của các đối tượng chứ không phải cách chúng tương tác với nhau được xác định thông qua cú pháp. Ví dụ: một câu lệnh chỉ có thể xuất hiện trong một thủ tục, một biểu thức trong câu lệnh, một biến có thể bao gồm tên và các chỉ mục tùy chọn, v.v. Cú pháp không liên quan đến những hiện tượng như vậy trong chương trình như “nhảy đến một nhãn không tồn tại” hoặc “một biến có tên đã cho không được xác định”. Đây là những gì ngữ nghĩa làm.

Ngữ nghĩa - các quy tắc và điều kiện xác định mối quan hệ giữa các thành phần ngôn ngữ và ý nghĩa ngữ nghĩa của chúng, cũng như việc giải thích ý nghĩa của các cấu trúc cú pháp của ngôn ngữ. Các đối tượng của ngôn ngữ lập trình không chỉ được đặt trong văn bản theo một hệ thống phân cấp nhất định mà còn được liên kết với nhau thông qua các khái niệm khác tạo thành các liên kết khác nhau. Ví dụ: một biến mà cú pháp xác định vị trí hợp lệ chỉ trong các khai báo và một số câu lệnh, có một loại cụ thể, có thể được sử dụng với một số thao tác giới hạn, có địa chỉ, kích thước và phải được khai báo trước khi có thể. được sử dụng trong chương trình.

Máy phân tích cú pháp - một thành phần trình biên dịch kiểm tra các câu lệnh nguồn xem có tuân thủ các quy tắc cú pháp và ngữ nghĩa của một ngôn ngữ lập trình nhất định không. Mặc dù có tên như vậy nhưng bộ phân tích vẫn kiểm tra cả cú pháp và ngữ nghĩa. Nó bao gồm một số khối, mỗi khối giải quyết các vấn đề riêng của nó. Nó sẽ được thảo luận chi tiết hơn khi mô tả cấu trúc của người dịch.

Đặc điểm chung của ngôn ngữ lập trình và trình dịch

Các ngôn ngữ lập trình khá khác nhau về mục đích, cấu trúc, độ phức tạp về ngữ nghĩa và phương pháp triển khai. Điều này áp đặt các tính năng cụ thể của riêng nó vào sự phát triển của các dịch giả cụ thể.

Ngôn ngữ lập trình là công cụ để giải quyết các vấn đề trong các lĩnh vực chủ đề khác nhau, xác định các đặc điểm cụ thể của tổ chức và sự khác biệt về mục đích của chúng. Các ví dụ bao gồm các ngôn ngữ như Fortran, thiên về tính toán khoa học, C, dành cho lập trình hệ thống, Prolog, mô tả hiệu quả các vấn đề suy luận và Lisp, được sử dụng để xử lý danh sách đệ quy. Những ví dụ này có thể được tiếp tục. Mỗi lĩnh vực chủ đề đặt ra những yêu cầu riêng về cách tổ chức ngôn ngữ. Do đó, chúng ta có thể lưu ý đến sự đa dạng của các hình thức biểu diễn toán tử và biểu thức, sự khác biệt trong tập hợp các phép toán cơ bản và sự giảm hiệu quả lập trình khi giải các bài toán không liên quan đến môn học. Sự khác biệt về ngôn ngữ cũng được phản ánh trong cấu trúc của người dịch. Lisp và Prolog thường được thực thi ở chế độ diễn giải do chúng sử dụng việc tạo các kiểu dữ liệu động trong quá trình tính toán. Trình dịch Fortran có đặc điểm là tối ưu hóa mạnh mẽ mã máy kết quả, điều này có thể thực hiện được nhờ ngữ nghĩa tương đối đơn giản của cấu trúc ngôn ngữ - đặc biệt là do không có cơ chế đặt tên biến thay thế thông qua con trỏ hoặc tham chiếu. Sự hiện diện của con trỏ trong ngôn ngữ C đặt ra những yêu cầu cụ thể cho việc cấp phát bộ nhớ động.

Cấu trúc của một ngôn ngữ đặc trưng cho mối quan hệ phân cấp giữa các khái niệm của nó, được mô tả bằng các quy tắc cú pháp. Các ngôn ngữ lập trình có thể khác nhau rất nhiều trong cách tổ chức các khái niệm riêng lẻ và mối quan hệ giữa chúng. Ngôn ngữ lập trình PL/1 cho phép lồng các thủ tục và hàm tùy ý, trong khi ở C tất cả các hàm phải ở mức lồng bên ngoài. Ngôn ngữ C++ cho phép khai báo các biến tại bất kỳ điểm nào trong chương trình trước khi sử dụng lần đầu, trong khi trong Pascal, các biến phải được xác định trong một vùng khai báo đặc biệt. Đi xa hơn nữa là PL/1, cho phép khai báo một biến sau khi nó được sử dụng. Hoặc bạn có thể bỏ qua toàn bộ mô tả và sử dụng các quy tắc mặc định. Tùy thuộc vào quyết định được đưa ra, người dịch có thể phân tích chương trình theo một hoặc nhiều lượt, điều này ảnh hưởng đến tốc độ dịch.

Ngữ nghĩa của các ngôn ngữ lập trình rất khác nhau. Chúng khác nhau không chỉ ở các tính năng triển khai của các hoạt động riêng lẻ mà còn ở các mô hình lập trình, những yếu tố quyết định sự khác biệt cơ bản trong phương pháp phát triển chương trình. Các chi tiết cụ thể của việc thực hiện các hoạt động có thể liên quan đến cả cấu trúc của dữ liệu đang được xử lý và các quy tắc xử lý cùng loại dữ liệu. Các ngôn ngữ như PL/1 và APL hỗ trợ các phép toán ma trận và vectơ. Hầu hết các ngôn ngữ làm việc chủ yếu với các đại lượng vô hướng, cung cấp các thủ tục và hàm do các lập trình viên viết để xử lý mảng. Nhưng ngay cả khi thực hiện thao tác cộng hai số nguyên, các ngôn ngữ như C và Pascal có thể hoạt động khác.

Cùng với lập trình thủ tục truyền thống, còn được gọi là lập trình mệnh lệnh, còn có các mô hình như lập trình chức năng, lập trình logic và lập trình hướng đối tượng. Tôi hy vọng rằng mô hình lập trình tham số thủ tục mà tôi đề xuất sẽ có vị trí trong loạt bài này [Legalov2000]. Cấu trúc của các khái niệm và đối tượng của ngôn ngữ phụ thuộc rất nhiều vào mô hình đã chọn, điều này cũng ảnh hưởng đến việc triển khai của người dịch.

Ngay cả cùng một ngôn ngữ cũng có thể được thực hiện theo nhiều cách. Điều này là do lý thuyết về ngữ pháp hình thức cho phép sử dụng các phương pháp phân tích cú pháp khác nhau đối với cùng một câu. Theo đó, người dịch có thể thu được cùng một kết quả (chương trình đối tượng) từ văn bản nguồn gốc theo nhiều cách khác nhau.

Đồng thời, tất cả các ngôn ngữ lập trình đều có một số đặc điểm và thông số chung. Điểm chung này cũng quyết định nguyên tắc tổ chức dịch giả giống nhau cho tất cả các ngôn ngữ.

  1. Ngôn ngữ lập trình được thiết kế để giúp việc lập trình trở nên dễ dàng hơn. Do đó, các toán tử và cấu trúc dữ liệu của chúng mạnh hơn so với các ngôn ngữ máy.
  2. Để tăng khả năng hiển thị của các chương trình, thay vì mã số, các biểu diễn bằng ký hiệu hoặc đồ họa của cấu trúc ngôn ngữ được sử dụng, thuận tiện hơn cho nhận thức của con người.
  3. Đối với bất kỳ ngôn ngữ nào, nó được xác định:
  • Rất nhiều ký hiệu có thể được sử dụng để viết chương trình (bảng chữ cái) chính xác, các phần tử cơ bản.
  • Rất nhiều chương trình đúng (cú pháp).
  • "Ý nghĩa" của mọi chương trình chính xác (ngữ nghĩa).

Bất kể đặc điểm cụ thể của ngôn ngữ, bất kỳ người dịch nào cũng có thể được coi là bộ chuyển đổi chức năng F, cung cấp ánh xạ duy nhất từ ​​X sang Y, trong đó X là chương trình ở ngôn ngữ nguồn, Y là chương trình ở ngôn ngữ đầu ra. Do đó, bản thân quá trình dịch thuật có thể được trình bày chính thức khá đơn giản và rõ ràng:

Về mặt hình thức, mỗi chương trình X đúng là một chuỗi ký hiệu từ bảng chữ cái A nào đó, được chuyển đổi thành chuỗi Y tương ứng, bao gồm các ký hiệu của bảng chữ cái B.

Một ngôn ngữ lập trình, giống như bất kỳ hệ thống phức tạp nào, được xác định thông qua hệ thống phân cấp các khái niệm xác định mối quan hệ giữa các phần tử của nó. Các khái niệm này được kết nối với nhau theo các quy tắc cú pháp. Mỗi chương trình được xây dựng theo các quy tắc này đều có cấu trúc phân cấp tương ứng.

Về vấn đề này, các đặc điểm chung sau đây có thể được phân biệt bổ sung cho tất cả các ngôn ngữ và chương trình của chúng: mỗi ngôn ngữ phải chứa các quy tắc cho phép tạo chương trình tương ứng với ngôn ngữ này hoặc nhận ra sự tương ứng giữa các chương trình viết và một ngôn ngữ nhất định.

Mối quan hệ giữa cấu trúc chương trình và ngôn ngữ lập trình được gọi là ánh xạ cú pháp.

Ví dụ: hãy xem xét mối quan hệ giữa cấu trúc phân cấp và chuỗi ký hiệu xác định biểu thức số học sau:

Trong hầu hết các ngôn ngữ lập trình, biểu thức này xác định hệ thống phân cấp của các đối tượng chương trình, có thể được hiển thị dưới dạng cây (Hình 1.1.):

Các vòng tròn biểu thị các ký hiệu được sử dụng làm cấu trúc cơ bản và các hình chữ nhật biểu thị các khái niệm tổng hợp có cấu trúc phân cấp và có thể đệ quy. Hệ thống phân cấp này được xác định bằng cách sử dụng các quy tắc cú pháp được viết bằng một ngôn ngữ đặc biệt gọi là kim loại (các ngôn ngữ kim loại sẽ được thảo luận chi tiết hơn khi nghiên cứu các ngữ pháp chính thức):

<выражение> ::= <слагаемое> | <выражение> + <слагаемое>

<слагаемое> ::= <множитель> | <слагаемое> * <множитель>

<множитель> ::= <буква> | (<выражение>)

<буква>

Ghi chú. Dấu "::=" được đọc là "đây là". Ống "|" đọc như "hoặc".

Nếu các quy tắc được viết khác đi, cấu trúc phân cấp sẽ thay đổi. Ví dụ: chúng ta có thể đưa ra cách viết quy tắc sau:

<выражение> ::= <операнд> | <выражение> + < операнд > | <выражение> * < операнд >

<операнд> ::= <буква> | (<выражение>)

<буква>::= một | b | c | d | tôi | f | g | h | tôi | j | k | tôi | m | n | o | p | q | r | s | t | bạn | v | w | x | y | z

Là kết quả của việc phân tích cú pháp của cùng một biểu thức số học, một cấu trúc phân cấp sẽ được xây dựng, như trong Hình 2. 1.2.


Cần lưu ý rằng cấu trúc phân cấp trong trường hợp chung có thể không liên quan đến ngữ nghĩa của biểu thức. Trong cả hai trường hợp, mức độ ưu tiên của các phép toán có thể được thực hiện theo các quy tắc được chấp nhận chung, khi phép nhân đi trước phép cộng (hoặc ngược lại, tất cả các phép toán có thể có cùng mức độ ưu tiên theo bất kỳ bộ quy tắc nào). Tuy nhiên, cấu trúc đầu tiên rõ ràng hỗ trợ việc triển khai thêm mức độ ưu tiên được chấp nhận chung, trong khi cấu trúc thứ hai phù hợp hơn để triển khai các hoạt động có cùng mức độ ưu tiên và thực hiện chúng từ phải sang trái.

Quá trình tìm cấu trúc cú pháp của một chương trình nhất định được gọi là phân tích cú pháp.

Cấu trúc cú pháp đúng trong ngôn ngữ này có thể không chính xác trong ngôn ngữ khác. Ví dụ: trong ngôn ngữ Forth, biểu thức đã cho sẽ không được nhận dạng. Tuy nhiên, đối với ngôn ngữ này biểu thức hậu tố đúng là:

Cấu trúc cú pháp của nó được mô tả bởi các quy tắc:

<выражение> ::= <буква> | <операнд> <операнд> <операция>

< операнд > ::= < буква > | < выражение >

< операция > ::= + | *

<буква>::= một | b | c | d | tôi | f | g | h | tôi | j | k | tôi | m | n | o | p | q | r | s | t | bạn | v | w | x | y | z

Cây phân cấp xác định cấu trúc cú pháp được trình bày trong Hình. 1.3.

Một đặc điểm đặc trưng khác của tất cả các ngôn ngữ là ngữ nghĩa của chúng. Nó xác định ý nghĩa của các phép toán ngôn ngữ và tính chính xác của các toán hạng. Các chuỗi có cùng cấu trúc cú pháp trong các ngôn ngữ lập trình khác nhau có thể khác nhau về ngữ nghĩa (ví dụ: được quan sát thấy trong C++, Pascal, Basic cho đoạn trên của biểu thức số học).

Kiến thức về ngữ nghĩa của một ngôn ngữ cho phép bạn tách nó khỏi cú pháp của nó và sử dụng nó để chuyển đổi sang ngôn ngữ khác (để tạo mã).

Mô tả ngữ nghĩa và thừa nhận tính chính xác của nó thường là phần tốn nhiều công sức và khối lượng nhất của người dịch, vì cần phải liệt kê và phân tích nhiều lựa chọn để kết hợp hợp lệ các phép toán và toán hạng.

Cấu trúc dịch tổng quát

Các thuộc tính và mẫu chung vốn có ở cả các ngôn ngữ lập trình và trình dịch khác nhau từ các ngôn ngữ này. Họ trải qua các quá trình tương tự để chuyển đổi văn bản nguồn. Mặc dù thực tế là sự tương tác của các quy trình này có thể được tổ chức theo nhiều cách khác nhau, nhưng vẫn có thể xác định được các chức năng mà việc triển khai của chúng dẫn đến các kết quả giống nhau. Chúng ta hãy gọi các chức năng đó là các giai đoạn của quá trình dịch thuật.

Do sự giống nhau giữa trình biên dịch và trình thông dịch, chúng ta hãy xem xét các giai đoạn tồn tại trong trình biên dịch. Nó nhấn mạnh:

  1. Giai đoạn phân tích từ vựng
  2. Giai đoạn phân tích cú pháp bao gồm:
  • nhận biết cấu trúc cú pháp;
  • phân tích cú pháp ngữ nghĩa, trong đó công việc với các bảng được thực hiện, tạo ra biểu diễn ngữ nghĩa trung gian hoặc mô hình đối tượng của ngôn ngữ.
  • Giai đoạn tạo mã, trong đó:
    • phân tích ngữ nghĩa của các thành phần của một biểu diễn trung gian hoặc mô hình đối tượng của ngôn ngữ;
    • dịch một biểu diễn trung gian hoặc mô hình đối tượng thành mã đối tượng.

    Cùng với các giai đoạn chính của quá trình dịch thuật, cũng có thể có các giai đoạn bổ sung:

      2a. Giai đoạn thăm dò và tối ưu hóa biểu diễn trung gian, bao gồm:
    2a.1. phân tích tính đúng đắn của biểu diễn trung gian;
    2a.2. tối ưu hóa biểu diễn trung gian.
      3a. Giai đoạn tối ưu hóa mã đối tượng.

    Trình thông dịch khác ở chỗ giai đoạn tạo mã thường được thay thế bằng giai đoạn mô phỏng các phần tử của biểu diễn trung gian hoặc mô hình đối tượng của ngôn ngữ. Ngoài ra, trình thông dịch thường không tối ưu hóa cách biểu diễn trung gian mà ngay lập tức mô phỏng nó.

    Ngoài ra, có thể phân biệt quy trình phân tích và sửa lỗi tồn tại trong văn bản nguồn đã xử lý của chương trình là thống nhất cho tất cả các giai đoạn.

    Cấu trúc tổng quát của trình biên dịch, có tính đến các giai đoạn tồn tại trong nó, được trình bày trong Hình. 1.4.

    Nó bao gồm một bộ phân tích từ vựng, một bộ phân tích cú pháp, một bộ tạo mã và một bộ phân tích lỗi. Thay vì trình tạo mã, trình thông dịch sử dụng trình mô phỏng (Hình 1.5), trong đó, ngoài các phần tử của biểu diễn trung gian, dữ liệu nguồn được truyền vào đó. Đầu ra của trình mô phỏng là kết quả của các phép tính.

    Máy phân tích từ vựng (còn được gọi là máy quét) đọc chuỗi ký tự đầu vào và nhóm chúng thành các cấu trúc cơ bản gọi là từ vựng. Mỗi mã thông báo có một lớp và một ý nghĩa. Thông thường, các ứng cử viên cho vai trò từ vị là các cấu trúc ngôn ngữ cơ bản, ví dụ: mã định danh, số thực, chú thích. Mã thông báo kết quả được chuyển đến trình phân tích cú pháp. Máy quét không phải là một phần bắt buộc của người dịch. Tuy nhiên, nó cho phép bạn tăng hiệu quả của quá trình dịch thuật. Phân tích từ vựng được thảo luận chi tiết hơn trong chủ đề: “Tổ chức phân tích từ vựng”.

    Trình phân tích cú pháp phân tích chương trình nguồn bằng cách sử dụng các từ vựng đến, xây dựng cấu trúc cú pháp của chương trình và phân tích ngữ nghĩa với việc hình thành mô hình đối tượng của ngôn ngữ. Mô hình đối tượng thể hiện một cấu trúc cú pháp, được bổ sung bởi các mối quan hệ ngữ nghĩa giữa các khái niệm hiện có. Những kết nối này có thể là:

    • tham chiếu đến các biến, kiểu dữ liệu và tên thủ tục được đặt trong bảng tên;
    • các kết nối xác định trình tự thực hiện lệnh;
    • các kết nối xác định việc lồng các phần tử của mô hình đối tượng ngôn ngữ và các phần tử khác.

    Vì vậy, trình phân tích cú pháp là một khối dịch thuật khá phức tạp. Vì vậy, nó có thể được chia thành các thành phần sau:

    • nhận dạng;
    • khối phân tích ngữ nghĩa;
    • một mô hình đối tượng hoặc biểu diễn trung gian, bao gồm một bảng tên và cấu trúc cú pháp.

    Cấu trúc tổng quát của bộ phân tích cú pháp được hiển thị trong Hình. 1.6.

    Bộ nhận dạng nhận được một chuỗi mã thông báo và dựa vào đó, thực hiện phân tích cú pháp theo các quy tắc được sử dụng. Các mã thông báo, sau khi phân tích thành công các quy tắc, sẽ được chuyển đến bộ phân tích ngữ nghĩa, bộ phân tích này sẽ xây dựng một bảng tên và ghi lại các đoạn của cấu trúc cú pháp. Ngoài ra, các kết nối ngữ nghĩa bổ sung được ghi lại giữa bảng tên và cấu trúc cú pháp. Kết quả là một mô hình đối tượng của chương trình được hình thành, không bị ràng buộc bởi cú pháp của ngôn ngữ lập trình. Thông thường, thay vì một cấu trúc cú pháp sao chép hoàn toàn hệ thống phân cấp của các đối tượng ngôn ngữ, một cấu trúc tương tự đơn giản hóa của nó được tạo ra, được gọi là biểu diễn trung gian.

    Bộ phân tích lỗi nhận thông tin về các lỗi xảy ra trong các khối dịch khác nhau. Sử dụng thông tin nhận được, nó sẽ tạo ra tin nhắn cho người dùng. Ngoài ra, khối này có thể cố gắng sửa lỗi để tiếp tục phân tích cú pháp thêm. Anh ta cũng chịu trách nhiệm về các hành động liên quan đến việc hoàn thành đúng chương trình trong trường hợp không thể tiếp tục phát sóng.

    Trình tạo mã xây dựng mã máy đối tượng dựa trên phân tích mô hình đối tượng hoặc biểu diễn trung gian. Việc xây dựng mã đi kèm với phân tích ngữ nghĩa bổ sung liên quan đến nhu cầu chuyển đổi các lệnh tổng quát thành mã của một máy tính cụ thể. Ở giai đoạn phân tích như vậy, khả năng chuyển đổi cuối cùng đã được xác định và các phương án hiệu quả được lựa chọn. Bản thân việc tạo mã là việc mã hóa lại lệnh này sang lệnh khác.

    Tùy chọn tương tác của các khối dịch

    Việc tổ chức các quy trình dịch thuật quyết định việc thực hiện các giai đoạn chính có thể được thực hiện theo nhiều cách khác nhau. Điều này được xác định bởi các tùy chọn khác nhau cho sự tương tác của các khối dịch: bộ phân tích từ vựng, trình phân tích cú pháp và trình tạo mã. Mặc dù có cùng kết quả cuối cùng, nhưng các tùy chọn khác nhau để tương tác với các khối dịch sẽ cung cấp các tùy chọn khác nhau để lưu trữ dữ liệu trung gian. Có hai tùy chọn chính cho sự tương tác của các khối dịch:

    • tổ chức nhiều lượt, trong đó mỗi giai đoạn là một quy trình độc lập, chỉ chuyển quyền kiểm soát sang giai đoạn tiếp theo sau khi xử lý xong dữ liệu của nó;
    • tổ chức một lượt, trong đó tất cả các giai đoạn đại diện cho một quy trình duy nhất và truyền dữ liệu cho nhau theo từng đoạn nhỏ.

    Dựa trên hai tùy chọn chính, bạn cũng có thể tạo nhiều cách kết hợp khác nhau.

    Tổ chức tương tác nhiều lượt giữa các khối dịch thuật

    Phiên bản tương tác của các khối này, sử dụng trình biên dịch làm ví dụ, được trình bày trong Hình 1.7.


    Bộ phân tích từ vựng xử lý hoàn toàn văn bản nguồn, tạo thành chuỗi đầu ra bao gồm tất cả các từ vựng nhận được. Chỉ sau đó quyền điều khiển mới được chuyển đến bộ phân tích cú pháp. Trình phân tích cú pháp nhận chuỗi từ vựng được tạo ra và dựa trên nó, tạo thành một biểu diễn trung gian hoặc mô hình đối tượng. Sau khi nhận được toàn bộ mô hình đối tượng, nó sẽ chuyển quyền điều khiển cho bộ tạo mã. Trình tạo mã, dựa trên mô hình đối tượng ngôn ngữ, xây dựng mã máy cần thiết

    Ưu điểm của phương pháp này bao gồm:

    1. Cách ly các giai đoạn riêng lẻ, cho phép thực hiện và sử dụng độc lập.
    2. Khả năng lưu trữ dữ liệu thu được do hoạt động của từng giai đoạn trên các thiết bị lưu trữ bên ngoài và sử dụng chúng khi cần thiết.
    3. Khả năng giảm dung lượng RAM cần thiết để vận hành trình dịch bằng cách gọi các giai đoạn một cách tuần tự.

    Những nhược điểm bao gồm:

    1. Sự hiện diện của khối lượng lớn thông tin trung gian, trong đó chỉ cần một phần nhỏ tại một thời điểm nhất định.
    2. Tốc độ phát sóng bị chậm lại do thực hiện tuần tự các pha và sử dụng thiết bị lưu trữ ngoài để tiết kiệm RAM.

    Cách tiếp cận này có thể thuận tiện khi xây dựng trình dịch từ các ngôn ngữ lập trình có cấu trúc cú pháp và ngữ nghĩa phức tạp (ví dụ: PL/I). Trong những tình huống như vậy, việc dịch khó thực hiện trong một lần chuyển, do đó việc biểu diễn kết quả của các lần chuyển trước dưới dạng dữ liệu trung gian bổ sung sẽ dễ dàng hơn. Cần lưu ý rằng cấu trúc ngữ nghĩa và cú pháp phức tạp của ngôn ngữ có thể dẫn đến việc phải vượt qua các bước bổ sung để thiết lập các phụ thuộc cần thiết. Tổng số lượt đi có thể nhiều hơn mười. Số lần vượt qua cũng có thể bị ảnh hưởng bởi việc sử dụng các tính năng ngôn ngữ cụ thể của chương trình, chẳng hạn như khai báo các biến và thủ tục sau khi chúng được sử dụng, áp dụng các quy tắc khai báo mặc định, v.v.

    Tổ chức tương tác một lần giữa các khối dịch thuật

    Một trong các tùy chọn để tương tác giữa các khối trình biên dịch với tổ chức một lượt được trình bày trong Hình. 1.8.

    Trong trường hợp này, quá trình dịch thuật diễn ra như sau. Trình phân tích từ vựng đọc một đoạn văn bản nguồn cần thiết để có được một từ vựng. Sau khi mã thông báo được hình thành, nó gọi trình phân tích cú pháp và chuyển mã thông báo đã tạo dưới dạng tham số. Nếu trình phân tích cú pháp có thể xây dựng phần tử tiếp theo của biểu diễn trung gian thì nó sẽ làm như vậy và chuyển đoạn được xây dựng tới trình tạo mã. Mặt khác, trình phân tích cú pháp sẽ trả lại quyền kiểm soát cho máy quét, từ đó làm rõ rằng mã thông báo tiếp theo đã được xử lý và cần có dữ liệu mới.

    Trình tạo mã hoạt động theo cách tương tự. Dựa trên đoạn nhận được của biểu diễn trung gian, nó tạo ra đoạn mã đối tượng tương ứng. Sau đó, điều khiển sẽ quay trở lại trình phân tích cú pháp.

    Sau khi hoàn thành văn bản nguồn và hoàn thành việc xử lý tất cả dữ liệu trung gian theo từng khối, bộ phân tích từ vựng sẽ bắt đầu quá trình kết thúc chương trình.

    Thông thường, các trình dịch một lần sử dụng một sơ đồ điều khiển khác, trong đó trình phân tích cú pháp đóng vai trò là khối chính (Hình 1.9).

    Bộ phân tích từ vựng và bộ tạo mã hoạt động như các chương trình con mà nó gọi. Ngay khi trình phân tích cú pháp cần một mã thông báo khác, nó sẽ gọi máy quét. Khi nhận được một đoạn biểu diễn trung gian, lệnh gọi sẽ được thực hiện tới bộ tạo mã. Việc hoàn tất quá trình dịch xảy ra sau khi mã thông báo cuối cùng được nhận và xử lý và được trình phân tích cú pháp bắt đầu.

    Ưu điểm của sơ đồ một lượt bao gồm không có khối lượng lớn dữ liệu trung gian, tốc độ xử lý cao do sự kết hợp của các giai đoạn trong một quy trình duy nhất và không có quyền truy cập vào các thiết bị lưu trữ bên ngoài.

    Những nhược điểm bao gồm: không thể thực hiện sơ đồ dịch thuật như vậy đối với các ngôn ngữ có cấu trúc phức tạp và thiếu dữ liệu trung gian có thể được sử dụng để phân tích và tối ưu hóa phức tạp.

    Lược đồ này thường được sử dụng cho các ngôn ngữ lập trình đơn giản về cấu trúc ngữ nghĩa và cú pháp, cả trong trình biên dịch và trình thông dịch. Ví dụ về các ngôn ngữ như vậy là Basic và Pascal. Trình thông dịch cổ điển thường được xây dựng bằng sơ đồ một lượt, vì việc thực thi trực tiếp được thực hiện ở cấp độ các đoạn riêng lẻ của biểu diễn trung gian. Việc tổ chức tương tác giữa các khối của trình thông dịch như vậy được thể hiện trong Hình 2. 1.10.

    Tương tác kết hợp của các khối dịch

    Sự kết hợp của sơ đồ dịch nhiều lượt và một lượt sẽ tạo ra nhiều tùy chọn kết hợp khác nhau, nhiều tùy chọn trong số đó đã được sử dụng thành công. Ví dụ, chúng ta có thể xem xét một số trong số họ.

    Trong bộ lễ phục. Hình 1.11 cho thấy sơ đồ tương tác của các khối dịch, chia toàn bộ quá trình thành hai bước. Lần đầu tiên tạo ra một biểu diễn trung gian hoàn chỉnh của chương trình và lần thứ hai tạo mã. Sử dụng sơ đồ như vậy cho phép bạn dễ dàng chuyển trình dịch từ hệ thống máy tính này sang hệ thống máy tính khác bằng cách viết lại trình tạo mã.

    Ngoài ra, thay vì trình tạo mã, bạn có thể dễ dàng kết nối trình mô phỏng biểu diễn trung gian, điều này khá đơn giản cho phép bạn phát triển hệ thống lập trình bằng một ngôn ngữ nhất định, hướng đến các môi trường thực thi khác nhau. Một ví dụ về cách tổ chức tương tác giữa các khối dịch thuật như vậy được hiển thị trong Hình. 1.12.


    Cùng với các kế hoạch liên quan đến việc thay thế trình tạo mã bằng trình mô phỏng, còn có các trình dịch cho phép sử dụng chung. Một trong những sơ đồ như vậy được hiển thị trong Hình. 1.13.

    Quá trình dịch thuật, bao gồm cả việc tạo mã, có thể được hoàn thành với số lần chuyển bất kỳ (ví dụ sử dụng bản dịch một lần được trình bày trước đó). Tuy nhiên, mã đối tượng được tạo ra không được thực thi trên hệ thống máy tính tương ứng mà được mô phỏng trên máy tính có kiến ​​trúc khác. Lược đồ này được sử dụng trong môi trường được xây dựng xung quanh ngôn ngữ lập trình Java. Bản thân trình dịch tạo mã máy Java ảo, được mô phỏng bằng các phương tiện đặc biệt cả tự động và trong môi trường trình duyệt Internet.

    Sơ đồ được trình bày cũng có thể có cách hiểu rộng hơn liên quan đến bất kỳ trình biên dịch nào tạo ra mã máy. Vấn đề là hầu hết các máy tính hiện đại đều được thực hiện bằng cách sử dụng điều khiển vi chương trình. Một thiết bị điều khiển vi chương trình có thể được coi là một chương trình mô phỏng mã máy. Điều này cho phép chúng ta nói về việc sử dụng rộng rãi chương trình được trình bày mới nhất.

    Câu hỏi và bài tập kiểm tra

    1. Đặt tên cho sự khác biệt:
      • thông dịch viên từ trình biên dịch;
      • trình biên dịch từ trình biên dịch chương trình;
      • bộ chuyển mã dịch thuật;
      • trình giả lập từ trình thông dịch;
      • cú pháp từ ngữ nghĩa.
    1. Hãy cho chúng tôi biết về những phát triển mới nhất trong ngôn ngữ lập trình mà bạn biết. Nêu đặc điểm chính của các ngôn ngữ này.
    2. Cho ví dụ cụ thể về việc sử dụng phương pháp dịch thuật trong những lĩnh vực không liên quan đến ngôn ngữ lập trình.
    3. Cho ví dụ cụ thể về các ngôn ngữ lập trình được biên dịch.
    4. Đưa ra ví dụ cụ thể về ngôn ngữ lập trình được giải thích.
    5. Đưa ra ví dụ cụ thể về các ngôn ngữ lập trình có sẵn cả trình biên dịch và trình thông dịch.
    6. Những ưu điểm và nhược điểm chính của trình biên dịch.
    7. Những ưu điểm và nhược điểm chính của phiên dịch viên.
    8. Mô tả sự khác biệt chính trong cú pháp của hai ngôn ngữ lập trình mà bạn biết.
    9. Mô tả sự khác biệt chính về ngữ nghĩa của hai ngôn ngữ lập trình mà bạn biết.
    10. Kể tên các giai đoạn chính của quá trình dịch thuật và mục đích của chúng.
    11. Kể tên các tính năng cụ thể của dịch một lần.
    12. Kể tên các tính năng cụ thể của dịch nhiều lần.
    13. Cho ví dụ về sự kết hợp có thể có của dịch một lượt và nhiều lượt. Hãy cho chúng tôi biết về việc sử dụng thực tế của các chương trình này.

    Mỗi máy tính có ngôn ngữ lập trình riêng - ngôn ngữ lệnh hoặc ngôn ngữ máy - và chỉ có thể thực thi các chương trình được viết bằng ngôn ngữ này. Về nguyên tắc, bất kỳ thuật toán nào cũng có thể được mô tả bằng ngôn ngữ máy, nhưng chi phí lập trình sẽ cực kỳ cao. Điều này là do ngôn ngữ máy chỉ cho phép bạn mô tả và xử lý các cấu trúc dữ liệu nguyên thủy - bit, byte, từ. Lập trình bằng mã máy đòi hỏi quá nhiều chi tiết về chương trình và chỉ những lập trình viên có kiến ​​thức tốt về cấu trúc và chức năng của máy tính mới có thể tiếp cận được. Các ngôn ngữ cấp cao (Fortran, PL/1, Pascal, C, Ada, v.v.) với các cấu trúc dữ liệu và phương tiện xử lý được phát triển không phụ thuộc vào ngôn ngữ của một máy tính cụ thể đã giúp khắc phục khó khăn này.

    Ngôn ngữ thuật toán cấp cao cho phép lập trình viên mô tả khá đơn giản và thuận tiện các thuật toán để giải quyết nhiều vấn đề ứng dụng. Mô tả này được gọi là chương trình gốc và ngôn ngữ cấp cao là ngôn ngữ đầu vào.

    Bộ xử lý ngôn ngữ là một chương trình ngôn ngữ máy cho phép máy tính hiểu và thực thi các chương trình bằng ngôn ngữ đầu vào. Có hai loại bộ xử lý ngôn ngữ chính: trình thông dịch và trình dịch.

    Thông dịch viên là một chương trình chấp nhận một chương trình bằng ngôn ngữ đầu vào làm đầu vào và khi các cấu trúc ngôn ngữ đầu vào được nhận dạng, sẽ triển khai chúng, tạo ra kết quả đầu ra của các phép tính do chương trình nguồn quy định.

    Người phiên dịch là một chương trình nhận chương trình gốc làm đầu vào và tạo ra một chương trình ở đầu ra có chức năng tương đương với chương trình gốc, được gọi là sự vật. Một chương trình đối tượng được viết bằng ngôn ngữ đối tượng. Trong một trường hợp cụ thể, ngôn ngữ máy có thể đóng vai trò là ngôn ngữ đối tượng và trong trường hợp này, chương trình thu được ở đầu ra của trình dịch có thể được thực thi ngay lập tức trên máy tính (thông dịch). Trong trường hợp này, máy tính là trình thông dịch của chương trình đối tượng trong mã máy. Nói chung, ngôn ngữ đối tượng không nhất thiết phải là máy hoặc thứ gì đó gần với nó (mã tự động). Một số ngôn ngữ đối tượng có thể đóng vai trò ngôn ngữ Trung gian– một ngôn ngữ nằm giữa ngôn ngữ đầu vào và ngôn ngữ máy.

    Nếu một ngôn ngữ trung gian được sử dụng làm ngôn ngữ đối tượng thì có thể có hai tùy chọn để xây dựng trình dịch.

    Tùy chọn đầu tiên là đối với ngôn ngữ trung gian, có (hoặc đang được phát triển) một trình dịch khác từ ngôn ngữ trung gian sang ngôn ngữ máy và nó được sử dụng làm khối cuối cùng của trình dịch được thiết kế.

    Tùy chọn thứ hai để xây dựng trình dịch sử dụng ngôn ngữ trung gian là xây dựng trình thông dịch cho các lệnh của ngôn ngữ trung gian và sử dụng nó làm khối cuối cùng của trình dịch. Ưu điểm của trình thông dịch được thể hiện ở việc gỡ lỗi và dịch hộp thoại, đảm bảo rằng người dùng có thể làm việc ở chế độ tương tác, cho đến khi thực hiện các thay đổi đối với chương trình mà không cần dịch lại hoàn toàn.

    Trình thông dịch cũng được sử dụng trong việc mô phỏng chương trình - thực thi các chương trình được biên dịch cho máy (đối tượng) khác trên máy công nghệ. Đặc biệt, tùy chọn này được sử dụng khi gỡ lỗi các chương trình trên máy tính đa năng sẽ được thực thi trên máy tính chuyên dụng.

    Một trình dịch sử dụng ngôn ngữ gần với ngôn ngữ máy (mã tự động hoặc trình biên dịch mã) làm ngôn ngữ đầu vào thường được gọi là người lắp ráp. Người dịch ngôn ngữ cấp cao được gọi là trình biên dịch.

    Những tiến bộ đáng kể đã được thực hiện trong việc phát triển trình biên dịch trong những năm gần đây. Các trình biên dịch đầu tiên sử dụng cái gọi là phương pháp phát sóng trực tiếp- Đây chủ yếu là các phương pháp heuristic, trong đó, dựa trên ý tưởng chung, đối với mỗi cấu trúc ngôn ngữ, thuật toán dịch riêng của nó sang máy tương đương đã được phát triển. Những phương pháp này chậm và không có cấu trúc.

    Phương pháp thiết kế các trình biên dịch hiện đại dựa trên phương pháp điều khiển cú pháp thành phần xử lý ngôn ngữ. Thành phần theo nghĩa là quá trình chuyển đổi một chương trình nguồn thành một chương trình đối tượng được thực hiện bằng cách kết hợp các ánh xạ độc lập về mặt chức năng với các cấu trúc dữ liệu đầu vào và đầu ra được xác định rõ ràng. Các ánh xạ này được xây dựng từ việc coi chương trình nguồn là sự kết hợp của các khía cạnh (cấp độ) chính của mô tả ngôn ngữ đầu vào: từ vựng, cú pháp, ngữ nghĩa và ngữ dụng, đồng thời xác định các khía cạnh này từ chương trình nguồn trong quá trình biên dịch. Chúng ta hãy xem xét những khía cạnh này để có được một mô hình trình biên dịch đơn giản hóa.

    Cơ sở của bất kỳ ngôn ngữ tự nhiên hay nhân tạo nào đều là bảng chữ cái– một tập hợp các ký tự cơ bản được phép trong ngôn ngữ (chữ cái, số và ký tự dịch vụ). Các dấu hiệu có thể được kết hợp thành từ– các cấu trúc cơ bản của ngôn ngữ, được coi trong văn bản (chương trình) là những ký hiệu không thể chia cắt, có một ý nghĩa nhất định.


    Một từ cũng có thể là một ký tự đơn. Ví dụ: trong ngôn ngữ Pascal, các từ là mã định danh, từ khóa, hằng số và dấu phân cách, đặc biệt là các toán tử số học và logic, dấu ngoặc đơn, dấu phẩy và các ký hiệu khác. Từ vựng của một ngôn ngữ, cùng với sự mô tả cách chúng được thể hiện, tạo nên từ vựng ngôn ngữ.

    Các từ trong một ngôn ngữ được kết hợp thành các cấu trúc phức tạp hơn - câu. Trong các ngôn ngữ lập trình, câu đơn giản nhất là toán tử. Câu được xây dựng từ các từ và các câu đơn giản hơn theo quy tắc cú pháp. Cú pháp ngôn ngữ là sự mô tả các câu đúng. Mô tả ý nghĩa của câu, tức là. nghĩa của từ và các kết nối bên trong của chúng, là ngữ nghĩa ngôn ngữ. Ngoài ra, chúng tôi lưu ý rằng một chương trình cụ thể có một số tác động đến người dịch - chủ nghĩa thực dụng. Kết hợp với nhau, cú pháp, ngữ nghĩa và tính thực dụng của hình thức ngôn ngữ ký hiệu học ngôn ngữ.

    Nói chung, dịch một chương trình từ ngôn ngữ này sang ngôn ngữ khác bao gồm việc thay đổi bảng chữ cái, từ vựng và cú pháp của ngôn ngữ chương trình trong khi vẫn duy trì ngữ nghĩa của nó. Quá trình dịch một chương trình nguồn thành một chương trình đối tượng thường được chia thành nhiều quy trình con độc lập (các giai đoạn dịch), được thực hiện bởi các khối dịch tương ứng. Thật thuận tiện khi xem xét phân tích từ vựng, phân tích cú pháp, phân tích ngữ nghĩa và

    tổng hợp chương trình đối tượng Tuy nhiên, trong nhiều trình biên dịch thực, các giai đoạn này được chia thành nhiều giai đoạn phụ và cũng có thể có các giai đoạn khác (ví dụ: tối ưu hóa mã đối tượng). Trong bộ lễ phục. Hình 1.1 thể hiện mô hình chức năng đơn giản của bộ dịch.

    Theo mô hình này, chương trình đầu vào chủ yếu được xử lý từ vựng. Mục đích của phân tích từ vựng là dịch chương trình nguồn sang ngôn ngữ bên trong của trình biên dịch, trong đó các từ khóa, mã định danh, nhãn và hằng số được giảm xuống một định dạng duy nhất và được thay thế bằng các mã có điều kiện: số hoặc ký hiệu, được gọi là bộ mô tả. Mỗi bộ mô tả bao gồm hai phần: lớp (loại) của mã thông báo và một con trỏ tới địa chỉ bộ nhớ nơi lưu trữ thông tin về mã thông báo cụ thể. Thông thường thông tin này được tổ chức trong bảng. Đồng thời với việc dịch chương trình nguồn sang ngôn ngữ nội bộ, ở khâu phân tích từ vựng, kiểm soát từ vựng- xác định các từ không được chấp nhận trong chương trình.

    Trình phân tích cú pháp lấy đầu ra của bộ phân tích từ vựng và dịch chuỗi hình ảnh mã thông báo sang dạng chương trình trung gian. Một chương trình trung gian về cơ bản là sự biểu diễn cây cú pháp của một chương trình. Cái sau phản ánh cấu trúc của chương trình gốc, tức là. trật tự và kết nối giữa các nhà khai thác của nó. Trong quá trình xây dựng cây cú pháp, kiểm soát cú pháp– Xác định lỗi cú pháp trong chương trình.

    Đầu ra thực tế của trình phân tích cú pháp có thể là chuỗi lệnh cần thiết để xây dựng phần mềm trung gian, truy cập các bảng thư mục và đưa ra thông báo chẩn đoán khi được yêu cầu.

    Cơm. 1.1. Mô hình chức năng đơn giản hóa của trình dịch

    Quá trình tổng hợp một chương trình đối tượng thường bắt đầu bằng việc phân bổ và cấp phát bộ nhớ cho các đối tượng chương trình chính. Sau đó, mỗi câu trong chương trình nguồn sẽ được kiểm tra và tạo ra các câu tương đương về mặt ngữ nghĩa trong ngôn ngữ đối tượng. Thông tin đầu vào ở đây là cây cú pháp của chương trình và các bảng đầu ra của bộ phân tích từ vựng - bảng định danh, bảng hằng số và các bảng khác. Phân tích cây cho phép chúng ta xác định trình tự các lệnh được tạo ra của một chương trình đối tượng và bằng cách sử dụng bảng định danh, chúng ta xác định các loại lệnh hợp lệ cho các giá trị của toán hạng trong các lệnh được tạo ra (ví dụ: lệnh nào cần được tạo: dấu phẩy động hoặc cố định, v.v.).

    Việc tạo ra một chương trình đối tượng thực sự thường được bắt đầu bằng phân tích ngữ nghĩa, bao gồm nhiều loại xử lý ngữ nghĩa khác nhau. Một trong những loại đó là kiểm tra các thỏa thuận ngữ nghĩa trong chương trình. Ví dụ về các quy ước như vậy: mô tả duy nhất của từng mã định danh trong chương trình, định nghĩa của một biến được thực hiện trước khi nó được sử dụng, v.v. Phân tích ngữ nghĩa có thể được thực hiện ở các giai đoạn dịch sau này, chẳng hạn như ở giai đoạn tối ưu hóa chương trình, giai đoạn này cũng có thể được đưa vào trình dịch. Mục tiêu của việc tối ưu hóa là giảm tài nguyên thời gian hoặc tài nguyên RAM cần thiết để thực thi một chương trình đối tượng.

    Đây là những khía cạnh chính của quá trình dịch thuật từ các ngôn ngữ cấp cao. Việc tổ chức các giai đoạn dịch thuật khác nhau và các phương pháp thực tế liên quan để mô tả toán học của chúng sẽ được thảo luận dưới đây.

    Để dịch từ ngôn ngữ này sang ngôn ngữ khác, các chương trình, giống như con người, cần có người phiên dịch hoặc nói một cách khoa học là người phiên dịch.

    Người dịch: các khái niệm cơ bản

    Một chương trình như một trình dịch là một biểu diễn ngôn ngữ của các phép tính I ->P ->P (i). Trình thông dịch là một chương trình có đầu vào là chương trình P với một số dữ liệu đầu vào X. Nó thực thi P trên X: I(P, x) = P(x). có thể được biểu diễn trong hệ thống hình thức). Đây là một khám phá rất có ý nghĩa và sâu sắc của Turing. Bộ xử lý là một trình thông dịch các chương trình ngôn ngữ máy. Việc viết trình thông dịch cho các ngôn ngữ cấp cao thường quá tốn kém nên chúng được dịch sang dạng dễ diễn giải hơn. Một số loại dịch giả có những cái tên rất lạ. Chương trình dịch các chương trình hợp ngữ sang ngôn ngữ máy. Trình biên dịch cho phép bạn dịch từ ngôn ngữ cấp cao sang ngôn ngữ cấp thấp hơn. Trình dịch là một chương trình lấy đầu vào là chương trình bằng một số ngôn ngữ S và sau khi xử lý sẽ tạo ra chương trình bằng ngôn ngữ T. Do đó, cả hai đều có cùng ngữ nghĩa: P->X->Q. Do đó, với mọi xP(x)=Q(x). Việc dịch toàn bộ chương trình sang thứ gì đó được thông dịch được gọi là biên dịch trước khi thực hiện hoặc biên dịch AOT. Trình biên dịch AOT có thể được sử dụng tuần tự. Người cuối cùng thường là người lắp ráp. Vì vậy, chúng ta hãy xem một ví dụ: Mã nguồn -> Trình biên dịch (trình dịch) -> Mã hội -> Trình biên dịch (trình dịch) -> Mã máy -> CPU (trình thông dịch). Quá trình biên dịch động hoặc trực tuyến xảy ra khi một phần của chương trình được dịch trong khi các phần được biên dịch trước đó khác được thực thi. Người dịch JIT ghi nhớ những gì họ đã làm trước đây để không lặp đi lặp lại mã nguồn. Chúng thậm chí còn có khả năng biên dịch và biên dịch lại thích ứng, dựa trên hành vi của môi trường thời gian chạy của chương trình. Nhiều ngôn ngữ cung cấp khả năng thực thi mã trong khi chương trình đang được dịch và cũng có thể biên dịch mã mới trong khi chương trình đang chạy.

    Phát sóng: các giai đoạn

    Quá trình dịch thuật bao gồm các giai đoạn tổng hợp và phân tích. Về mặt sơ đồ, quá trình này trông giống như sau: Mã nguồn -> Trình phân tích -> Biểu diễn khái niệm -> Bộ tổng hợp (trình tạo) -> Mã đích. Điều này là do những lý do sau:

    - bất kỳ phương pháp nào khác đơn giản là không phù hợp;

    — dịch bằng lời đơn giản là không hiệu quả.

    Bạn có thể sử dụng giải pháp kỹ thuật sau: nếu bạn cần viết trình dịch cho M ngôn ngữ nguồn và N ngôn ngữ đích, bạn sẽ chỉ cần viết M+N chương trình đơn giản (bán biên dịch) chứ không phải trình dịch MxN đầy đủ (phức tạp) . Tuy nhiên, trong thực tế, rất hiếm khi một biểu diễn khái niệm đủ biểu cảm và mạnh mẽ để bao quát tất cả các ngôn ngữ đích và nguồn hiện có. Mặc dù một số người dùng đã có thể đạt được điều này. Trình biên dịch thực sự trải qua nhiều giai đoạn khác nhau. Bằng cách tạo trình biên dịch của riêng mình, bạn sẽ không phải làm lại tất cả công việc khó khăn mà các lập trình viên đã thực hiện trong việc tạo trình tạo và chế độ xem. Bạn có thể dịch ngôn ngữ của mình trực tiếp sang JavaScript hoặc C và sử dụng trình biên dịch ngôn ngữ C và công cụ JavaScript hiện có để thực hiện phần còn lại. Bạn cũng có thể sử dụng các chế độ xem trung gian và máy ảo hiện có.

    Ghi âm phiên dịch

    Trình dịch có thể là một công cụ kỹ thuật hoặc một chương trình sử dụng ba ngôn ngữ: nguồn, đích, cơ sở. Chúng có thể được viết dưới dạng chữ T, đặt nguồn ở bên trái, mục tiêu ở bên phải và phần đế bên dưới. Tổng cộng có ba loại trình biên dịch.

    1. Trình dịch là người tự biên dịch nếu ngôn ngữ nguồn của nó khớp với ngôn ngữ cơ sở.
    2. Một trình biên dịch có ngôn ngữ đích bằng với ngôn ngữ cơ sở của nó được gọi là self-resident.
    3. Nếu ngôn ngữ đích và ngôn ngữ cơ sở khác nhau thì trình dịch là trình biên dịch chéo.

    Tại sao việc phân biệt giữa các loại trình biên dịch này lại quan trọng? Ngay cả khi bạn chưa bao giờ xây dựng một trình biên dịch thực sự tốt thì bạn cũng nên tìm hiểu về công nghệ đằng sau nó vì tất cả các khái niệm được sử dụng cho mục đích này đều được sử dụng ở mọi nơi trong các ngôn ngữ truy vấn cơ sở dữ liệu, định dạng văn bản, kiến ​​trúc máy tính nâng cao, giao diện đồ họa, các tác vụ tổng quát tối ưu hóa, dịch máy, bộ điều khiển và trong máy ảo. Ngoài ra, nếu bạn cần viết bộ tiền xử lý, trình tải, trình biên dịch, trình gỡ lỗi hoặc trình biên dịch, bạn cần phải thực hiện tất cả các bước tương tự như khi viết trình biên dịch. Bạn cũng có thể tìm hiểu về những cách tốt hơn để viết chương trình, vì việc phát triển một trình dịch cho ngôn ngữ lập trình đồng nghĩa với việc hiểu rõ hơn tất cả những điều mơ hồ và tinh tế của ngôn ngữ đó. Bằng cách học các nguyên tắc chung của dịch thuật, bạn có thể trở thành một nhà thiết kế ngôn ngữ giỏi. Nhưng nó thực sự quan trọng? Một ngôn ngữ sẽ tuyệt vời đến mức nào nếu nó không thể được triển khai một cách hiệu quả?

    Công nghệ quy mô lớn

    Công nghệ biên dịch bao gồm nhiều lĩnh vực khác nhau của khoa học máy tính. Nó bao gồm lý thuyết ngôn ngữ hình thức, ngữ pháp, kiến ​​trúc máy tính, phân tích cú pháp, khả năng tính toán, tập lệnh, CISC hoặc RISC, đường ống, chu kỳ đồng hồ, hạt nhân, v.v., cũng như điều khiển trình tự, đệ quy, thực thi có điều kiện, phân rã chức năng, lặp lại, mô đun hóa, đồng bộ hóa, siêu lập trình, hằng số, phạm vi, mẫu, loại đầu ra, chú thích, nguyên mẫu, luồng, hộp thư, đơn nguyên, ký tự đại diện, phần tiếp theo, bộ nhớ giao dịch, biểu thức chính quy, đa hình, kế thừa, chế độ tham số, v.v. Ngoài ra, để tạo trình biên dịch, bạn cần hiểu các ngôn ngữ lập trình trừu tượng, thuật toán và cấu trúc dữ liệu, biểu thức chính quy, thuật toán đồ họa và lập trình động.

    Thiết kế trình biên dịch. Các vấn đề có thể phát sinh khi tạo một dịch giả thực sự

    Những vấn đề gì có thể phát sinh với ngôn ngữ nguồn? Có dễ biên dịch không? Có bộ tiền xử lý nào cho việc này không? Các loại được xử lý như thế nào? Nhóm trình biên dịch nào được sử dụng - một lượt hoặc nhiều lượt? Mức độ tối ưu hóa mong muốn cũng đáng được quan tâm đặc biệt. Việc phát sóng một chương trình nhanh và không được tối ưu hóa có thể là điều bình thường. Tối ưu hóa quá mức có thể làm chậm trình biên dịch, nhưng trong thời gian chạy, mã tốt hơn có thể có giá trị.

    Tỷ lệ phát hiện lỗi. Người dịch có nhất thiết phải dừng lại ở lỗi đầu tiên không? Khi nào anh nên dừng lại? Bạn có nên tin tưởng trình biên dịch sẽ sửa lỗi không?

    Bộ công cụ cần thiết

    Nếu trong trường hợp của bạn, ngôn ngữ nguồn không quá nhỏ thì sự hiện diện của bộ tạo máy phân tích và máy quét là điều kiện tiên quyết. Ngoài ra còn có các trình tạo mã đặc biệt, nhưng chúng không phổ biến lắm.

    Đối với loại mã mục tiêu cần tạo, bạn cần chọn mã máy thuần túy, mã tăng cường hoặc mã máy ảo. Bạn cũng có thể viết phần đầu vào tạo các chế độ xem trung gian phổ biến như LLVM, JVM, RTL. Bạn cũng có thể thực hiện dịch từ mã nguồn sang mã nguồn bằng Java Script hoặc C. Nếu chúng ta nói về định dạng mã đích, ở đây bạn có thể chọn mã máy di động, mã máy hình ảnh bộ nhớ, ngôn ngữ hợp ngữ.

    Nhắm mục tiêu lại

    Khi sử dụng số lượng lớn máy phát điện, sẽ rất tốt nếu có một bộ phận đầu vào chung. Cũng vì lý do này, đối với nhiều bộ phận đầu vào, tốt hơn là nên có một máy phát điện.

    Thành phần trình biên dịch

    Chúng tôi liệt kê các thành phần chức năng chính của trình dịch, tạo mã máy nếu chương trình đầu ra là chương trình được viết bằng C hoặc máy ảo:

    — chương trình đầu vào đi vào một bộ phân tích từ vựng, hay nói cách khác là một máy quét, chuyển đổi nó thành một dòng mã thông báo;

    — bộ phân tích cú pháp (trình phân tích cú pháp) xây dựng cây cú pháp trừu tượng từ chúng;

    - một bộ phân tích ngữ nghĩa phân tích thông tin ngữ nghĩa và kiểm tra các nút cây để tìm lỗi;

    - kết quả là một biểu đồ ngữ nghĩa được xây dựng. Thuật ngữ này đề cập đến một cây cú pháp trừu tượng với các liên kết đã được thiết lập và các thuộc tính bổ sung;

    — trình tạo mã trung gian xây dựng biểu đồ luồng (các bộ dữ liệu được nhóm thành các khối chính);

    — trình tối ưu hóa độc lập với máy thực hiện tối ưu hóa cục bộ và toàn cục, nhưng chủ yếu vẫn nằm trong khuôn khổ các chương trình con, đồng thời đơn giản hóa các phép tính và giảm mã dư thừa. Kết quả phải là một biểu đồ luồng đã được sửa đổi;

    - để kết nối các khối cơ bản thành mã đường thẳng với việc chuyển giao quyền điều khiển, sử dụng bộ tạo mã đích. Nó tạo một tệp đối tượng trong trình biên dịch mã với các thanh ghi trực quan, việc này có thể không hiệu quả lắm;

    - trình liên kết tối ưu hóa phụ thuộc vào máy được sử dụng để phân phối bộ nhớ giữa các thanh ghi ảo và thực hiện lập lịch lệnh. Nó cũng chuyển đổi một chương trình được viết bằng hợp ngữ thành trình biên dịch thực sự bằng cách sử dụng đường ống.

    - sử dụng các hệ thống con phát hiện lỗi và trình quản lý bảng ký hiệu;

    - quét và phân tích từ vựng. Máy quét được sử dụng để chuyển đổi luồng ký tự mã nguồn thành luồng mã thông báo, xóa nhận xét, dấu cách và mở rộng macro. Máy quét thường gặp phải vấn đề sau: có nên tính đến các thụt lề, viết hoa hay nhận xét lồng nhau hay không.

    Những lỗi có thể xảy ra trong quá trình quét được gọi là lỗi từ vựng. Chúng bao gồm những điều sau đây:

    - các ký hiệu bị thiếu trong bảng chữ cái;

    — vượt quá số lượng ký tự trong một dòng hoặc một từ;

    - chuỗi ký tự hoặc ký tự không đóng;

    - kết thúc tập tin trong bình luận.

    Phân tích cú pháp hoặc phân tích cú pháp được sử dụng để chuyển đổi một chuỗi mã thông báo thành cây cú pháp trừu tượng. Trong trường hợp này, mỗi nút cây được lưu dưới dạng đối tượng với các trường được đặt tên. Nhiều trong số chúng chính là các nút cây. Không có chu kỳ ở giai đoạn này. Khi tạo trình phân tích cú pháp, trước tiên bạn cần chú ý đến mức độ phức tạp của ngữ pháp (LR hoặc LL) và tìm hiểu xem có bất kỳ quy tắc phân biệt nào hay không. Thật vậy, một số ngôn ngữ yêu cầu phân tích ngữ nghĩa. Các lỗi xảy ra ở giai đoạn này được gọi là lỗi cú pháp.

    Phân tích ngữ nghĩa

    Khi tiến hành phân tích ngữ nghĩa, trước hết cần kiểm tra các quy tắc hợp lệ và liên kết các phần của cây cú pháp với nhau để tạo thành biểu đồ ngữ nghĩa bằng cách chèn một thao tác để ép kiểu ngầm định, phân giải tham chiếu tên, v.v. Rõ ràng là các ngôn ngữ lập trình khác nhau có bộ quy tắc hợp lệ khác nhau. Khi biên dịch các ngôn ngữ giống Java, người dịch có thể gặp phải các lỗi sau:

    - nhiều khai báo của một biến trong phạm vi của nó;

    — vi phạm các quy tắc tiếp cận;

    - sự hiện diện của các tham chiếu đến tên không được khai báo;

    — quá lớn hoặc ngược lại, không đủ số lượng đối số khi gọi một phương thức;

    - loại không phù hợp.

    Thế hệ

    Bằng cách tạo mã trung gian, một biểu đồ luồng được tạo ra, bao gồm các bộ dữ liệu được nhóm thành các khối cơ bản. Sau khi tạo mã, mã máy thực tế sẽ được lấy. Bước đầu tiên trong trình biên dịch truyền thống dành cho máy RISC là tạo một trình biên dịch chương trình với vô số thanh ghi ảo. Điều này có lẽ sẽ không xảy ra với máy CISC.

    Ngôn ngữ lập trình có thể được chia thành biên dịch và thông dịch.

    Một chương trình bằng ngôn ngữ được biên dịch, sử dụng chương trình biên dịch đặc biệt, được chuyển đổi (biên dịch) thành một tập hợp các hướng dẫn cho một loại bộ xử lý nhất định (mã máy) và sau đó được ghi vào một mô-đun thực thi, có thể được khởi chạy để thực thi dưới dạng một mô-đun riêng biệt. chương trình. Nói cách khác, trình biên dịch dịch mã nguồn chương trình từ ngôn ngữ lập trình cấp cao sang mã nhị phân của lệnh xử lý.

    Nếu một chương trình được viết bằng ngôn ngữ thông dịch thì trình thông dịch sẽ trực tiếp thực thi (thông dịch) văn bản nguồn mà không cần dịch trước. Trong trường hợp này, chương trình vẫn ở ngôn ngữ gốc và không thể khởi chạy nếu không có trình thông dịch. Chúng ta có thể nói rằng bộ xử lý máy tính là một trình thông dịch mã máy.

    Nói tóm lại, trình biên dịch dịch mã nguồn của chương trình sang ngôn ngữ máy ngay lập tức và toàn bộ, tạo ra một chương trình thực thi riêng biệt và trình thông dịch thực thi văn bản nguồn trong khi chương trình đang chạy.

    Việc phân chia thành các ngôn ngữ được biên dịch và thông dịch có phần tùy tiện. Vì vậy, đối với bất kỳ ngôn ngữ được biên dịch truyền thống nào, chẳng hạn như Pascal, bạn có thể viết một trình thông dịch. Ngoài ra, hầu hết các trình thông dịch "thuần túy" hiện đại không thực thi trực tiếp các cấu trúc ngôn ngữ mà biên dịch chúng thành một số biểu diễn trung gian cấp cao (ví dụ: với hội nghị biến đổi và mở rộng macro).

    Một trình biên dịch có thể được tạo cho bất kỳ ngôn ngữ thông dịch nào - ví dụ: ngôn ngữ Lisp, được thông dịch nguyên bản, có thể được biên dịch mà không có bất kỳ hạn chế nào. Mã được tạo trong quá trình thực thi chương trình cũng có thể được biên dịch động trong quá trình thực thi.

    Theo quy định, các chương trình đã biên dịch sẽ thực thi nhanh hơn và không yêu cầu các chương trình bổ sung để thực thi vì chúng đã được dịch sang ngôn ngữ máy. Đồng thời, mỗi khi văn bản chương trình được thay đổi thì cần phải biên dịch lại, điều này gây khó khăn trong quá trình phát triển. Ngoài ra, chương trình đã biên dịch chỉ có thể được thực thi trên cùng một loại máy tính và thường trong cùng một hệ điều hành mà trình biên dịch được thiết kế. Để tạo một tệp thực thi cho một loại máy khác, cần phải có một trình biên dịch mới.

    Các ngôn ngữ được phiên dịch có một số tính năng bổ sung cụ thể (xem ở trên), ngoài ra, các chương trình trong đó có thể chạy ngay sau khi sửa đổi, giúp việc phát triển dễ dàng hơn. Một chương trình bằng ngôn ngữ thông dịch thường có thể chạy trên các loại máy và hệ điều hành khác nhau mà không cần nỗ lực thêm.

    Tuy nhiên, các chương trình được thông dịch chạy chậm hơn đáng kể so với các chương trình được biên dịch và chúng không thể được thực thi nếu không có chương trình thông dịch bổ sung.

    Một số ngôn ngữ, chẳng hạn như Java và C#, nằm giữa biên dịch và thông dịch. Cụ thể, chương trình không được biên dịch sang ngôn ngữ máy mà thành mã độc lập với máy cấp thấp, mã byte. Mã byte sau đó được thực thi bởi máy ảo. Thông dịch thường được sử dụng để thực thi mã byte, mặc dù các phần riêng lẻ của nó có thể được dịch trực tiếp sang mã máy trong quá trình thực thi chương trình bằng cách sử dụng tính năng biên dịch đúng lúc (JIT) để tăng tốc chương trình. Đối với Java, mã byte được thực thi bởi Máy ảo Java (JVM), đối với C# - bởi Thời gian chạy ngôn ngữ chung.

    Theo một nghĩa nào đó, cách tiếp cận này cho phép bạn sử dụng những ưu điểm của cả trình thông dịch và trình biên dịch. Điều đáng nói là ngôn ngữ Forth gốc, có cả trình thông dịch và trình biên dịch.

    Vì máy tính không thể hiểu được văn bản được viết bằng ngôn ngữ lập trình nên nó cần được dịch sang mã máy. Việc dịch chương trình từ ngôn ngữ lập trình sang ngôn ngữ mã máy này được gọi là dịch thuật và nó được thực hiện bởi các chương trình đặc biệt - trình dịch.

    Trình dịch là một chương trình dịch vụ chuyển đổi chương trình nguồn được cung cấp bằng ngôn ngữ lập trình đầu vào thành chương trình làm việc được trình bày bằng ngôn ngữ đối tượng.

    Hiện nay, người dịch được chia làm 3 nhóm chính: người biên dịch, người biên dịch và người phiên dịch.

    Trình biên dịch mã là một chương trình tiện ích hệ thống có chức năng chuyển đổi các cấu trúc biểu tượng thành các lệnh ngôn ngữ máy. Một tính năng cụ thể của trình biên dịch mã là chúng thực hiện dịch nguyên văn một lệnh ký hiệu thành một lệnh máy. Do đó, hợp ngữ (còn gọi là mã tự động) được thiết kế để tạo điều kiện thuận lợi cho việc nhận thức hệ thống lệnh của máy tính và tăng tốc độ lập trình trong hệ thống lệnh này. Việc lập trình viên ghi nhớ ký hiệu dễ nhớ của các lệnh máy sẽ dễ dàng hơn nhiều so với mã nhị phân của chúng.

    Đồng thời, hợp ngữ, ngoài các tính chất tương tự của lệnh máy, còn chứa nhiều lệnh bổ sung, đặc biệt là tạo điều kiện thuận lợi cho việc quản lý tài nguyên máy tính, viết các đoạn lặp lại và xây dựng các chương trình đa mô-đun. Do đó, khả năng biểu đạt của ngôn ngữ phong phú hơn nhiều so với chỉ một ngôn ngữ mã hóa tượng trưng, ​​giúp cải thiện đáng kể hiệu quả lập trình.

    Trình biên dịch là một chương trình dịch vụ dịch chương trình được viết bằng ngôn ngữ lập trình nguồn sang ngôn ngữ máy. Giống như trình biên dịch chương trình, trình biên dịch chuyển đổi một chương trình từ ngôn ngữ này sang ngôn ngữ khác (thường là sang ngôn ngữ của một máy tính cụ thể). Đồng thời, các lệnh ngôn ngữ nguồn khác biệt đáng kể về tổ chức và sức mạnh so với các lệnh ngôn ngữ máy. Có những ngôn ngữ trong đó một lệnh của ngôn ngữ nguồn được dịch sang 7-10 lệnh máy. Tuy nhiên, cũng có những ngôn ngữ trong đó mỗi lệnh có thể có 100 lệnh máy trở lên (ví dụ: Prolog). Ngoài ra, các ngôn ngữ nguồn thường sử dụng cách nhập dữ liệu nghiêm ngặt, được thực hiện thông qua mô tả sơ bộ của chúng. Lập trình có thể không dựa vào việc mã hóa thuật toán mà dựa vào việc suy nghĩ cẩn thận về các cấu trúc hoặc lớp dữ liệu. Quá trình dịch từ các ngôn ngữ như vậy thường được gọi là biên dịch và ngôn ngữ nguồn thường được phân loại là ngôn ngữ lập trình cấp cao (hoặc ngôn ngữ cấp cao). Việc trừu tượng hóa ngôn ngữ lập trình khỏi hệ thống lệnh máy tính đã dẫn đến việc tạo ra nhiều loại ngôn ngữ độc lập tập trung vào việc giải quyết các vấn đề cụ thể. Ngôn ngữ đã xuất hiện để tính toán khoa học, tính toán kinh tế, truy cập cơ sở dữ liệu và các ngôn ngữ khác.

    Trình thông dịch - một chương trình hoặc thiết bị thực hiện việc dịch thuật của từng người vận hành và thực hiện chương trình nguồn. Không giống như trình biên dịch, trình thông dịch không tạo ra chương trình ngôn ngữ máy làm đầu ra. Sau khi nhận ra một lệnh trong ngôn ngữ nguồn, nó sẽ thực thi lệnh đó ngay lập tức. Cả trình biên dịch và trình thông dịch đều sử dụng cùng một phương pháp để phân tích mã nguồn của chương trình. Nhưng trình thông dịch cho phép bạn bắt đầu xử lý dữ liệu sau khi viết dù chỉ một lệnh. Điều này làm cho quá trình phát triển và gỡ lỗi chương trình trở nên linh hoạt hơn. Ngoài ra, việc không có mã máy đầu ra giúp không thể "làm lộn xộn" các thiết bị bên ngoài với các tệp bổ sung và bản thân trình thông dịch có thể khá dễ dàng thích ứng với bất kỳ kiến ​​​​trúc máy nào, chỉ phát triển nó một lần bằng ngôn ngữ lập trình được sử dụng rộng rãi. Vì vậy, các ngôn ngữ thông dịch như Java Script và VB Script đã trở nên phổ biến. Nhược điểm của trình thông dịch là tốc độ thực hiện chương trình thấp. Thông thường, các chương trình thông dịch chạy chậm hơn 50 đến 100 lần so với các chương trình gốc.

    Trình mô phỏng là một chương trình hoặc phần mềm và công cụ phần cứng cung cấp khả năng thực thi trên một máy tính nhất định một chương trình sử dụng mã hoặc phương pháp thực hiện các hoạt động khác với máy tính nhất định mà không cần lập trình lại. Trình mô phỏng tương tự như trình thông dịch ở chỗ nó trực tiếp thực thi chương trình được viết bằng một ngôn ngữ nhất định. Tuy nhiên, thông thường nhất đó là ngôn ngữ máy hoặc mã trung gian. Cả hai đều thể hiện các hướng dẫn ở dạng mã nhị phân có thể được thực thi ngay sau khi mã hoạt động được nhận dạng. Không giống như các chương trình văn bản, không cần nhận dạng cấu trúc chương trình hoặc chọn toán hạng.

    Trình giả lập được sử dụng khá thường xuyên cho nhiều mục đích khác nhau. Ví dụ: khi phát triển hệ thống máy tính mới, trước tiên, một trình mô phỏng sẽ được tạo để chạy các chương trình được phát triển cho các máy tính chưa tồn tại. Điều này cho phép bạn đánh giá hệ thống lệnh và phát triển phần mềm cơ bản ngay cả trước khi phần cứng tương ứng được tạo ra.

    Rất thường xuyên, trình giả lập được sử dụng để chạy các chương trình cũ trên máy tính mới. Thông thường, các máy tính mới hơn sẽ nhanh hơn và có thiết bị ngoại vi tốt hơn. Điều này cho phép bạn mô phỏng các chương trình cũ hiệu quả hơn so với việc chạy chúng trên các máy tính cũ.

    Bộ chuyển mã là một chương trình hoặc thiết bị phần mềm dịch các chương trình được viết bằng ngôn ngữ máy của một máy tính sang các chương trình bằng ngôn ngữ máy của một máy tính khác. Nếu trình mô phỏng là một trình tương tự kém thông minh hơn của trình thông dịch thì bộ chuyển mã sẽ hoạt động với cùng khả năng so với trình biên dịch. Tương tự, mã máy nguồn (và thường là nhị phân) hoặc biểu diễn trung gian được chuyển đổi thành mã tương tự khác bằng một lệnh duy nhất và không có bất kỳ phân tích chung nào về cấu trúc của chương trình nguồn. Bộ chuyển mã rất hữu ích khi chuyển các chương trình từ kiến ​​trúc máy tính này sang kiến ​​trúc máy tính khác. Chúng cũng có thể được sử dụng để tái tạo lại văn bản chương trình ngôn ngữ cấp cao từ mã nhị phân hiện có.

    Bộ xử lý vĩ mô là một chương trình thay thế một chuỗi ký tự này bằng một chuỗi ký tự khác. Đây là một loại trình biên dịch. Nó tạo ra văn bản đầu ra bằng cách xử lý các phần chèn đặc biệt nằm trong văn bản nguồn. Những phần chèn này được thiết kế theo cách đặc biệt và thuộc về cấu trúc của một ngôn ngữ được gọi là ngôn ngữ vĩ mô. Bộ vi xử lý thường được sử dụng làm tiện ích bổ sung cho các ngôn ngữ lập trình, làm tăng chức năng của hệ thống lập trình. Hầu hết mọi trình biên dịch chương trình đều có bộ xử lý vĩ mô, giúp tăng hiệu quả phát triển các chương trình máy. Những hệ thống lập trình như vậy thường được gọi là macroassemblers.

    Bộ xử lý vĩ mô cũng được sử dụng với các ngôn ngữ cấp cao. Chúng tăng cường chức năng của các ngôn ngữ như PL/1, C, C++. Bộ xử lý macro đặc biệt được sử dụng rộng rãi trong C và C++, giúp việc viết chương trình trở nên dễ dàng hơn. Bộ vi xử lý cải thiện hiệu quả lập trình mà không thay đổi cú pháp hoặc ngữ nghĩa của ngôn ngữ.

    Cú pháp là một tập hợp các quy tắc của một ngôn ngữ xác định sự hình thành các phần tử của nó. Nói cách khác, đây là một bộ quy tắc để hình thành các chuỗi ký hiệu có ý nghĩa về mặt ngữ nghĩa trong một ngôn ngữ nhất định. Cú pháp được xác định bằng cách sử dụng các quy tắc mô tả các khái niệm của ngôn ngữ. Ví dụ về các khái niệm là: biến, biểu thức, toán tử, thủ tục. Trình tự các khái niệm và cách sử dụng được chấp nhận của chúng trong các quy tắc sẽ xác định cấu trúc đúng về mặt cú pháp tạo nên chương trình. Đó là thứ bậc của các đối tượng chứ không phải cách chúng tương tác với nhau được xác định thông qua cú pháp. Ví dụ: một câu lệnh chỉ có thể xuất hiện trong một thủ tục, một biểu thức trong câu lệnh, một biến có thể bao gồm tên và các chỉ mục tùy chọn, v.v. Cú pháp không liên quan đến những hiện tượng như vậy trong chương trình như “nhảy đến một nhãn không tồn tại” hoặc “một biến có tên đã cho không được xác định”. Đây là những gì ngữ nghĩa làm.

    Ngữ nghĩa - các quy tắc và điều kiện xác định mối quan hệ giữa các thành phần ngôn ngữ và ý nghĩa ngữ nghĩa của chúng, cũng như việc giải thích ý nghĩa có ý nghĩa của các cấu trúc cú pháp của ngôn ngữ. Các đối tượng của ngôn ngữ lập trình không chỉ được đặt trong văn bản theo một hệ thống phân cấp nhất định mà còn được liên kết với nhau thông qua các khái niệm khác tạo thành các liên kết khác nhau. Ví dụ: một biến mà cú pháp xác định vị trí hợp lệ chỉ trong các khai báo và một số câu lệnh, có một loại cụ thể, có thể được sử dụng với một số thao tác giới hạn, có địa chỉ, kích thước và phải được khai báo trước khi có thể. được sử dụng trong chương trình.

    Trình phân tích cú pháp là một thành phần trình biên dịch kiểm tra các câu lệnh nguồn xem có tuân thủ các quy tắc cú pháp và ngữ nghĩa của một ngôn ngữ lập trình nhất định hay không. Mặc dù có tên như vậy nhưng bộ phân tích vẫn kiểm tra cả cú pháp và ngữ nghĩa. Nó bao gồm một số khối, mỗi khối giải quyết các vấn đề riêng của nó. Nó sẽ được thảo luận chi tiết hơn khi mô tả cấu trúc của người dịch. lập trình ngôn ngữ trình biên dịch

    Bất kỳ người dịch nào cũng thực hiện các nhiệm vụ chính sau:

    • - phân tích chương trình đã dịch, đặc biệt là xác định xem nó có chứa lỗi cú pháp hay không;
    • - tạo ra một chương trình đầu ra (thường được gọi là chương trình đối tượng) bằng ngôn ngữ lệnh máy;
    • - cấp phát bộ nhớ cho chương trình đối tượng.1.1 Trình thông dịch

    Một ưu điểm thường được trích dẫn của việc triển khai diễn giải là nó cho phép sử dụng "chế độ tức thời". Chế độ trực tiếp cho phép bạn hỏi máy tính một vấn đề như PRINT 3.14159*3/2.1 và trả về câu trả lời cho bạn ngay khi bạn nhấn ENTER (điều này cho phép bạn sử dụng máy tính 3.000 đô la làm máy tính 10 đô la). Ngoài ra, trình thông dịch còn có các thuộc tính đặc biệt giúp việc gỡ lỗi trở nên dễ dàng hơn. Ví dụ, bạn có thể làm gián đoạn quá trình xử lý của một chương trình thông dịch, hiển thị nội dung của các biến nhất định, đọc lướt chương trình và sau đó tiếp tục thực thi.

    Điều mà các lập trình viên thích nhất ở phiên dịch viên là khả năng nhận được câu trả lời nhanh chóng. Ở đây không cần phải biên dịch vì trình thông dịch luôn sẵn sàng can thiệp vào chương trình của bạn. Gõ RUN và kết quả của thay đổi gần đây nhất của bạn sẽ xuất hiện trên màn hình.

    Tuy nhiên, ngôn ngữ thông dịch có nhược điểm. Ví dụ, cần phải luôn có một bản sao của trình thông dịch trong bộ nhớ, trong khi nhiều khả năng của trình thông dịch và do đó các khả năng của nó có thể không cần thiết để thực thi một chương trình cụ thể.

    Một nhược điểm nhỏ của phiên dịch viên là họ có xu hướng không khuyến khích phong cách lập trình tốt. Vì các chú thích và các chi tiết chính thức khác chiếm một lượng đáng kể bộ nhớ chương trình nên mọi người có xu hướng không sử dụng chúng. Ma quỷ sẽ bớt giận dữ hơn một lập trình viên làm việc trong trình thông dịch BASIC đang cố gắng đưa chương trình 120K vào bộ nhớ 60K. nhưng điều tệ nhất là người phiên dịch di chuyển chậm.

    Họ dành quá nhiều thời gian để cố gắng tìm ra những việc cần làm thay vì thực sự làm việc đó. Khi thực thi các câu lệnh của chương trình, trước tiên trình thông dịch phải quét từng câu lệnh để đọc nội dung của nó (người này yêu cầu tôi làm gì?) rồi thực hiện thao tác được yêu cầu. Các toán tử trong vòng lặp được quét quá mức.

    Hãy xem xét chương trình: trong trình thông dịch BASIC 10 FOR N=1 TO 1000 20 PRINT N,SQR(N) 30 NEXT N lần đầu tiên bạn xem qua chương trình này, Trình thông dịch BASIC phải tìm ra dòng 20 nghĩa là gì:

    • 1. chuyển đổi biến số N thành chuỗi
    • 2. gửi một chuỗi ra màn hình
    • 3. di chuyển tới vùng in tiếp theo
    • 4. tính căn bậc hai của N
    • 5. chuyển đổi kết quả thành chuỗi
    • 6. gửi một chuỗi ra màn hình

    Trong lần thứ hai của chu kỳ, tất cả việc giải quyết này được lặp lại một lần nữa, vì tất cả các kết quả nghiên cứu dòng này cách đây vài mili giây đều bị lãng quên hoàn toàn. Và cứ thế cho tất cả 998 lượt tiếp theo. Rõ ràng là nếu bằng cách nào đó bạn có thể tách giai đoạn quét/hiểu khỏi giai đoạn thực thi thì bạn sẽ có một chương trình nhanh hơn. Và đây chính xác là mục đích của trình biên dịch.