Bộ phân tích cú pháp GCC và Clang có thực sự được viết tay không?


90

Dường như GCC và LLVM-Clang đang sử dụng viết tay parsers gốc đệ quy , và không máy tạo ra, Bison-Flex dựa, từ dưới lên phân tích cú pháp.

Ai đó ở đây có thể vui lòng xác nhận rằng đây là trường hợp? Và nếu vậy, tại sao các khung biên dịch chính thống lại sử dụng trình phân tích cú pháp viết tay?

Cập nhật : blog thú vị về chủ đề này ở đây


27
Hầu như tất cả các trình biên dịch chính đang sử dụng trình phân tích cú pháp viết tay. Có vấn đề gì với điều đó?
SK-logic

2
bạn phải làm điều đó (bán) thủ công nếu bạn cần hiệu suất.
Gene Bushuyev

15
Và không chỉ thực hiện - thông báo lỗi tốt hơn, khả năng phục hồi, vv
SK-logic

Điều gì về MS VisualStudio? mặc dù không có nguồn mở, ai đó từ MS có thể xác minh rằng họ cũng đang sử dụng trình phân tích cú pháp gốc đệ quy viết tay không?
OrenIshShalom

3
@GeneBushuyev, từ wiki GCC: "... Mặc dù timings cho thấy sự tăng tốc 1,5% , những lợi ích chính đang tạo điều kiện cho các cải tiến trong tương lai ..." tăng tốc này có vẻ khá lề ...
OrenIshShalom

Câu trả lời:


78

Đúng:

  • GCC đã từng sử dụng trình phân tích cú pháp yacc (bison), nhưng nó đã được thay thế bằng trình phân tích cú pháp gốc đệ quy viết tay tại một số điểm trong loạt 3.x: xem http://gcc.gnu.org/wiki/New_C_Parser cho liên kết đến các bản vá lỗi có liên quan.

  • Clang cũng sử dụng trình phân tích cú pháp gốc đệ quy viết tay: xem phần "Một trình phân tích cú pháp hợp nhất duy nhất cho C, Objective C, C ++ và Objective C ++" ở gần cuối http://clang.llvm.org/features.html .


3
Điều đó có nghĩa là ObjC, C và C ++ có Ngữ pháp LL (k)?
Lindemann

47
Không: ngay cả C, đơn giản nhất trong ba, có ngữ pháp không rõ ràng. Ví dụ, foo * bar;có thể phân tích cú pháp dưới dạng một biểu thức nhân (với kết quả không được sử dụng) hoặc một khai báo của một biến barcó kiểu con trỏ-to- foo. Cái nào đúng phụ thuộc vào việc một typedeffor foocó nằm trong phạm vi tại thời điểm đó hay không, đây không phải là thứ có thể được xác định bằng bất kỳ lượng tìm kiếm nào. Nhưng điều đó chỉ có nghĩa là trình phân tích cú pháp gốc đệ quy cần một số máy móc bổ sung xấu xí được thêm vào để xử lý điều đó.
Matthew Slattery vào

9
Tôi có thể xác nhận từ bằng chứng thực nghiệm, rằng C ++ 11, C và Objective C có ngữ pháp không có ngữ cảnh mà trình phân tích cú pháp GLR có thể xử lý.
Ira Baxter

2
Về mức độ nhạy cảm với ngữ cảnh, câu trả lời này cũng không khẳng định rằng: việc phân tích cú pháp các ngôn ngữ này có thể là Turing-complete.
Ioannis Filippidis

106

Có một định lý dân gian nói rằng C rất khó để phân tích cú pháp, và C ++ về cơ bản là không thể.

Nó không đúng.

Điều đúng là C và C ++ khá khó để phân tích cú pháp bằng cách sử dụng bộ phân tích cú pháp LALR (1) mà không cần đến máy móc phân tích cú pháp và làm rối trong dữ liệu bảng ký hiệu. Trên thực tế, GCC đã sử dụng để phân tích cú pháp chúng, sử dụng YACC và các phương thức hack bổ sung như thế này, và vâng, nó thật tệ. Giờ đây, GCC sử dụng các trình phân tích cú pháp viết tay, nhưng vẫn với hack bảng biểu tượng. Người Clang chưa bao giờ cố gắng sử dụng các trình tạo phân tích cú pháp tự động; AFAIK trình phân tích cú pháp Clang luôn được mã hóa thủ công gốc đệ quy.

