2012-07-01 50 views
5

Tôi đang cố gắng phân tích ngôn ngữ mà các toán tử có thuộc tính động (ưu tiên và ưu tiên) bằng trình phân tích cú pháp Menhir (tương tự như Ocamlyacc). Trong giai đoạn lexing, tất cả các toán tử điền vào một mã thông báo OP:string (vì vậy "+" biến thành (OP "+"), v.v ...).Chỉ định ưu tiên động và ưu tiên cho một toán tử trong Menhir/Ocamlyacc

Thuộc tính toán tử được xác định tại thời gian phân tích cú pháp và điền vào bảng liên kết toán tử và thuộc tính của chúng. Với bảng này, làm thế nào tôi có thể hướng dẫn Menhir tự động thay đổi mức độ ưu tiên của quy tắc phân tích cú pháp toán tử dựa trên dữ liệu của bảng này?

Xin cảm ơn, CharlieP.

Trả lời

10

Tôi rất tiếc vì đã trả lời bằng nhận xét "bạn đang làm sai". Tôi có ba phản đối mà tôi hy vọng là mang tính xây dựng, theo thứ tự giảm dần mức độ liên quan:

  1. Menhir không dành cho các cập nhật ngữ pháp động; nếu bạn nhấn mạnh vào việc thay đổi ngữ pháp của bạn tại thời điểm phân tích cú pháp, bạn nên sử dụng một công cụ cung cấp tính năng này, chẳng hạn như trình phân tích cú pháp GLR Dypgen. Sổ tay Dypgen đề cập đến khả năng tự động cập nhật các ưu tiên của nhà điều hành, theo cách hạn chế (có vẻ như bạn có thể thêm toán tử mới và các ưu tiên tương ứng, nhưng không thay đổi mức độ ưu tiên của các toán tử hiện tại) có thể hoặc không phù hợp với nhu cầu của bạn. Xem phần 6.6 của Dypgen manual (PDF), trang ... 42.

  2. Tự động cập nhật ngữ pháp CFG là, tôi nghĩ, không phải là cách tốt nhất để xử lý các tiền tố toán tử do người dùng xác định. Agda có các toán tử mixfix do người dùng định nghĩa rất chung và giải pháp của họ gần như sau: sử dụng trình phân tích cú pháp CFG của bạn để phân tích cú pháp cấu trúc ngữ pháp được biết đến tĩnh, nhưng đối với biểu thức có thể sử dụng các tiền tố và liên kết ưa thích, chỉ cần phân tích cú pháp chúng thành danh sách mã thông báo. Ví dụ: let x = if foo then x + y * z else bar sẽ được phân tích cú pháp thành một cái gì đó như Let(x, If(foo, Expr(x, +, y, *, z), bar). Một chiếc pass chuyên dụng sau này có thể thu thập thông tin cần thiết để phân tích cú pháp các thông tin đó thành các nút Expr vào cấu trúc chuyên dụng của chúng. Sử dụng trình tạo trình phân tích cú pháp cho những gì chúng tốt cho (CFG giàu được biết đến tĩnh) và sử dụng một đoạn hậu xử lý cho các công cụ phức tạp, không xác định và động. Các chàng trai của Agda có một số tài liệu về chủ đề này, ví dụ: Parsing Mixfix Operators, Danielsson and Norell, 2009.

    Từ quan điểm thiết kế, tôi khuyên bạn tách riêng phần lexing và phân tích thành nhiều đường khác nhau, mỗi thẻ đều tốt -defined và chỉ sử dụng thông tin thu thập được trên cấu trúc trước đó, thay vì cố gắng tự động thay đổi hành vi của chính nó. Bạn sẽ có một cái gì đó đơn giản hơn nhiều và mạnh mẽ hơn nhiều.

  3. Ưu tiên hoặc ưu tiên động hoặc do người dùng xác định, theo ý kiến ​​của tôi, có chút ác ý. OCaml có một hệ thống khác nhau nơi ưu tiên toán tử được xác định bởi vài ký tự đầu tiên của chúng (ví dụ: @, @@@+ là tất cả các liên kết phù hợp). Đó là một chút hạn chế cho những người chọn một nhà điều hành, nhưng làm cho mã đọc cuộc sống thoải mái hơn nhiều, vì họ chỉ có một bộ quy tắc ngữ pháp để tìm hiểu, thay vì phải tự động điều chỉnh mắt của họ cho bất kỳ đoạn mã mới nào . Nếu bạn muốn cho phép chèn các đoạn mã hoang dã, nước ngoài với một cú pháp hoàn toàn khác, các cơ chế trích dẫn (ví dụ: camlp4 <:foo<...>>) mạnh hơn nhiều so với các kết hợp và mức độ ưu tiên của nhà điều hành và cũng đơn giản hơn nhiều để phân tích cú pháp.

    Điều đó nói rằng, các dự án có nhu cầu khác nhau và tôi hoàn toàn hiểu nếu bạn khăng khăng đòi thay đổi nhà khai thác động và ưu tiên cho một số ứng dụng mà tôi không biết.Chỉ cần ghi nhớ rằng nó không phải là cách duy nhất xung quanh, và đôi khi sự nhất quán và đơn giản là tốt hơn so với tính linh hoạt tuyệt đối.