Vì bạn muốn tìm hiểu cách thức hoạt động của lexer, tôi cho rằng bạn thực sự muốn biết làm thế nào các trình tạo lexer hoạt động.
Một trình tạo từ vựng có một đặc tả từ vựng, đó là một danh sách các quy tắc (các cặp mã thông báo biểu thức chính quy) và tạo ra một từ vựng. Sau đó, lexer kết quả này có thể chuyển đổi một chuỗi đầu vào (ký tự) thành một chuỗi mã thông báo theo danh sách quy tắc này.
Phương pháp được sử dụng phổ biến nhất chủ yếu bao gồm chuyển đổi một biểu thức chính quy thành một automata hữu hạn xác định (DFA) thông qua một automata không điều kiện (NFA), cùng với một vài chi tiết.
Một hướng dẫn chi tiết về việc thực hiện chuyển đổi này có thể được tìm thấy ở đây . Lưu ý rằng tôi đã không đọc nó cho mình, nhưng nó trông khá tốt. Ngoài ra, bất kỳ cuốn sách nào về xây dựng trình biên dịch sẽ có sự chuyển đổi này trong một vài chương đầu tiên.
Nếu bạn quan tâm đến các bài giảng của các khóa học về chủ đề này, không có nghi ngờ gì về số lượng vô tận của chúng từ các khóa học về xây dựng trình biên dịch. Từ trường đại học của tôi, bạn có thể tìm thấy các slide như vậy ở đây và đây .
Có một vài điều nữa thường không được sử dụng trong các từ vựng hoặc được xử lý trong các văn bản, nhưng dù sao cũng khá hữu ích:
Thứ nhất, việc xử lý Unicode có phần không cần thiết. Vấn đề là đầu vào ASCII chỉ rộng 8 bit, điều đó có nghĩa là bạn có thể dễ dàng có bảng chuyển đổi cho mọi trạng thái trong DFA, vì chúng chỉ có 256 mục. Tuy nhiên, Unicode, rộng 16 bit (nếu bạn sử dụng UTF-16), yêu cầu 64k bảng cho mỗi mục trong DFA. Nếu bạn có ngữ pháp phức tạp, điều này có thể bắt đầu chiếm khá nhiều không gian. Việc lấp đầy các bảng này cũng bắt đầu mất khá nhiều thời gian.
Ngoài ra, bạn có thể tạo cây khoảng. Ví dụ, một cây phạm vi có thể chứa các bộ dữ liệu ('a', 'z'), ('A', 'Z'), giúp tiết kiệm bộ nhớ hơn rất nhiều so với việc có đầy đủ bảng. Nếu bạn duy trì các khoảng không chồng chéo, bạn có thể sử dụng bất kỳ cây nhị phân cân bằng nào cho mục đích này. Thời gian chạy là tuyến tính theo số bit bạn cần cho mỗi ký tự, vì vậy O (16) trong trường hợp Unicode. Tuy nhiên, trong trường hợp tốt nhất, nó thường sẽ ít hơn một chút.
Một vấn đề nữa là các từ vựng như thường được tạo ra thực sự có hiệu suất bậc hai trong trường hợp xấu nhất. Mặc dù hành vi trong trường hợp xấu nhất này không thường thấy, nhưng nó có thể cắn bạn. Nếu bạn gặp phải vấn đề và muốn giải quyết nó, một bài viết mô tả cách đạt được thời gian tuyến tính có thể được tìm thấy ở đây .
Bạn có thể muốn có thể mô tả các biểu thức thông thường ở dạng chuỗi, như chúng thường xuất hiện. Tuy nhiên, phân tích các mô tả biểu thức chính quy này thành NFA (hoặc có thể là cấu trúc trung gian đệ quy trước) là một vấn đề của trứng gà. Để phân tích các mô tả biểu thức chính quy, thuật toán Shunting Yard rất phù hợp. Wikipedia dường như có một trang mở rộng về thuật toán .