Tìm kiếm một định nghĩa rõ ràng về những gì một tokenizer của Google, các trình phân tích cú pháp của Google và các từ vựng của Google là gì và chúng có liên quan với nhau và được sử dụng như thế nào?


151

Tôi đang tìm một định nghĩa rõ ràng về "mã thông báo", "trình phân tích cú pháp" và "từ vựng" là gì và chúng có liên quan với nhau như thế nào (ví dụ: trình phân tích cú pháp sử dụng mã thông báo hoặc ngược lại)? Tôi cần tạo một chương trình sẽ đi qua các tệp nguồn c / h để trích xuất khai báo và định nghĩa dữ liệu.

Tôi đã tìm kiếm các ví dụ và có thể tìm thấy một số thông tin, nhưng tôi thực sự vật lộn để nắm bắt các khái niệm cơ bản như quy tắc ngữ pháp, cây phân tích cú pháp và cây cú pháp trừu tượng và cách chúng liên quan với nhau. Cuối cùng, các khái niệm này cần được lưu trữ trong một chương trình thực tế, nhưng 1) chúng trông như thế nào, 2) có những triển khai chung.

Tôi đã xem Wikipedia về các chủ đề và chương trình như Lex và Yacc, nhưng chưa bao giờ trải qua lớp biên dịch (chuyên ngành EE) Tôi cảm thấy khó hiểu hoàn toàn những gì đang diễn ra.

Câu trả lời:


166

Một mã thông báo phá vỡ một luồng văn bản thành các mã thông báo, thường bằng cách tìm khoảng trắng (tab, dấu cách, dòng mới).

Một lexer về cơ bản là một mã thông báo, nhưng nó thường gắn ngữ cảnh bổ sung vào các mã thông báo - mã thông báo này là một số, mã thông báo đó là một chuỗi ký tự, mã thông báo khác này là một toán tử đẳng thức.

Trình phân tích cú pháp lấy luồng mã thông báo từ lexer và biến nó thành một cây cú pháp trừu tượng đại diện cho chương trình (thường) được biểu thị bằng văn bản gốc.

Lần cuối tôi kiểm tra, cuốn sách hay nhất về chủ đề này là "Trình biên dịch: Nguyên tắc, Kỹ thuật và Công cụ" thường được gọi là "Cuốn sách rồng".


8
Không còn nghi ngờ gì nữa, "Cuốn sách rồng" là một cuốn sách hay, nhưng nó đòi hỏi người đọc phải có một nền tảng tốt trong CS. Một số cuốn sách có sức hấp dẫn thực tế hơn sẽ là "Viết trình biên dịch và phiên dịch" của Ronald Mak, "Thực hiện trình biên dịch hiện đại", Andrew Appel; "Xây dựng trình biên dịch", Niklaus Wirth; "Biên dịch với C # và Java" và "Trình biên dịch và trình tạo trình biên dịch: Giới thiệu với C ++" của Pat Terry; và, tất nhiên, "Tài liệu tham khảo ANTLR dứt khoát" của Terrence Parr.
Andre Artus

5
Chỉ để chắc chắn, tôi không gõ lời giới thiệu của bạn. "Cuốn sách rồng" là cuốn sách đầu tiên của tôi về công nghệ biên dịch, nhưng thật khó để so sánh với cuốn sách của Wirth, đây là cuốn sách bạn có thể mò mẫm trong vài giờ. Hồi đó tôi có vài lựa chọn vì đây là cuốn sách duy nhất tôi có thể có được (đó là năm 1991, trước Amazon và WWW). Tôi đã có điều đó và một bộ sưu tập các tệp văn bản được sản xuất bởi Jack W. Crenshaw có tên là "LET'S BUILD A MÁY TÍNH" (cảm ơn Jack!). Đây vẫn là cuốn sách để có được sự hiểu biết đầy đủ hơn về các nguyên tắc, nhưng hầu hết các lập trình viên chỉ cần một phần giới thiệu thực dụng.
Andre Artus

10
Tôi không đồng ý rằng trình phân tích cú pháp / theo định nghĩa / tạo ra một cây cú pháp trừu tượng. Trình phân tích cú pháp có thể tạo ra tất cả các loại đầu ra khác nhau. Ví dụ: thông thường, trình phân tích cú pháp tạo ra một chuỗi các cuộc gọi đến một số giao diện của trình tạo - xem Mô hình Trình tạo trong sách mẫu của Gang of Four. Điểm mấu chốt là trình phân tích cú pháp phân tích một chuỗi các mã thông báo để xác định xem chuỗi đó có phù hợp với một số ngữ pháp (thường không có ngữ cảnh) hay không và có thể tạo ra một số đầu ra dựa trên cấu trúc ngữ pháp của chuỗi.
Theodore Norvell

2
"Hãy xây dựng trình biên dịch" có tại đây: compilers.iecc.com/crenshaw . Tôi tìm thấy liên kết từ đây: prog21.dadgum.com/30.html
Roger Lipscombe

1
@Pithkos: nếu đó là những ràng buộc duy nhất, tất cả những gì bạn đã nói là hàm lấy một đầu vào trong một miền (toán học) chưa được đặt tên và tạo và xuất ra trong một miền không tên khác, ví dụ: F (X) -> Y bạn chỉ có thể gọi đây là "chức năng". Nếu bạn khẳng định rằng miền của X là <StreamOfCharacter, Grammar> và miền của Y là Tree với thuộc tính phản ánh hình dạng của ngữ pháp, thì F (X, G) -> T sẽ là một cái gì đó tôi sẽ gọi là trình phân tích cú pháp. Thông thường chúng tôi cà ri F liên quan đến G vì G không thay đổi thường xuyên, vì vậy F [G] (X) -> T là những gì bạn thường thấy là trình phân tích cú pháp.
Ira Baxter

