2012-05-04 7 views
5

Mam następujący podwyrażenie do analizowania „cytaty”, które mają następujący formatWskazówki dotyczące FParsec do obsługi spacje

"5.75 @ 5.95" 

I dlatego mają tę parsec wyraz analizować je

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

działa dobrze ... z wyjątkiem sytuacji, gdy w moim wejściu jest spacja, ponieważ wyrażenie separatora zaczyna pochłaniać zawartość. Więc owinąłem ją próbą, która działa i wydaje się, z tego, co rozumiem, mniej więcej tym, co to miało być.

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

Ponieważ nie znam tak dobrze fparsec, zastanawiam się, czy istnieje lepszy sposób na napisanie tego. wydaje się nieco ciężki (a jednocześnie jest bardzo zarządzaniu oczywiście)

Odpowiedz

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

Uwagi:

  1. Zrobiłem spaces opcjonalnego wszędzie spaces pomija dowolną sekwencję zerowy lub więcej białych znaków, więc nie ma potrzeby korzystania z opt - Dzięki @Daniel;
  2. type Parser<'t> = Parser<'t, UserState> - Definiuję to w ten sposób, aby uniknąć błędu "ograniczenia wartości"; możesz go usunąć;
  3. Nie należy również zapominać, co następuje, gdy Twój program może działać na systemie z ustawieniami domyślnymi język mający przecinek dziesiętny: System.Threading.Thread.CurrentThread.CurrentCulture <- Globalization.CultureInfo.GetCultureInfo "en-US" to nie będzie działać, dzięki @Stephan
  4. Nie użyłbym sepBy chyba mam lista wartości o nieznanym rozmiarze.
  5. Jeśli naprawdę nie potrzebujesz zwróconej wartości (na przykład '@' znaków), zaleca się użycie funkcji skip* zamiast p* dla rozważań dotyczących wydajności.

UPD dodano ukośnik jako separator

+0

to 2 był ból. dobra sztuczka. wszystkie przydatne komentarze .. – nicolas

+0

twój projekt jest szalony. jesteś szalony. dobrze, że widzę tu jakiś parsek, świadectwo jakości, jak sądzę. – nicolas

+1

['spacje'] (http://www.quanttec.com/fparsec/reference/charparsers.html#members.spaces) analizuje zero lub więcej białych znaków - nie ma potrzeby używania' opt'. – Daniel

3

to pewnie zrobić coś takiego, która zwraca 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) 

To jest typowy dla każdej parser spożywać końcowe spacje. Upewnij się, że parser najwyższego poziomu zawiera eof.

1

Zakładając, że można mieć więcej niż dwa float w wejściu i „/” i „@” są ograniczniki:

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

Mówiąc o obchodzenia whitespaces, this section w tutorialu FParsec jest bardzo pomocna.