2012-05-04 3 views
5

J'ai la sous-expression suivante pour analyser « cite » qui ont le format suivant: les conseils FParsec pour le traitement des espaces

"5.75 @ 5.95" 

J'ai donc cette expression parsec pour l'analyser

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

Il fonctionne très bien .. sauf quand il y a un espace de fin dans mon entrée, comme l'expression du séparateur commence à consommer le contenu. Alors je l'ai enveloppé autour d'une tentative, qui fonctionne et semble, d'après ce que je comprends, plus ou moins ce que cela devait être. Comme je ne connais pas si bien fparsec, je me demande s'il y a une meilleure façon d'écrire ceci. il semble un peu lourd (tout en étant très facile à gérer bien sûr)

Répondre

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

Notes:

  1. J'ai fait spaces en option partout spaces permet de sauter une séquence de zéro ou plus des espaces blancs, donc il n'y a pas besoin d'utiliser opt - merci @ Daniel;
  2. type Parser<'t> = Parser<'t, UserState> - Je le définis de cette façon afin d'éviter une erreur de "restriction de valeur"; vous pouvez l'enlever;
  3. En outre, ne pas oublier ce qui suit si votre programme peut fonctionner sur un système avec les paramètres de langue par défaut ayant une virgule décimale: System.Threading.Thread.CurrentThread.CurrentCulture <- Globalization.CultureInfo.GetCultureInfo "en-US" cela ne fonctionnera pas, merci @Stephan
  4. Je ne voudrais pas utiliser sepBy à moins d'avoir une liste de valeurs de taille inconnue.
  5. Si vous n'avez pas vraiment besoin de la valeur renvoyée (par exemple, '@' caractères), il est recommandé d'utiliser les fonctions skip* au lieu de p* pour des raisons de performances.

UPD ajouté slash comme séparateur

+0

ce n ° 2 était une douleur. bonne astuce à savoir. tous les commentaires utiles .. – nicolas

+0

votre projet est fou. tu es fou. bon de voir du parsec utilisé ici, témoignage de qualité je suppose. – nicolas

+1

['spaces'] (http://www.quanttec.com/fparsec/reference/charparsers.html#members.spaces) analyse zéro ou plusieurs espaces - pas besoin d'utiliser' opt'. – Daniel

3

je ferais probablement quelque chose comme ça, qui retourne 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) 

Il est typique pour chaque analyseur pour consommer les espaces de fin. Assurez-vous simplement que votre analyseur de niveau supérieur inclut eof.

1

Si l'on suppose que vous pourriez avoir plus de deux float dans l'entrée et «/» et « @ » sont délimiteurs:

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

En parlant de manipulation des espaces blancs, this section dans le tutoriel FParsec est vraiment utile.

Questions connexes