18

Thí dụ:

int x = 1;

Một lexer hoặc mã thông báo sẽ chia nó thành các mã thông báo 'int', 'x', '=', '1', ';'.

Trình phân tích cú pháp sẽ lấy các mã thông báo đó và sử dụng chúng để hiểu theo một cách nào đó:

  • chúng tôi có một tuyên bố
  • đó là định nghĩa của một số nguyên
  • số nguyên được gọi là 'x'
  • 'x' nên được khởi tạo với giá trị 1

9
Một từ vựng sẽ lưu ý rằng "int", "=" và ";" là các mã thông báo không có ý nghĩa gì thêm, "x" là tên định danh hoặc một cái gì đó, giá trị "x" và "1" là số nguyên hoặc số, giá trị "1". Một mã thông báo sẽ không nhất thiết phải làm điều đó.
David Thornley

5

Tôi có thể nói rằng một lexer và tokenizer về cơ bản là giống nhau và chúng đập văn bản thành các phần thành phần của nó ('mã thông báo'). Trình phân tích cú pháp sau đó diễn giải các mã thông báo bằng cách sử dụng một ngữ pháp.

Mặc dù vậy, tôi sẽ không quá bận tâm về cách sử dụng thuật ngữ chính xác - mọi người thường sử dụng 'phân tích cú pháp' để mô tả bất kỳ hành động nào trong việc diễn giải một cụm văn bản.


1
Với trình phân tích cú pháp PEG, sự khác biệt giữa mã thông báo và trình phân tích cú pháp thậm chí còn chưa rõ ràng.
Andre Artus

0

( thêm vào các câu trả lời đã cho )

  • Tokenizer cũng sẽ xóa bất kỳ nhận xét nào và chỉ trả lại mã thông báo cho Lexer.
  • Lexer cũng sẽ xác định phạm vi cho các mã thông báo (biến / hàm)
  • Trình phân tích cú pháp sau đó sẽ xây dựng cấu trúc mã / chương trình

1
Xin chào @downvoter, bạn có thể giải thích lý do tại sao bạn thực sự đã downvote?
Koray Tugay

1
Tôi không phải là người xuống, nhưng tôi nghĩ rằng downvote có thể là do câu trả lời của bạn có vẻ không đúng. Một mã thông báo có thể loại bỏ nhiễu (thường là khoảng trắng nhưng cũng có thể là các bình luận), nhưng nó thường không cung cấp từ vựng. Một lexer dựa trên DFA sẽ mã hóa và xác định các mã thông báo là gì (ví dụ: một số, một chuỗi, một mã định danh, nhưng cũng là một khoảng trắng hoặc một nhận xét), nhưng nó không thể bao gồm các mã này vì nó sẽ yêu cầu cây cú pháp được xây dựng sau trình phân tích cú pháp.
Lucero

1) Tôi không hiểu sự phân biệt người quản lý của bạn giữa "lexer" và "tokenizer". Tôi đã xây dựng các trình phân tích cú pháp cho hơn 50 ngôn ngữ và tôi chưa bao giờ có hai cơ chế riêng biệt phá vỡ văn bản nguồn thành các nguyên tử, vì vậy đối với tôi đây chỉ là các từ đồng nghĩa. 2) Nếu bạn đang biên dịch, loại bỏ các bình luận và khoảng trắng có ý nghĩa trong từ vựng. Nếu bạn đang xây dựng các công cụ chuyển đổi nguồn-nguồn, bạn không thể mất bình luận vì chúng phải xuất hiện lại trong văn bản được chuyển đổi. Vì vậy, LUÔN LUÔN xóa bình luận là sai; chúng ta có thể tranh luận về cách người ta quản lý để duy trì khoảng trắng. ...
Ira Baxter

1
... [Các công cụ tôi xây dựng (xem tiểu sử của tôi) nắm bắt cả hai với độ trung thực đầy đủ để tái tạo chúng trong mã được chuyển đổi; chúng ta đi xa hơn và nắm bắt định dạng của các nguyên tử, bao gồm cả những điều kỳ lạ như dấu ngoặc kép được sử dụng trên chuỗi ký tự và số 0 / số không dẫn đầu về số, tất cả nhằm tránh việc người dùng từ chối kết quả được chuyển đổi. Vì vậy, những gì bạn đã bỏ lỡ không chỉ là các từ vựng không nhất thiết phải tước thông tin, mà trên thực tế họ có thể cần phải nắm bắt thông tin ở trên và ngoài mã thông báo thô]. ....
Ira Baxter

... 3) Các trình phân tích chỉ định nghĩa "phạm vi" trong các trình phân tích cú pháp vô vọng lúng túng, có một thời gian khó xử lý sự mơ hồ cú pháp. Trình phân tích cú pháp C và C ++ là ví dụ điển hình; xem cuộc thảo luận của tôi tại stackoverflow.com/a/1004737/120163 ). Người ta không phải làm theo cách đó (xấu xí). Vì vậy, tôi tìm thấy câu trả lời của bạn chỉ đơn giản là sai lầm.
Ira Baxter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.