2010-08-29 30 views
8

Tôi đang làm việc trên ngôn ngữ lập trình mới, nhưng tôi đã luôn luôn bối rối bởi thực tế là tất cả mọi người đang sử dụng yaxx/lex để phân tích mã, nhưng tôi thì không.yacc/lex hoặc mã hóa bằng tay?

Trình biên dịch của tôi (đã hoạt động) được mã hóa bằng C++/STL và tôi không thể nói nó phức tạp hoặc mất quá nhiều thời gian. Nó có cả một số loại lexer và phân tích cú pháp, nhưng chúng không được tạo tự động. Trước đó, tôi đã viết một trình biên dịch C (không đầy đủ spec) theo cùng một cách - nó đã có thể biên dịch chương trình trong 1 vượt qua, với tất cả các tài liệu tham khảo trở lại giải quyết & tiền xử lý - điều này chắc chắn là không thể với yacc/lex.

Tôi không thể thuyết phục bản thân để loại bỏ tất cả điều này, và bắt đầu lặn vào yaxx/lex - có thể cần một nỗ lực để thực hiện và có thể giới thiệu một số hạn chế ngữ pháp.

Có điều gì tôi nhớ khi không sử dụng yacc/lex không? Tôi có làm điều ác không?

Trả lời

3

Yacc là không linh hoạt trong một số cách sau:

  • xử lý lỗi tốt là khó khăn (về cơ bản, thuật toán của nó được chỉ định để phân tích một chuỗi chính xác một cách chính xác, nếu không, tất cả các cược đang tắt, đây là một trong những nguyên mà GCC chuyển đến một phân tích cú pháp viết tay)
  • bối cảnh phụ thuộc rất khó để thể hiện, trong khi với một cú pháp gốc đệ quy viết tay bạn chỉ có thể thêm một tham số vào các chức năng

Hơn nữa, tôi đã nhận thấy mã đối tượng lex/yacc đó là của vi lớn hơn một trình phân tích cú pháp đệ quy viết tay (mã nguồn có xu hướng là vòng khác).

Tôi chưa sử dụng ANTLR vì vậy tôi không thể nói nếu điều đó tốt hơn ở những điểm này.

1

Có thể bạn đang bỏ lỡ số ANTLR, điều này tốt cho các ngôn ngữ có thể được xác định bằng chiến lược phân tích cú pháp gốc.

Có khả năng một số lợi thế khi sử dụng Yacc/Lex, nhưng không bắt buộc phải sử dụng chúng. Có một số nhược điểm để sử dụng Yacc/Lex quá, nhưng những lợi thế thường lớn hơn những bất lợi. Đặc biệt, nó thường dễ dàng hơn để duy trì ngữ pháp định hướng Yacc so với ngữ pháp được mã hóa bằng tay và bạn được hưởng lợi từ việc tự động hóa mà Yacc cung cấp.

Tuy nhiên, việc viết trình phân tích cú pháp của riêng bạn từ đầu không phải là điều xấu. Nó có thể làm cho nó khó khăn hơn để duy trì trong tương lai, nhưng nó có thể làm cho nó dễ dàng hơn, quá.

6

Ưu điểm chính của việc sử dụng bất kỳ loại trình tạo trình phân tích cú pháp/trình phân tích cú pháp nào là nó mang đến cho bạn sự linh hoạt hơn nhiều nếu ngôn ngữ của bạn phát triển. Trong một lexer/parser được mã hóa bằng tay (đặc biệt nếu bạn đã trộn lẫn nhiều chức năng trong một lần!), Các thay đổi đối với ngôn ngữ trở nên khó chịu một cách nhanh chóng, trong khi với trình tạo trình phân tích cú pháp bạn thực hiện thay đổi, hãy chạy lại máy phát điện, và tiếp tục cuộc sống của bạn. Có chắc chắn không có giới hạn kỹ thuật cố hữu để luôn luôn chỉ viết tất cả mọi thứ bằng tay, nhưng tôi nghĩ rằng khả năng evolvability và bảo trì của tự động đi các bit nhàm chán là giá trị nó!

+2

Thiết kế tốt, kiểu mô-đun (ví dụ, trình phân tích mã thông báo và từ vựng phải được phân tách hoàn toàn) có thể làm cho vấn đề này ít hơn. Vẫn còn quan trọng. – delnan

3

Ưu điểm lớn khác của việc sử dụng máy phát điện là chúng được đảm bảo xử lý chính xác và chỉ ngôn ngữ bạn đã chỉ định trong ngữ pháp. Bạn không thể nói điều đó của bất kỳ mã viết tay nào. Các biến thể LR/LALR cũng được bảo đảm là O (N), một lần nữa bạn không thể khẳng định về bất kỳ mã hóa tay nào, ít nhất là không có nhiều nỗ lực trong việc xây dựng bằng chứng.

Tôi đã viết cả hai và sống với cả hai và tôi sẽ không bao giờ viết tay lại. Tôi chỉ làm điều đó vì tôi không có yacc trên nền tảng tại thời điểm đó.

+0

Vâng, tôi không cần một bằng chứng toán học để biết rằng mã của tôi là nhanh chóng - thường là nó rõ ràng rằng nó là một nơi nào đó trong O (N) hoặc O (N * LogN). – BarsMonster

+2

Tôi không nói gì về 'nhanh'. Tôi đang nói về sự phức tạp về thuật toán, và bạn cần một bằng chứng cho điều đó. – EJP

+0

Vâng, khi tôi viết mã, tôi luôn biết sự phức tạp của nó. Nếu công cụ nếu viết mã cho tôi - thì tôi chắc chắn sẽ cần một bằng chứng. – BarsMonster

0

Nó chắc chắn phụ thuộc vào sự phức tạp của ngữ pháp ngôn ngữ của bạn. Một ngữ pháp dễ dàng có nghĩa là có một triển khai dễ dàng và bạn có thể tự mình làm điều đó. Hãy xem xét một ví dụ tồi tệ nhất có thể: C++ :) (Có ai biết ngôn ngữ khác, ngoài ngôn ngữ tự nhiên, khó phân tích chính xác hơn?) Ngay cả với các công cụ như Antlr, có khá khó khăn không làm cho nó đúng, mặc dù nó có thể quản lý được. Do đó, ở phía bên kia, ngay cả khi khó khăn hơn nhiều, có vẻ như một số trình phân tích cú pháp C++ tốt nhất, ví dụ: GCC và LLVM, cũng chủ yếu là viết tay.

Nếu bạn không cần quá nhiều tính linh hoạt và ngôn ngữ của bạn không quá nhỏ, bạn chắc chắn sẽ an toàn một số công việc/thời gian bằng cách sử dụng Antlr.

+0

Độ phức tạp của ngôn ngữ của tôi chỉ nhỏ hơn C++ một chút. – BarsMonster

+1

Fortran cổ điển khá khó phân tích: nhiệm vụ "' DO10I = 12.43' "và vòng lặp DO" 'DO10I = 12,43'" thậm chí không thể chia thành các từ chính xác cho đến khi bạn đến dấu phẩy và dấu chấm hết. (Đầu tiên liên quan đến một biến dấu chấm động 'DO10I', biến thứ hai liên quan đến một biến số nguyên' I' và một nhãn '10':' DO 10 I = 12, 43'.) Điều này có xu hướng làm cho nó khá khó! –

Các vấn đề liên quan