标签: fparsec

使用FParsec解析可选的多行表达式

我正在为这种形式的字符串编写一个FParsec解析器:

do[ n times]([ action] | \n([action]\n)*endDo)
Run Code Online (Sandbox Code Playgroud)

换句话说,这是一个带有可选时间量词的"do"语句,以及一个"action"语句或"action"列表(每个都在新行上),末尾有"end do"(I为简单起见省略了缩进/尾随空格处理.

这些是有效输入的示例:

do action

do 3 times action

do
endDo

do 3 times
endDo

do
action
action
endDo

do 3 times
action
action
endDo
Run Code Online (Sandbox Code Playgroud)

这看起来并不复杂,但是:

为什么这不起作用?

let statement = pstring "action"
let beginDo = pstring "do"
                >>. opt (spaces1 >>. pint32 .>> spaces1 .>> pstring "times")
let inlineDo = tuple2 beginDo (spaces >>. statement |>> fun w -> [w])
let expandedDo = (tuple2 (beginDo .>> newline)
                    (many (statement .>> newline)))
                 .>> pstring …
Run Code Online (Sandbox Code Playgroud)

f# fparsec

3
推荐指数
1
解决办法
534
查看次数

FParsec中的尾递归

我遇到了解析器有两个递归分支的问题.为了更容易地证明这个问题,我使用Luca Bolognese撰写的文章中的lambda演算的简单语法作为例子:

<expression> ::= <name> | <function> | <application>  
<name> ::= non­blank character sequence  
<function> ::= \ <name> . <body>  
<body> ::= <expression>  
<application> ::= ( <function expression> <argument expression> )  
<function expression> ::= <expression>  
<argument expression> ::= <expression>
Run Code Online (Sandbox Code Playgroud)

文章中的解析器非常简洁:

let ws = " \t\n" 
let specialChars = ".)(\\\n" 

let pWs = spaces 
let pName = manyChars (noneOf (ws + specialChars)) |>> EName 

let pExpr, pExprRef = createParserForwardedToRef<Expression, Unit>() 

let curry2 f a b = f(a,b) 
let pFunction …
Run Code Online (Sandbox Code Playgroud)

.net f# tail-recursion fparsec

3
推荐指数
1
解决办法
351
查看次数

为什么FParsec使用列表?

我以为我会尝试使用FParsec编写一个快速解析器,并很快意识到many返回列表是一个严重的性能问题.然后我发现了一个ResizeArray在文档中使用a的替代方法:

let manyA2 p1 p =
    Inline.Many(firstElementParser = p1,
                elementParser = p,
                stateFromFirstElement = (fun x0 ->
                                             let ra = ResizeArray<_>()
                                             ra.Add(x0)
                                             ra),
                foldState = (fun ra x -> ra.Add(x); ra),
                resultFromState = (fun ra -> ra.ToArray()),
                resultForEmptySequence = (fun () -> [||]))

let manyA p = manyA2 p p
Run Code Online (Sandbox Code Playgroud)

在我的代码中使用它会使它运行速度快几倍.那么为什么FParsec默认使用列表而不是ResizeArray

fparsec

3
推荐指数
1
解决办法
228
查看次数

FParsec和pipe3使参数显式或添加类型表示法

我试图使用库中的pipe3函数,FParsec但我得到一个错误,我不知道如何解决.

鉴于记录

type Point = { x: float; y: float }
Run Code Online (Sandbox Code Playgroud)

和以下解析器

let plistoffloats' =
    pipe3 pfloat (pchar ',' .>> spaces) pfloat 
        (fun first z second -> { x = first; y = second })
Run Code Online (Sandbox Code Playgroud)

我试图实现的是一个解析器,它接收格式的字符串"1.1, 3.7"并返回一个Point

run plistoffloats' "1.1, 3.7"
Run Code Online (Sandbox Code Playgroud)

输入:"1.1, 3.7"

期望的输出:Point = {x = 1.1; y = 3.7;}

错误:

错误FS0030:值限制.值'plistoffloats''被推断为具有泛型类型val plistoffloats':Parser <Point,'__a>
将'plistoffloats'的参数显式化,或者,如果您不打算将它作为泛型,则添加类型注释.

一个更简单的例子pchar也没有用.

let parsesA = pchar 'a'
Run Code Online (Sandbox Code Playgroud)

错误FS0030:值限制.值'parsesA'被推断为具有泛型类型val parsesA:Parser<char,'_a> …

f# parsing fparsec

3
推荐指数
1
解决办法
40
查看次数

避免一般使用返回两个函数的函数的值限制错误

我想将FParsec createParserForwardedToRef函数与通用的Expr联合一起使用,如下所示:

type Expr<'Term> =
        | Unary of Operator * Expr<'Term>
        | Binary of Operator * Expr<'Term> * Expr<'Term>
        | Ternary of Operator * Expr<'Term> * Expr<'Term> * Expr<'Term>
        | Term of 'Term
let expr, exprR = createParserForwardedToRef<Expr<'T>,unit>()
Run Code Online (Sandbox Code Playgroud)

我无法摆脱价值限制错误.我不能变成exprCLR功能,更不用说了exprR.

我通常如何处理这种情况?

f# type-inference fparsec

2
推荐指数
1
解决办法
202
查看次数

FParsec - 解析器序列

说我有一些文字:

a = "foobarbaz"
b = "foobar"
c = "foo"
d = "rubbish"
e = "foobazbar"
Run Code Online (Sandbox Code Playgroud)

和三个解析器foo,bar和baz分别用于字符串'foo','bar'和'baz'.

我如何创建一个可以给我结果的解析器:

a = ["foo", "bar", "baz"]
b = ["foo", "bar"]
c = ["foo"]
d = []
e = ["foo"]
Run Code Online (Sandbox Code Playgroud)

什么时候对上面的输入运行?在构建列表时,基本上尝试每种可能性直到失败.我可以使用用户状态,但我想尽可能避免.(我想让各个解析器自己对用户状态一无所知)

我得到的最接近的是下面的fooseq:

let foo = pstring "foo"
let bar = pstring "bar"
let baz = pstring "baz"

let foobar = pipe2 foo bar Seq.of2
let foobarbaz = pipe3 foo bar baz Seq.of3

let fooseq = choice (Seq.map attempt [foobarbaz; foobar; foo |>> Seq.of1 ;]) …
Run Code Online (Sandbox Code Playgroud)

f# parsing fparsec

2
推荐指数
1
解决办法
157
查看次数

使用 FParsec,如何在解析器之间使用 manyCharsTill 而不会在结束字符串上失败?

我正在尝试使用 FParsec 来解析 TOML 多行字符串,但在使用结束分隔符 ( """) 时遇到了问题。我有以下解析器:

let controlChars = 
    ['\u0000'; '\u0001'; '\u0002'; '\u0003'; '\u0004'; '\u0005'; '\u0006'; '\u0007';
     '\u0008'; '\u0009'; '\u000a'; '\u000b'; '\u000c'; '\u000d'; '\u000e'; '\u000f';
     '\u0010'; '\u0011'; '\u0012'; '\u0013'; '\u0014'; '\u0015'; '\u0016'; '\u0017';
     '\u0018'; '\u0019'; '\u001a'; '\u001b'; '\u001c'; '\u001d'; '\u001e'; '\u001f';
     '\u007f']

let nonSpaceCtrlChars =
    Set.difference (Set.ofList controlChars) (Set.ofList ['\n';'\r';'\t'])

let multiLineStringContents : Parser<char,unit> =
    satisfy (isNoneOf nonSpaceCtrlChars)

let multiLineString         : Parser<string,unit> =
    optional newline >>. manyCharsTill multiLineStringContents (pstring "\"\"\"")
    |> between (pstring "\"\"\"") (pstring "\"\"\"") 

let …
Run Code Online (Sandbox Code Playgroud)

f# parsing fparsec

2
推荐指数
1
解决办法
327
查看次数

F# FParsec parsing multiplication

I am trying to tackle the scariest part of programming for me and that is parsing and ASTs. I am working on a trivial example using F# and FParsec. I am wanting to parse a simple series of multiplications. I am only getting the first term back though. Here is what I have so far:

open FParsec

let test p str =
    match run p str with
    | Success(result, _, _) -> printfn  "Success: %A" result
    | Failure(errorMsg, _, _) …
Run Code Online (Sandbox Code Playgroud)

f# parsing fparsec

2
推荐指数
1
解决办法
87
查看次数

用FParsec解析字符串文字?

我想使用FParsec解析字符串文字.通过"字符串文字"我的意思是开始和结束报价(在我的情况下 - 单引号):

'Please, switch off your mobile phone'
Run Code Online (Sandbox Code Playgroud)

我目前正在做的是以下内容:

let string = between (pstring "'") (pstring "'") (manySatisfy isLetter)
Run Code Online (Sandbox Code Playgroud)

但是在消耗掉第一个字母后停止了.有没有办法让它变得贪婪?

f# parsing fparsec

1
推荐指数
1
解决办法
1099
查看次数

为什么我的 FParsec 解析器无法识别块注释?

我正在尝试使用 FParsec 解析 C 风格注释。不知道为什么会失败:

我的解析器代码:

let openComment : Parser<_,unit>  = pstring "/*"
let closeComment : Parser<_,unit> = pstring "*/"
let comment = pstring "//" >>. restOfLine true
                <|> openComment >>. (charsTillString "*/" true System.Int32.MaxValue) |>> Comment
                //<|> openComment >>. manyCharsTill anyChar closeComment |>> Comment
let spaceComments = many ((spaces1 |>> IgnoreU) <|> comment)
let str s  = spaceComments >>. pstring s .>> spaceComments
Run Code Online (Sandbox Code Playgroud)

测试线束:

let testStr = @"
// test comment
/* a block comment
   */
   x  // another …
Run Code Online (Sandbox Code Playgroud)

f# fparsec

1
推荐指数
1
解决办法
50
查看次数

使用F#解析日期

是否有一些'日期解析器'库可以用于日期FParsec对字符串的作用?

也就是说,您要么指定规则,要么匹配它们以识别提供的模式.


相反,是否有任何库可以根据一些解析规则生成日期?这个想法是为用户提供"实时"完成,以指导他进行有效的未来fparsec匹配.

(生成解析的这个问题在僻静的解析圈中有一个名字吗?)

f# parsec fparsec

0
推荐指数
1
解决办法
270
查看次数

FParsec - 如何从标准输入流解析

我似乎无法使用FParsec成功解析标准输入流.我把我的情况简化为这个非常简单的代码:

match (runParserOnStream (pstring "test" .>> FParsec.CharParsers.newline) () "stdin" (Console.OpenStandardInput ()) Console.InputEncoding) with
    | Success(result, _, _)   -> printfn "Success: %A" result
    | Failure(errorMsg, perr, _) -> printfn "Failure: %s" errorMsg
Run Code Online (Sandbox Code Playgroud)

但是,当我运行程序时,输入字符串测试,然后按Enter,它挂起,我似乎无法弄清楚为什么..

什么是解决方案?

.net f# parsing fparsec

0
推荐指数
1
解决办法
463
查看次数

标签 统计

fparsec ×12

f# ×11

parsing ×6

.net ×2

parsec ×1

tail-recursion ×1

type-inference ×1