Разбор int или float с FParsec
Я пытаюсь проанализировать файл, используя FParsec, который состоит из значений с плавающей запятой или int. Я сталкиваюсь с двумя проблемами, для которых я не могу найти хорошее решение.
1
И то и другоеpint32
а такжеpfloat
успешно проанализирует одну и ту же строку, но даст разные ответы, напримерpint32
вернусь3
при разборе строки"3.0"
а такжеpfloat
вернусь3.0
при разборе той же строки. Можно ли попробовать разобрать значение с плавающей запятой, используяpint32
и потерпеть неудачу, если строка"3.0"
?
Другими словами, есть ли способ заставить следующий код работать:
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
Этот фрагмент кода правильно поместит все значения с плавающей запятой вfloatvalues
список, а потомуpfloat
возвращается"3.0"
при разборе строки"3"
все целочисленные значения также будут помещены вfloatvalues
список.
2
Приведенный выше пример кода кажется мне немного неуклюжим, поэтому я предполагаю, что должен быть лучший способ сделать это. Я подумал объединить их, используяchoice
Однако оба парсера должны возвращать один и тот же тип, чтобы это работало. Я думаю, что я мог бы сделать дискриминационный союз с одним параметром для float и один для int и преобразовать вывод изpint32
а такжеpfloat
с использованием|>>
оператор. Однако мне интересно, есть ли лучшее решение?