2012-05-04 12 views
5

Ho il seguente sottoespressione per analizzare 'cita', che ha il seguente formatoConsigli su FParsec per la gestione di spazi bianchi

"5.75 @ 5.95" 

Ho quindi questa espressione parsec di analizzarlo

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

funziona benissimo .. eccetto quando c'è uno spazio finale nel mio input, poiché l'espressione separatore inizia a consumare contenuti. Quindi l'ho avvolto attorno a un tentativo, che funziona e sembra, da quello che ho capito, più o meno ciò che doveva essere.

Poiché non conosco molto bene fparsec, mi chiedo se ci sia un modo migliore per scrivere questo. mi sembra un po 'pesante (pur essendo molto maneggevole naturalmente)

risposta

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

Note:

  1. Ho fatto spaces opzionale ovunque spaces salta qualsiasi sequenza di a zero o più spazi bianchi, quindi non c'è alcuna necessità di utilizzare opt - grazie @ Daniel;
  2. type Parser<'t> = Parser<'t, UserState> - Lo definisco in questo modo per evitare l'errore "limitazione del valore"; puoi rimuoverlo;
  3. Inoltre, non dimenticare il seguente se il programma può funzionare su un sistema con le impostazioni della lingua di default con virgola decimale: System.Threading.Thread.CurrentThread.CurrentCulture <- Globalization.CultureInfo.GetCultureInfo "en-US" Questo non funziona, grazie @Stephan
  4. Non vorrei usare sepBy meno che non ho una lista valori di dimensioni sconosciute.
  5. Se non si ha realmente bisogno del valore restituito (ad esempio '@' caratteri), si consiglia di utilizzare le funzioni skip* invece p* per considerazioni sulle prestazioni.

UPD barra aggiunto come separatore

+0

questo # 2 è stato un dolore. buon trucco per saperlo. tutti i commenti utili .. – nicolas

+0

il tuo progetto è pazzo. sei pazzo. bello vedere un parsec usato qui, testimonianza di qualità immagino. – nicolas

+1

['spaces'] (http://www.quanttec.com/fparsec/reference/charparsers.html#members.spaces) analizza zero o più spazi bianchi: non è necessario utilizzare' opt'. – Daniel

3

avrei probabilmente fare qualcosa di simile, che restituisce 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) 

E' tipico per ogni parser di consumare spazio bianco in coda. Assicurati che il parser di primo livello includa eof.

1

Supponendo che si potrebbe avere più di due float nell'input e '/' e '@' sono delimitatori:

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

Parlando di spazi bianchi movimentazione, this section in FParsec tutorial è davvero utile.