Điều đúng là C và C ++ tương đối dễ phân tích cú pháp với các trình phân tích cú pháp được tạo tự động mạnh hơn, ví dụ: trình phân tích cú pháp GLR và bạn không cần bất kỳ bản hack nào. Bộ phân tích cú pháp Elsa C ++ là một ví dụ về điều này. Giao diện người dùng C ++ của chúng tôi là một giao diện khác (cũng như tất cả các giao diện người dùng "trình biên dịch" của chúng tôi, GLR là công nghệ phân tích cú pháp khá tuyệt vời).

Giao diện người dùng C ++ của chúng tôi không nhanh bằng GCC và chắc chắn chậm hơn Elsa; chúng tôi đã dành ít năng lượng để điều chỉnh nó một cách cẩn thận bởi vì chúng tôi có những vấn đề cấp bách khác (tuy nhiên nó đã được sử dụng trên hàng triệu dòng mã C ++). Elsa có thể chậm hơn GCC đơn giản vì nó chung chung hơn. Với tốc độ của bộ xử lý ngày nay, những khác biệt này có thể không quan trọng nhiều trong thực tế.

Nhưng các "trình biên dịch thực sự" được phân phối rộng rãi ngày nay có nguồn gốc từ các trình biên dịch của 10, 20 năm trước hoặc hơn. Sau đó, sự kém hiệu quả còn quan trọng hơn nhiều, và chưa ai nghe nói về trình phân tích cú pháp GLR, vì vậy mọi người đã làm những gì họ biết cách làm. Clang chắc chắn là gần đây hơn, nhưng sau đó các định lý dân gian vẫn giữ được "sức thuyết phục" của chúng trong một thời gian dài.

Bạn không cần phải làm theo cách đó nữa. Bạn rất có thể sử dụng hợp lý GLR và các trình phân tích cú pháp khác làm giao diện người dùng, với sự cải thiện về khả năng bảo trì trình biên dịch.

Sự thật như thế nào, là khó có được một ngữ pháp phù hợp với hành vi của trình biên dịch hàng xóm thân thiện của bạn. Trong khi hầu như tất cả các trình biên dịch C ++ đều triển khai (hầu hết) tiêu chuẩn ban đầu, chúng cũng có xu hướng có nhiều phần mở rộng góc tối, ví dụ: thông số kỹ thuật DLL trong trình biên dịch MS, v.v. Nếu bạn có một công cụ phân tích cú pháp mạnh, bạn có thể dành thời gian cố gắng lấy ngữ pháp cuối cùng để phù hợp với thực tế, thay vì cố gắng bẻ cong ngữ pháp của bạn để phù hợp với những hạn chế của trình phân tích cú pháp của bạn.

CHỈNH SỬA Tháng 11 năm 2012: Kể từ khi viết câu trả lời này, chúng tôi đã cải thiện giao diện người dùng C ++ của mình để xử lý C ++ 11 đầy đủ, bao gồm các phương ngữ biến thể ANSI, GNU và MS. Mặc dù có rất nhiều thứ bổ sung, chúng tôi không cần phải thay đổi công cụ phân tích cú pháp của mình; chúng tôi vừa sửa đổi các quy tắc ngữ pháp. Chúng tôi đã phải thay đổi phân tích ngữ nghĩa; C ++ 11 rất phức tạp về mặt ngữ nghĩa và công việc này làm tiêu hao nỗ lực để trình phân tích cú pháp chạy.

CHỈNH SỬA Tháng 2 năm 2015: ... hiện xử lý đầy đủ C ++ 14. (Xem lấy AST có thể đọc được của con người từ mã c ++ để phân tích cú pháp GLR của một đoạn mã đơn giản và "phân tích cú pháp khó chịu nhất" khét tiếng của C ++).

CHỈNH SỬA Tháng 4 năm 2017: Bây giờ xử lý (bản nháp) C ++ 17.


