5

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

"5.75 @ 5.95"

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

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

它工作得很好..除非我的输入中有一个尾随空格,因为分隔符表达式开始消耗内容。所以我将它包裹在一个尝试中,根据我的理解,它工作并且似乎或多或少是什么意思成为。

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

因为我不太了解 fparsec,所以我想知道是否有更好的方法来写这个。它似乎有点重(当然仍然非常易于管理)

4

3 回答 3

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跳过了任何个或多个空格的序列,所以没有必要使用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添加斜杠作为分隔符

于 2012-05-04T18:18:02.587 回答
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.

于 2012-05-04T16:12:25.187 回答
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 教程中的这一部分真的很有帮助。

于 2012-05-04T16:21:21.857 回答