2012-06-29 26 views
5

Tôi có bộ chuyển đổi bbcode -> html phản hồi sự kiện thay đổi trong vùng văn bản. Hiện nay, điều này được thực hiện bằng cách sử dụng một loạt các biểu thức chính quy, và có một số trường hợp bệnh lý. Tôi đã luôn luôn muốn làm sắc nét bút chì trong ngữ pháp này, nhưng không muốn bị cạo râu. Nhưng ... gần đây tôi đã trở thành nhận thức của pegjs, mà dường như một thực hiện khá đầy đủ của thế hệ phân tích cú pháp PEG. Tôi có hầu hết các ngữ pháp được chỉ định, nhưng bây giờ lại tự hỏi liệu đây có phải là một sử dụng thích hợp của một trình phân tích cú pháp toàn diện hay không.Sử dụng Phân tích cú pháp PEG để phân tích cú pháp BBCode: pegjs hoặc ... cái gì?

câu hỏi cụ thể của tôi là:

  1. Như ứng dụng của tôi dựa vào dịch những gì tôi có thể sang HTML và rời khỏi phần còn lại dưới dạng văn bản thô, không thực hiện bbcode sử dụng một phân tích cú pháp có thể thất bại trên một lỗi cú pháp có ý nghĩa ? Ví dụ: [url=/foo/bar]click me![/url] chắc chắn sẽ được dự kiến ​​thành công khi đã đóng dấu ngoặc đóng trên thẻ đóng. Nhưng người dùng sẽ thấy gì trong thời gian chờ đợi? Với regex, tôi chỉ có thể bỏ qua những thứ không phù hợp và coi nó là văn bản bình thường cho mục đích xem trước. Với một ngữ pháp chính thức, tôi không biết liệu điều này là có thể bởi vì tôi đang dựa vào việc tạo HTML từ một cây phân tích cú pháp và những gì không phân tích cú pháp là ... cái gì?

  2. Tôi không rõ nơi thực hiện các phép biến đổi. Trong một trình phân tích cú pháp dựa trên lex/yacc, tôi sẽ có các tệp tiêu đề và các ký hiệu biểu thị loại nút. Trong pegjs, tôi nhận được mảng lồng nhau với văn bản nút. Tôi có thể phát ra mã đã dịch như là một hành động của trình phân tích cú pháp được tạo bởi pegjs, nhưng nó có vẻ giống như một mùi mã để kết hợp một trình phân tích cú pháp và một bộ phát. Tuy nhiên, nếu tôi gọi PEG.parse.parse(), tôi nhận lại một cái gì đó như thế này:

[ 
     [ 
      "[", 
      "img", 
      "", 
      [ 
      "/", 
      "f", 
      "o", 
      "o", 
      "/", 
      "b", 
      "a", 
      "r" 
      ], 
      "", 
      "]" 
     ], 
     [ 
      "[/", 
      "img", 
      "]" 
     ] 
    ]

được đưa ra một ngữ pháp như:

document 
    = (open_tag/close_tag/new_line/text)* 

open_tag 
    = ("[" tag_name "="? tag_data? tag_attributes? "]") 


close_tag 
    = ("[/" tag_name "]") 

text 
    = non_tag+ 

non_tag 
    = [\n\[\]] 

new_line 
    = ("\r\n"/"\n") 

Tôi viết tắt ngữ pháp, tất nhiên, nhưng bạn Có được ý tưởng. Vì vậy, nếu bạn nhận thấy, không có thông tin theo ngữ cảnh trong mảng mảng cho tôi biết loại nút nào tôi có và tôi còn lại để so sánh chuỗi lại thậm chí nghĩ rằng trình phân tích cú pháp đã thực hiện việc này. Tôi hy vọng có thể xác định callbacks và sử dụng các hành động để chạy chúng trong khi phân tích cú pháp, nhưng có thông tin có sẵn trên Web về cách người ta có thể làm điều đó.

Tôi có đang sủa nhầm cây không? Tôi có nên quay trở lại quá trình quét regex và quên phân tích cú pháp không?

Cảm ơn

+0

Steve, câu hỏi của bạn rất thú vị (+1), tôi chỉ muốn làm điều tương tự trong phần mở rộng: phân tích cú pháp BBCode trong văn bản (không may đây là định dạng mà diễn đàn vẫn đang sử dụng) và tạo "sống "xem trước từ văn bản đã nhập bằng PEG.js hoặc bất kỳ nội dung nào khác ngoại trừ cụm từ thông dụng. Bạn đã quản lý để tạo ngữ pháp cho trình phân tích cú pháp BBCode chưa? Bạn không thể chia sẻ giải pháp của mình thông qua GitHub hay bất cứ thứ gì khác? Điều đó sẽ giúp tôi rất nhiều. Cảm ơn rất nhiều trước! – Sk8erPeter

