关于FParsec处理空格的建议

时间:2012-05-04 15:56:15

标签: f# fparsec

我有以下子表达式来解析具有以下格式的“引号”

"5.75 @ 5.95"

因此我有这个parsec表达式来解析它

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

它工作得很好..除非我的输入中有一个尾随空格,因为分隔符表达式开始消耗内容。所以我把它包裹在一个尝试中,根据我的理解,它或多或少是有效的这本来就是。

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

由于我不太了解fparsec,我想知道是否有更好的方法来写这个。它似乎有点沉重(当然仍然很容易管理)

3 个答案:

答案 0 :(得分:6)

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

注意:

  1. 我已将spaces随处可选 spaces跳过或更多空格的任何序列,因此无需使用{{ 1}} - 谢谢@Daniel;
  2. opt - 我这样定义它是为了避免“价值限制”错误;你可以删除它;
  3. 此外,如果您的程序可能在具有带小数逗号的默认语言设置的系统上运行,请不要忘记以下内容:type Parser<'t> = Parser<'t, UserState> 这不起作用,谢谢@Stephan
  4. 我不会使用System.Threading.Thread.CurrentThread.CurrentCulture <- Globalization.CultureInfo.GetCultureInfo "en-US",除非我有一个未知大小的值列表。
  5. 如果您确实不需要返回的值(例如sepBy个字符),建议您使用'@'函数代替skip*进行性能考虑。
  6. UPD 添加了斜杠作为分隔符

答案 1 :(得分:3)

我可能会这样做,返回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)

每个解析器通常使用尾随空格。只需确保您的顶级解析器包含eof

答案 2 :(得分:1)

假设输入中有两个以上float,而'/'和'@'是分隔符:

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

谈到处理空格,FParsec教程中的this section非常有帮助。