6
PostScript: Cũng giống như việc hiểu được ngữ pháp để khớp với những gì mà nhà cung cấp thực sự làm đã khó hơn, thì việc lấy tên và độ phân giải kiểu để phù hợp với cách giải thích của các nhà cung cấp khác nhau về sổ tay C ++ 11 thậm chí còn khó hơn, vì bằng chứng duy nhất bạn có là các chương trình biên dịch một chút khác, nếu bạn có thể tìm thấy chúng. Chúng tôi phần lớn đã qua khỏi tính đến tháng 8 năm 2013 cho C ++ 11 thích hợp, nhưng tôi hơi thất vọng một chút ở ủy ban C ++, nơi có vẻ rất khó tạo ra một tiêu chuẩn thậm chí còn lớn hơn (và theo kinh nghiệm, khó hiểu hơn) ở dạng C ++ 1 năm.
Ira Baxter

5
Tôi thực sự muốn biết: Bạn xử lý foo * bar;sự mơ hồ đó như thế nào?
Martin

14
@Martin: trình phân tích cú pháp của chúng tôi phân tích cú pháp nó theo cả hai cách, tạo ra một cây chứa các "nút mơ hồ" đặc biệt có con là các phân tích cú pháp thay thế; những đứa trẻ chia sẻ tối đa với con cái của chúng, vì vậy chúng tôi kết thúc bằng một DAG thay vì một cái cây. Sau khi phân tích cú pháp hoàn tất, chúng tôi chạy một trình đánh giá ngữ pháp thuộc tính (AGE) qua DAG (tên ưa thích của "dạo cây và làm mọi thứ" nếu bạn không biết) tính toán các loại của tất cả các số nhận dạng đã khai báo. ...
Ira Baxter

12
... Những đứa trẻ mơ hồ không thể đồng nhất về kiểu chữ; AGE khi phát hiện ra một đứa trẻ mơ hồ không thể đánh máy một cách hợp lý chỉ cần xóa nó đi. Những gì còn lại là những đứa trẻ đã được đánh máy tốt; do đó, chúng tôi đã xác định được phân tích cú pháp nào của "foo bar;" đúng. Thủ thuật này phù hợp với tất cả các loại mơ hồ điên rồ được tìm thấy trong ngữ pháp thực mà chúng tôi xây dựng cho phương ngữ thực của C ++ 11 và * hoàn toàn tách biệt việc phân tích cú pháp khỏi phân tích ngữ nghĩa cho tên. Sự tách biệt rõ ràng này có nghĩa là ít công việc kỹ thuật phải làm hơn (không có rối để gỡ lỗi). Xem stackoverflow.com/a/1004737/120163 để thảo luận thêm.
Ira Baxter

3
@TimCas: Trên thực tế, tôi đang cùng bạn trải qua sự ngu ngốc của việc thiết kế cú pháp ngôn ngữ (và ngữ nghĩa) quá phức tạp đến mức rất khó để làm cho nó đúng (vâng, ngôn ngữ C ++ mắc phải ở đây rất tệ). Tôi ước các ủy ban thiết kế ngôn ngữ sẽ thiết kế cú pháp để các công nghệ phân tích cú pháp đơn giản hơn sẽ hoạt động và xác định rõ ràng ngữ nghĩa của ngôn ngữ và kiểm tra nó bằng một số công cụ phân tích ngữ nghĩa. Than ôi, thế giới dường như không phải như vậy. Vì vậy, tôi có quan điểm rằng bạn xây dựng những gì bạn phải xây dựng tốt nhất có thể, và tiếp tục với cuộc sống, bất chấp những khó khăn.
Ira Baxter

31

Trình phân tích cú pháp của Clang là trình phân tích cú pháp gốc đệ quy được viết tay, cũng như một số giao diện người dùng C và C ++ mã nguồn mở và thương mại khác.