+0

Tôi đã sử dụng [trình phân tích cú pháp bbcode của patorjk] (https://github.com/patorjk/Extendible-BBCode-Parser). Hoạt động tốt và có thể được điều chỉnh theo nhu cầu của riêng bạn nếu bạn có các thẻ đặc biệt. –

+0

Cảm ơn, tôi đã thấy thư viện này, nhưng nó sử dụng các biểu thức chính quy, mà tôi muốn tránh, bởi vì về mặt lý thuyết, phân tích BBCode bằng cách sử dụng cụm từ thông dụng không thể thực hiện được mà không có lỗi ([»» link] (http: // kore- nordmann.de/blog/do_NOT_parse_using_regexp.html)) trong một số trường hợp, ví dụ khi lồng ghép chúng vào nhau, vv Đó là lý do tại sao tôi muốn làm điều đó bằng cách sử dụng phân tích cú pháp biểu thức ngữ pháp biểu thức. Vì vậy, bạn không cố gắng cải tiến ngữ pháp mà bạn đã bắt đầu? :) Bạn không thể chia sẻ cơ sở của nó? :) – Sk8erPeter

Trả lời

2

Về câu hỏi đầu tiên của bạn, tôi phải tin rằng bản xem trước trực tiếp sẽ khó khăn. Các vấn đề bạn đã chỉ ra liên quan đến việc trình phân tích cú pháp sẽ không hiểu rằng đầu vào là "công việc đang tiến hành" là chính xác. Peg.js cho bạn biết điểm nào là lỗi, vì vậy có thể bạn có thể lấy thông tin đó và quay lại một vài từ và phân tích cú pháp lại hoặc nếu thẻ kết thúc bị thiếu, hãy thử thêm nó ở cuối.

Phần thứ hai của câu hỏi của bạn dễ dàng hơn nhưng ngữ pháp của bạn sẽ không đẹp hơn sau này. Về cơ bản những gì bạn làm là đặt callbacks trên mọi quy tắc, ví dụ:

text 
    = text:non_tag+ { 
    // we captured the text in an array and can manipulate it now 
    return text.join(""); 
    } 

Hiện tại bạn phải viết những lời gọi lại này trong ngữ pháp của bạn. Tôi đang làm rất nhiều công cụ này ngay bây giờ, vì vậy tôi có thể thực hiện một pullrequest để peg.js để khắc phục điều đó. Nhưng tôi không chắc khi nào tôi tìm ra thời gian để làm điều này.

1

Hãy thử một cái gì đó như quy tắc thay thế này. Bạn đang đi đúng hướng; bạn chỉ cần nói với nó để tập hợp các kết quả.

văn bản = kết quả: non_tag + {return result.join (''); }

3

Trước câu hỏi (ngữ pháp cho văn bản đầy đủ):

Bạn có thể thêm

incomplete_tag = ("[" tag_name "="? tag_data? tag_attributes?) 
//       the closing bracket is omitted ---^ 

sauopen_tag và thay đổi document để bao gồm một thẻ chưa đầy đủ ở cuối. Bí quyết là bạn cung cấp cho trình phân tích cú pháp tất cả các sản phẩm cần thiết để luôn luôn phân tích cú pháp, nhưng các giá trị hợp lệ sẽ xuất hiện trước. Sau đó, bạn có thể bỏ qua incomplete_tag trong bản xem trước trực tiếp.

Câu hỏi thứ hai (làm thế nào để bao gồm các hành động):

bạn viết cái gọi là hành động sau biểu thức. Một hành động là mã Javascript kèm theo dấu ngoặc và được cho phép sau biểu thức pegjs, i. e. cũng ở giữa sản xuất!

Trong các hành động thực hành như { return result.join("") } hầu như luôn luôn cần thiết vì pegjs chia thành các ký tự đơn. Các mảng lồng nhau phức tạp cũng có thể được trả về. Vì vậy, tôi thường viết các hàm trợ giúp trong trình khởi tạo pegjs ở phần đầu của ngữ pháp để giữ các hành động nhỏ. Nếu bạn chọn tên hàm một cách cẩn thận thì hành động sẽ tự ghi lại tài liệu.

Để xem thử, hãy xem PEG for Python style indentation. Disclaimer: đây là một câu trả lời của tôi.