关于FParsec处理空格的建议

nic*_*las 5 f# fparsec

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

"5.75 @ 5.95"
Run Code Online (Sandbox Code Playgroud)

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

let pquote x = (sepBy (pfloat) ((spaces .>> (pchar '/' <|>  pchar '@' )>>. spaces))) x
Run Code Online (Sandbox Code Playgroud)

它工作得很好..除非我的输入中有一个尾随空格,因为分隔符表达式开始消耗内容.所以我把它包裹在一次尝试中,根据我的理解,这看起来很像或多或少是这意味着什么成为.

let pquote x = (sepBy (pfloat) (attempt (spaces .>> (pchar '/' <|>  pchar '@' )>>. spaces))) x
Run Code Online (Sandbox Code Playgroud)

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

byt*_*ter 6

let s1 = "5.75         @             5.95              "
let s2 = "5.75/5.95   "
let pquote: Parser<_> =
    pfloat
    .>> spaces .>> skipAnyOf ['@'; '/'] .>> spaces
    .>>. pfloat
    .>> spaces
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 我在spaces spaces任何地方可以选择跳过零个或多个空格的任何序列,所以没有必要使用opt- 谢谢@Daniel;
  2. type Parser<'t> = Parser<'t, UserState> - 我这样定义它是为了避免"价值限制"错误; 你可以删除它;
  3. 此外,如果您的程序可能在具有带小数逗号的默认语言设置的系统上运行,请不要忘记以下内容:System.Threading.Thread.CurrentThread.CurrentCulture <- Globalization.CultureInfo.GetCultureInfo "en-US"这不起作用,谢谢@Stephan
  4. sepBy除非我有一个未知大小的值列表,否则我不会使用.
  5. 如果您确实不需要返回的值(例如'@'字符),建议使用skip*函数来代替p*性能.

UPD添加了斜杠作为分隔符