2012-05-04 12 views
5

Tôi có subexpression sau đây để phân tích 'trích' mà có định dạng sauTư vấn về FParsec để xử lý khoảng trắng

"5.75 @ 5.95" 

do đó tôi có biểu hiện parsec này để phân tích nó

let pquote x = (sepBy (pfloat) ((spaces .>> (pchar '/' <|> pchar '@')>>. spaces))) x 

Nó hoạt động tốt .. ngoại trừ khi có dấu cách trong đầu vào của tôi, khi biểu thức dấu phân tách bắt đầu tiêu thụ nội dung. Tôi đã quấn nó quanh một nỗ lực, hoạt động và dường như, từ những gì tôi hiểu, nhiều hay ít ý nghĩa của điều này.

let pquote x = (sepBy (pfloat) (attempt (spaces .>> (pchar '/' <|> pchar '@')>>. spaces))) x 

Vì tôi không biết fparsec rất tốt, tôi tự hỏi nếu có cách nào tốt hơn để viết điều này. nó có vẻ hơi nặng (trong khi vẫn rất dễ quản lý tất nhiên)

Trả lời

6
let s1 = "5.75   @    5.95    " 
let s2 = "5.75/5.95 " 
let pquote: Parser<_> = 
    pfloat 
    .>> spaces .>> skipAnyOf ['@'; '/'] .>> spaces 
    .>>. pfloat 
    .>> spaces 

Ghi chú:

  1. Tôi đã thực hiện spaces tùy chọn ở khắp mọi nơi spaces bỏ qua bất kỳ chuỗi zero hoặc nhiều khoảng trắng, vì vậy không có nhu cầu sử dụng opt - nhờ @Daniel;
  2. type Parser<'t> = Parser<'t, UserState> - Tôi xác định theo cách này để tránh lỗi "hạn chế giá trị"; bạn có thể loại bỏ nó;
  3. Ngoài ra, đừng quên những điều sau nếu chương trình của bạn có thể chạy trên một hệ thống với các thiết lập ngôn ngữ mặc định có dấu phẩy thập phân: System.Threading.Thread.CurrentThread.CurrentCulture <- Globalization.CultureInfo.GetCultureInfo "en-US" này sẽ không hoạt động, nhờ @Stephan
  4. tôi sẽ không sử dụng sepBy trừ khi tôi có một danh sách giá trị có kích thước không xác định.
  5. Nếu bạn không thực sự cần giá trị trả lại (ví dụ: '@' ký tự), bạn nên sử dụng các hàm skip* thay vì p* để xem xét hiệu suất.

UPD thêm dấu gạch chéo như tách

+0

# này 2 là một nỗi đau. lừa tốt để biết. tất cả các ý kiến ​​hữu ích .. – nicolas

+0

dự án của bạn là điên rồ. bạn bị điên. tốt để xem một số parsec được sử dụng ở đây, lời khai của chất lượng tôi đoán. – nicolas

+1

['khoảng trống'] (http://www.quanttec.com/fparsec/reference/charparsers.html#members.spaces) phân tách không hoặc nhiều khoảng trống - không cần sử dụng' opt'. – Daniel

3

tôi có lẽ sẽ làm một cái gì đó như thế này, mà trả về float * float:

let ws = spaces 
let quantity = pfloat .>> ws 
let price = pfloat .>> ws 
let quoteSep = pstring "@" .>> ws 
let quote = quantity .>> quoteSep .>>. price //`.>> eof` (if final parser) 

Đó là điển hình cho mỗi phân tích cú pháp để tiêu thụ dấu khoảng trắng. Chỉ cần đảm bảo trình phân tích cú pháp cấp cao nhất của bạn bao gồm eof.

1

Giả sử rằng bạn có thể có nhiều hơn hai float trong đầu vào và '/' và '@' được delimiters:

let ws = spaces 
let str_ws s = pstring s .>> ws 
let float_ws = pfloat .>> ws 
let pquote = sepBy float_ws (str_ws "/" <|> str_ws "@") 

Nói về xử lý khoảng trắng, this section trong FParsec hướng dẫn là thực sự hữu ích.