Próbuję przeanalizować plik, używając FParsec, który składa się z wartości float lub int. Mam dwa problemy, na które nie mogę znaleźć dobrego rozwiązania.Parsowanie int lub float z FParsec
Zarówno pint32
i pfloat
powodzeniem analizować ten sam ciąg, ale dają różne odpowiedzi, np pint32
powróci 3
podczas analizowania ciąg "3.0"
i pfloat
powróci 3.0
podczas analizowania ten sam ciąg. Czy możliwe jest sparsowanie wartości zmiennoprzecinkowej przy użyciu pint32
i czy nie powiedzie się, jeśli ciąg znaków to "3.0"
?
Innymi słowy, czy istnieje sposób, aby następujące prace kodu:
let parseFloatOrInt lines =
let rec loop intvalues floatvalues lines =
match lines with
| [] -> floatvalues, intvalues
| line::rest ->
match run floatWs line with
| Success (r, _, _) -> loop intvalues (r::floatvalues) rest
| Failure _ ->
match run intWs line with
| Success (r, _, _) -> loop (r::intvalues) floatvalues rest
| Failure _ -> loop intvalues floatvalues rest
loop [] [] lines
Ten fragment kodu będzie prawidłowo umieścić wszystkie wartości zmiennoprzecinkowych na liście floatvalues
, ale ponieważ pfloat
powraca "3.0"
podczas analizowania string "3"
, wszystkie wartości całkowite zostaną również umieszczone na liście floatvalues
.
Powyższy przykład kodu wydaje się nieco niezdarny do mnie, więc zgaduję, że musi być lepszy sposób to zrobić. Zastanawiałem się nad łączeniem ich za pomocą choice
, jednak oba parsery muszą zwracać ten sam typ, aby działał. Sądzę, że mógłbym stworzyć dyskryminowany związek z jedną opcją float i jedną dla int i konwertować dane wyjściowe z pint32
i pfloat
przy użyciu operatora |>>
. Zastanawiam się jednak, czy istnieje lepsze rozwiązanie?
Tak przy okazji, @bytebuster, mam problemy z uruchomieniem pCombined na łańcuchu testowym, daje to komunikat o błędzie '' Kombinator 'many' został zastosowany do parsera, który się powiódł bez zużywania danych wejściowych i bez zmiany parsera stan w jakikolwiek inny sposób. ". Czy eof musi być obsługiwany? – Chepe
Świetnie, dzięki @bytebuster! Jeszcze jedno, próbowałem uruchomić parser na łańcuchu '" 2 "' po tym, jak usunąłem kombinator 'many', i wtedy dostałem ten sam problem, co opisałem powyżej, a mianowicie, że został on zwrócony jako float, ponieważ float parser przychodzi przed parserem int. Jakieś pomysły, jak temu zaradzić? – Chepe
@ Chep, sprawdź zaktualizowaną wersję. Mamy nadzieję, że odnosi się on do obu problemów. – bytebuster