Clang sử dụng trình phân tích cú pháp gốc đệ quy vì một số lý do:

  • Hiệu suất : trình phân tích cú pháp viết tay cho phép chúng tôi viết trình phân tích cú pháp nhanh, tối ưu hóa các đường dẫn nóng nếu cần và chúng tôi luôn kiểm soát hiệu suất đó. Việc có một trình phân tích cú pháp nhanh đã cho phép Clang được sử dụng trong các công cụ phát triển khác mà các trình phân tích cú pháp "thực" thường không được sử dụng, ví dụ: tô sáng cú pháp và hoàn thành mã trong IDE.
  • Chẩn đoán và khôi phục lỗi : bởi vì bạn có toàn quyền kiểm soát với trình phân tích cú pháp gốc đệ quy viết tay, nên dễ dàng thêm các trường hợp đặc biệt để phát hiện các sự cố thường gặp và cung cấp chẩn đoán và khôi phục lỗi tuyệt vời (ví dụ: xem http: //clang.llvm .org / features.html # expressivediags ) Với các trình phân tích cú pháp được tạo tự động, bạn bị giới hạn khả năng của trình tạo.
  • Tính đơn giản : trình phân tích cú pháp đệ quy gốc dễ viết, dễ hiểu và gỡ lỗi. Bạn không cần phải là một chuyên gia phân tích cú pháp hoặc tìm hiểu một công cụ mới để mở rộng / cải thiện trình phân tích cú pháp (điều này đặc biệt quan trọng đối với một dự án nguồn mở), nhưng bạn vẫn có thể nhận được kết quả tuyệt vời.

Nhìn chung, đối với một trình biên dịch C ++, điều đó không quan trọng lắm: phần phân tích cú pháp của C ++ không phải là tầm thường, nhưng nó vẫn là một trong những phần dễ dàng hơn, vì vậy bạn phải giữ cho nó đơn giản. Phân tích ngữ nghĩa --- đặc biệt là tra cứu tên, khởi tạo, giải quyết quá tải và khởi tạo mẫu --- là các đơn đặt hàng phức tạp hơn phân tích cú pháp. Nếu bạn muốn có bằng chứng, hãy kiểm tra việc phân phối mã và các cam kết trong thành phần "Sema" của Clang (để phân tích ngữ nghĩa) so với thành phần "Phân tích cú pháp" của nó (để phân tích cú pháp).


4
Vâng, phân tích ngữ nghĩa khó hơn rất nhiều. Chúng tôi có khoảng 4000 dòng quy tắc ngữ pháp bao gồm ngữ pháp C ++ 11 của chúng tôi và khoảng 180.000 dòng mã ngữ pháp thuộc tính cho danh sách Doub "phân tích ngữ nghĩa" ở trên, với 100.000 dòng mã hỗ trợ khác. Phân tích cú pháp thực sự không phải là vấn đề, mặc dù nó đủ khó nếu bạn bắt đầu sai.
Ira Baxter

1
Tôi không chắc rằng trình phân tích cú pháp viết tay nhất thiết phải tốt hơn cho việc báo cáo / khôi phục lỗi. Có vẻ như mọi người đã dồn nhiều năng lượng vào các trình phân tích cú pháp như vậy hơn là tăng cường các trình phân tích cú pháp được tạo ra bởi các máy phân tích cú pháp tự động trong thực tế. Có vẻ như có một nghiên cứu khá tốt về chủ đề này; bài báo đặc biệt này đã thực sự thu hút sự chú ý của tôi: MG Burke, 1983, Một phương pháp thực tế để chẩn đoán và khôi phục lỗi cú pháp LR và LL, Luận án Tiến sĩ, Khoa Khoa học Máy tính, Đại học New York, Xem archive.org/details/practicalmethodf00burk
Ira Baxter

1
... tiếp tục chương trình suy nghĩ này: nếu bạn sẵn sàng sửa đổi / mở rộng / tùy chỉnh trình phân tích cú pháp được xây dựng bằng tay của mình để kiểm tra các trường hợp đặc biệt nhằm chẩn đoán tốt hơn, thì bạn nên sẵn sàng đầu tư tương đương vào các chẩn đoán tốt hơn của trình phân tích cú pháp được tạo cơ học. Đối với bất kỳ phân tích cú pháp đặc biệt nào mà bạn có thể mã hóa cho sổ tay thủ công, bạn cũng có thể viết mã kiểm tra cho trình phân tích cơ học (và đối với trình phân tích cú pháp (G) LR, bạn có thể thực hiện khá nhiều điều này như kiểm tra ngữ nghĩa khi giảm bớt). Ở mức độ có vẻ không được tốt, người ta chỉ đang lười biếng nhưng đó không phải là bản cáo trạng của trình phân tích cú pháp được tạo ra một cách máy móc IMHO.
Ira Baxter

8

trình phân tích cú pháp của gcc được viết tay. . Tôi nghi ngờ điều tương tự đối với tiếng kêu. Điều này có thể là vì một vài lý do:

  • Hiệu suất : thứ mà bạn đã tối ưu hóa thủ công cho tác vụ cụ thể của mình hầu như sẽ luôn hoạt động tốt hơn so với một giải pháp chung chung. Trừu tượng thường có hiệu suất cao
  • Thời gian : ít nhất là trong trường hợp của GCC, GCC có trước rất nhiều công cụ dành cho nhà phát triển miễn phí (ra mắt vào năm 1987). Không có phiên bản miễn phí của yacc, v.v. vào thời điểm đó, điều mà tôi tưởng tượng sẽ được ưu tiên cho những người tại FSF.

Đây có lẽ không phải là một trường hợp của hội chứng "không được phát minh ra ở đây", nhưng nhiều hơn là "không có gì được tối ưu hóa cụ thể cho những gì chúng tôi cần, vì vậy chúng tôi đã viết của riêng mình".


15
Không có phiên bản miễn phí của yacc vào năm 1987? Tôi nghĩ rằng đã có những phiên bản miễn phí khi yacc lần đầu tiên được phân phối dưới Unix vào những năm 70. Và IIRC (áp phích khác có vẻ giống nhau), GCC từng có trình phân tích cú pháp dựa trên YACC. Tôi nghe nói lý do cho việc thay đổi nó là để báo cáo lỗi tốt hơn.
Ira Baxter

7
Tôi muốn nói thêm rằng việc tạo các thông báo lỗi tốt từ trình phân tích cú pháp viết tay thường dễ dàng hơn.
Dietrich Epp

1
Quan điểm của bạn về Thời gian là không chính xác. GCC từng có trình phân tích cú pháp dựa trên YACC, nhưng điều này đã được thay thế bằng trình phân tích cú pháp gốc đệ quy viết tay, sau này.
Tommy Andersen

7

Câu trả lời kỳ lạ ở đó!

Ngữ pháp C / C ++ không có ngữ cảnh. Chúng nhạy cảm với ngữ cảnh vì thanh Foo *; sự mơ hồ. Chúng ta phải xây dựng một danh sách các typedef để biết Foo có phải là một loại hay không.

Ira Baxter: Tôi không hiểu vấn đề GLR của bạn. Tại sao phải xây dựng một cây phân tích cú pháp bao gồm những điều không rõ ràng. Phân tích cú pháp có nghĩa là giải quyết sự mơ hồ, xây dựng cây cú pháp. Bạn giải quyết những sự mơ hồ này trong một lần xử lý thứ hai, vì vậy điều này không ít xấu xí hơn. Đối với tôi nó còn xấu xa hơn nhiều ...

Yacc là trình tạo phân tích cú pháp LR (1) (hoặc LALR (1)), nhưng nó có thể dễ dàng sửa đổi để có ngữ cảnh nhạy cảm. Và không có gì xấu xí trong đó. Yacc / Bison đã được tạo ra để giúp phân tích ngôn ngữ C, vì vậy có lẽ nó không phải là công cụ xấu nhất để tạo trình phân tích cú pháp C ...

Cho đến GCC 3.x, trình phân tích cú pháp C được tạo bởi yacc / bison, với bảng typedefs được xây dựng trong quá trình phân tích cú pháp. Với việc xây dựng bảng typedefs "in parse", ngữ pháp C trở nên không có ngữ cảnh cục bộ và hơn nữa là "local LR (1)".

Bây giờ, trong Gcc 4.x, nó là một trình phân tích cú pháp gốc đệ quy. Nó hoàn toàn giống với trình phân tích cú pháp như trong Gcc 3.x, nó vẫn là LR (1) và có cùng các quy tắc ngữ pháp. Sự khác biệt là trình phân tích cú pháp yacc đã được viết lại bằng tay, chuyển / giảm hiện được ẩn trong ngăn xếp cuộc gọi và không có "state454: if (nextsym == '(') goto state398" như trong gcc 3.x yacc's phân tích cú pháp, do đó, việc vá lỗi, xử lý lỗi và in thư đẹp hơn dễ dàng hơn và thực hiện một số bước biên dịch tiếp theo trong quá trình phân tích cú pháp. Với mức giá thấp hơn nhiều mã "dễ đọc" cho một gcc noob.

Tại sao họ chuyển từ yacc sang đệ quy? Bởi vì nó là khá cần thiết để tránh yacc để phân tích cú pháp C ++, và vì GCC mơ ước là trình biên dịch đa ngôn ngữ, tức là chia sẻ tối đa mã giữa các ngôn ngữ khác nhau mà nó có thể biên dịch. Đây là lý do tại sao C ++ và C parser được viết theo cùng một cách.

C ++ khó phân tích cú pháp hơn C vì nó không phải là LR (1) "cục bộ" như C, nó thậm chí không phải là LR (k). Hãy xem func<4 > 2>đó là một hàm mẫu được khởi tạo với 4> 2, tức là func<4 > 2> phải được đọc là func<1>. Đây chắc chắn không phải là LR (1). Bây giờ hãy xem xét func<4 > 2 > 1 > 3 > 3 > 8 > 9 > 8 > 7 > 8>,. Đây là nơi mà một đường xuống đệ quy có thể dễ dàng giải quyết sự mơ hồ, với giá của một vài lệnh gọi hàm khác (parse_template_parameter là hàm phân tích cú pháp không rõ ràng. Nếu parse_template_parameter (17 mã thông báo) không thành công, hãy thử lại parse_template_parameter (15 mã thông báo), parse_template_parameter (13 mã thông báo) ... nó hoạt động).

Tôi không biết tại sao không thể thêm vào các ngữ pháp phụ đệ quy yacc / bison, có lẽ đây sẽ là bước tiếp theo trong phát triển trình phân tích cú pháp gcc / GNU?


9
"đối với tôi, nó còn xấu xa hơn nhiều". Những gì tôi có thể nói với bạn là kỹ thuật phân tích cú pháp chất lượng sản xuất sử dụng GLR và độ trễ giải quyết sự mơ hồ là thực tế với một nhóm thực sự nhỏ. Tất cả các giải pháp khác mà tôi đã thấy đã liên quan đến nhiều năm nghiến răng trước công chúng về những cú lộn ngược và hack cần thiết để làm cho nó hoạt động với LR, bạn đặt tên cho nó. Bạn có thể giả định rất nhiều công nghệ phân tích cú pháp mới thú vị khác, nhưng theo như tôi có thể nói, đó chỉ là việc nghiến răng nghiến lợi vào thời điểm này. Ý tưởng rẻ; thi hành là thân yêu.
Ira Baxter


@Fizz: Bài báo thú vị về phân tích cú pháp Pháo đài, một ngôn ngữ lập trình khoa học phức tạp. Họ cho biết một số điều lưu ý: a) trình tạo phân tích cú pháp cổ điển (LL (k), LALR (1)) không thể xử lý các ngữ pháp khó, b) họ đã thử GLR, gặp khó khăn với quy mô nhưng các nhà phát triển thiếu kinh nghiệm nên họ không hoàn thành [đó không phải là lỗi của GLR] và c) họ đã sử dụng trình phân tích cú pháp Packrat backtracking (giao dịch) và nỗ lực rất nhiều vào nó, bao gồm cả việc tạo ra các thông báo lỗi tốt hơn. Về ví dụ của họ về phân tích cú pháp "{| x || x ← mySet, 3 | x}", tôi tin rằng GLR sẽ làm điều đó tốt và nó không cần dấu cách.
Ira Baxter

