我对F#相当陌生,但在过去的几个星期里,我一直在阅读参考资料。我希望处理一个用户提供的输入字符串,识别和分离组成元素.例如,对于此输入:
XYZ酒店:6晚,220欧元/晚,外加17.5%的税
输出应该类似于一个元组列表:
("XYZ",Word);(“旅馆:”,Word); ("6",编号);(“夜晚”,字); ("at",操作员);("220",编号); ("EUR",CurrencyCode);("/",操作员);(“夜”,单词); (“+”,操作员);("17.5",数字);("%",PerCent);(“税”,词)
因为我处理的是用户输入,所以它可能是任何东西。因此,期望用户遵守语法是不可能的。我想要识别数字(可以是整数、浮点数、负.)、度量单位(可选,但可以包括SI或帝国物理单位、货币代码、计数,例如我的示例中的“夜/秒”)、数学运算符(作为数学符号或包括"at“per”、" of“、”折扣“等在内的单词)和所有其他单词。
我的印象是我应该使用主动模式匹配--这是对的吗?--但我不确定如何开始。任何指向适当参考材料或类似例子的指示都是很好的。
发布于 2011-01-11 03:48:50
我使用FParsec库编写了一个示例。这个例子一点也不健壮,但是它给出了一个关于如何使用FParsec的很好的图片。
type Element =
| Word of string
| Number of string
| Operator of string
| CurrencyCode of string
| PerCent of string
let parsePerCent state =
(parse {
let! r = pstring "%"
return PerCent r
}) state
let currencyCodes = [|
pstring "EUR"
|]
let parseCurrencyCode state =
(parse {
let! r = choice currencyCodes
return CurrencyCode r
}) state
let operators = [|
pstring "at"
pstring "/"
|]
let parseOperator state =
(parse {
let! r = choice operators
return Operator r
}) state
let parseNumber state =
(parse {
let! e1 = many1Chars digit
let! r = opt (pchar '.')
let! e2 = manyChars digit
return Number (e1 + (if r.IsSome then "." else "") + e2)
}) state
let parseWord state =
(parse {
let! r = many1Chars (letter <|> pchar ':')
return Word r
}) state
let elements = [|
parseOperator
parseCurrencyCode
parseWord
parseNumber
parsePerCent
|]
let parseElement state =
(parse {
do! spaces
let! r = choice elements
do! spaces
return r
}) state
let parseElements state =
manyTill parseElement eof state
let parse (input:string) =
let result = run parseElements input
match result with
| Success (v, _, _) -> v
| Failure (m, _, _) -> failwith m发布于 2011-01-11 05:38:02
听起来你真正想要的只是一个雷克萨斯。FSParsec的一个很好的替代方案是FSLex。(不错的入门教程( albiet )有点过时,可以在我的旧博客这里上找到。)使用FSLex,您可以获取输入文本:
XYZ Hotel: 6 nights at 220EUR / night plus 17.5% tax并将其正确标记为如下所示:
[ Word("XYZ"); Hotel; Int(6); Word("nights"); Word("at"); Int(220); EUR; ... ]下一步,一旦您有了一个标记列表,就会执行某种形式的模式匹配/分析来提取语义信息(我认为这就是您真正想要的)。对于规范化的令牌流,它应该非常简单,如:
let rec processTokenList tokens =
match tokens with
| Float(x) :: Keyword("EUR") :: rest -> // Dollar amount x
| Word(x) :: Keyword("Hotel") :: rest -> // Hotel x
| hd :: rest -> // Couldn't find anything interesting...
processTokenList rest那至少能让你开始。但是请注意,随着你的输入得到更多的“正式”,你的词汇也会有用。(如果您只接受非常特定的输入,那么您可以使用适当的解析器并完成它!)
https://stackoverflow.com/questions/4653820
复制相似问题