0

Có vẻ như GCC và LLVM-Clang đang sử dụng trình phân tích cú pháp gốc đệ quy viết tay chứ không phải do máy tạo ra, dựa trên Bison-Flex, phân tích cú pháp từ dưới lên.

Nói riêng về Bison, tôi không nghĩ có thể xử lý ngữ pháp mà không cần phân tích cú pháp một số thứ một cách mơ hồ và thực hiện lần thứ hai sau đó.

Tôi biết Haskell's Happy cho phép phân tích cú pháp đơn nguyên (tức là phụ thuộc vào trạng thái) có thể giải quyết vấn đề cụ thể với cú pháp C, nhưng tôi biết không có trình tạo phân tích cú pháp C nào cho phép đơn nguyên trạng thái do người dùng cung cấp.

Về lý thuyết, khôi phục lỗi sẽ là một điểm có lợi cho trình phân tích cú pháp viết tay, nhưng kinh nghiệm của tôi với GCC / Clang là các thông báo lỗi không đặc biệt tốt.

Đối với hiệu suất - một số tuyên bố dường như không có cơ sở. Việc tạo ra một máy trạng thái lớn bằng cách sử dụng trình tạo phân tích cú pháp sẽ dẫn đến một cái gì đó O(n)và tôi nghi ngờ phân tích cú pháp là nút thắt cổ chai trong nhiều công cụ.


3
Câu hỏi này đã có một câu trả lời chất lượng rất cao, bạn đang cố gắng bổ sung điều gì?
tod
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.