F#、FParsec 和更新用户状态

2023-11-30

好吧,自从我的最后一个问题没有引起任何反应,我正在朝不同的方向前进。哈哈!

我找不到任何超出的例子官方文档管理用户状态或访问先前解析器的结果。

注意:这段代码的作用是not编译。

namespace MultipartMIMEParser

open FParsec
open System.IO


type Header = { name  : string
              ; value : string
              ; addl  : (string * string) list option }

type Content = Content of string
             | Post of Post list
and Post = { headers : Header list
           ; content : Content }

type private UserState = { Boundary : string }
  with static member Default = { Boundary="" }


module internal P =
  let ($) f x = f x
  let undefined = failwith "Undefined."
  let ascii = System.Text.Encoding.ASCII
  let str cs = System.String.Concat (cs:char list)

  let makeHeader ((n,v),nvps) = { name=n; value=v; addl=nvps}

  let runP p s = match runParserOnStream p UserState.Default "" s ascii with
                 | Success (r,_,_) -> r
                 | Failure (e,_,_) -> failwith (sprintf "%A" e)

  let blankField = parray 2 newline

  let delimited d e =
      let pEnd = preturn () .>> e
      let part = spaces >>. (manyTill $ noneOf d $ (attempt (preturn () .>> pstring d) <|> pEnd)) |>> str
       in part .>>. part

  let delimited3 firstDelimiter secondDelimiter thirdDelimiter endMarker =
      delimited firstDelimiter endMarker
      .>>. opt (many (delimited secondDelimiter endMarker
                      >>. delimited thirdDelimiter endMarker))

  // TODO: This is the parser I'm asking about.
  let pHeader =
      let includesBoundary s = undefined
      let setBoundary b = { Boundary=b }
       in delimited3 ":" ";" "=" blankField
          |>> makeHeader
          >>. fun stream -> if includesBoundary // How do I access the output from makeHeader here?
                            then stream.UserState <- setBoundary b // I need b to be read from the output of makeHeader.
                                 Reply ()
                            else Reply ()

  let pHeaders = manyTill pHeader $ attempt (preturn () .>> blankField)

  // N.b. This is the mess I'm currently wrestling with. It does not compile, and is
  // not sound yet.
  let rec pContent boundary =
      match boundary with
      | "" -> // Content is text.
              let line = restOfLine false
               in pipe2 pHeaders (manyTill line $ attempt (preturn () .>> blankField))
                  $ fun h c -> { headers=h
                               ; content=Content $ System.String.Join (System.Environment.NewLine,c) }
      | _  -> // Content contains boundaries.
              let b = "--"+boundary
              let p = pipe2 pHeaders (pContent b) $ fun h c -> { headers=h; content=c }
               in skipString b >>. manyTill p (attempt (preturn () .>> blankField))

  let pStream = runP (pipe2 pHeaders pContent $ fun h c -> { headers=h; content=c })


type MParser (s:Stream) =
  let r = P.pStream s

  let findHeader name =
      match r.headers |> List.tryFind (fun h -> h.name.ToLower() = name) with
      | Some h -> h.value
      | None   -> ""

  member p.Boundary =
    let isBoundary ((s:string),_) = s.ToLower() = "boundary"
    let header = r.headers
                 |> List.tryFind (fun h -> if h.addl.IsSome
                                           then h.addl.Value |> List.exists isBoundary
                                           else false)
     in match header with
        | Some h -> h.addl.Value |> List.find isBoundary |> snd
        | None   -> ""
  member p.ContentID = findHeader "content-id"
  member p.ContentLocation = findHeader "content-location"
  member p.ContentSubtype = findHeader "type"
  member p.ContentTransferEncoding = findHeader "content-transfer-encoding"
  member p.ContentType = findHeader "content-type"
  member p.Content = r.content
  member p.Headers = r.headers
  member p.MessageID = findHeader "message-id"
  member p.MimeVersion = findHeader "mime-version"

我试图解析的 POST 的截断示例如下:

content-type: Multipart/related; boundary="RN-Http-Body-Boundary"; type="multipart/related"

--RN-Http-Body-Boundary
Message-ID: <25845033.1160080657073.JavaMail.webmethods@exshaw>
Mime-Version: 1.0
Content-Type: multipart/related; type="application/xml";
  boundary="----=_Part_235_11184805.1160080657052"

------=_Part_235_11184805.1160080657052
Content-Type: Application/XML
Content-Transfer-Encoding: binary
Content-Location: RN-Preamble
Content-ID: <1430586.1160080657050.JavaMail.webmethods@exshaw>

XML document begins here...

所以基本上,你想做什么pHeader是将解析器用作 monad,而不是应用程序。根据你的代码风格,你来自 Haskell,所以我假设你知道这些词。然后是这样的:

  let pHeader =
      let includesBoundary s = undefined
      let setBoundary b = { Boundary=b }
       in delimited3 ":" ";" "=" blankField
          |>> makeHeader
          >>= fun header stream ->
               if includesBoundary header
               then let b = undefined // some expression including header, if I understood correctly
                    stream.UserState <- setBoundary b
                    Reply ()
               else Reply ()

或者你可以将其写在计算表达式中(这对应于 Haskell 中的 do-notation):

  let pHeader =
      let includesBoundary s = undefined
      let setBoundary b = { Boundary=b }
      parse {
          let! header =
              delimited3 ":" ";" "=" blankField
              |>> makeHeader
          return! fun stream ->
               if includesBoundary header
               then let b = undefined // some expression including header, if I understood correctly
                    stream.UserState <- setBoundary b
                    Reply ()
               else Reply ()
      }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

F#、FParsec 和更新用户状态 的相关文章

  • 如何将两个函数调用合并为一个?

    我想合并以下几行 let result1 add numbers let result2 add numbers n 变成这样的东西 let resultX add numbers gt add numbers n 我可以编写这样的函数吗
  • 不可为空字符串的 F# 类型别名

    我的代码中有一些域类型 我用它们来区分不同类型的字符串 因此编译器可以阻止我 例如以错误的顺序传递参数 type Foo string type Bar string let baz foo Foo bar Bar printfn A A
  • 在可移植类库中使用 F# JsonProvider 失败

    我正在尝试使用 JsonProvider 当我调用它的函数时出现以下错误 System TypeInitializationException was unhandled Message An unhandled exception of
  • F# 的 timeit 函数

    我想写一些类似的东西 let timeit x a gt b let start System DateTime Now x let duration System DateTime Now start printfn time usage
  • 继续“F# 中是否存在与 C# 的 nameof(..) 等效的内容?”

    参考F 中是否存在相当于 C 的 nameof 的功能 https stackoverflow com questions 48304398 is there an equivalent of cs nameof in f 在以下情况下如何
  • 在 F# 列表中键入扩展名

    假设我有一个类型 let MyType some info 但是 它通常用于列表 MyType list 所以我可以定义 let MyTypeList MyType list 有没有办法在 MyTypeList 上定义类型增强 我的实际情况
  • 不可变数据结构性能

    我不明白作为一个集合的东西怎么可能是不可变的并且仍然具有可接受的性能 根据我在 F Sets 中读到的内容 内部使用红黑树作为其实现 如果每次我们想要向红黑树添加新内容时 我们基本上都必须重新创建它 那么它如何才能具有良好的性能呢 我在这里
  • 在 F# 中的 Choice 之上构建 Either(或 Result)

    我根据 Scott Wlaschin 中的信息构建了一个成功 失败的 monadblog http fsharpforfunandprofit com posts computation expressions wrapper types
  • 如何使用 printf 自定义自定义类型的输出?

    我已经阅读了很多内容专家 F 并正在致力于构建一个实际的应用程序 在调试时 我已经习惯了传递这样的 fsi 命令 以使 repl 窗口中的内容清晰可见 fsi AddPrinter fun x myType gt myType ToStri
  • 双前向/后向管道操作符是否有记录?

    我记得读过有关双管道运算符的内容 gt 和 Example let print a b sprintf O O a b 1 2 gt print val it string 1 2 双 向前 向后 管道运算符记录在以下列表中MSDN 上的
  • 对 null/空值使用 bool.Parse 时出错

    我有一个使用管道运算符的表达式 该表达式将值转换为字符串 然后转换为布尔值 但有时原始值可能为空 当值为 null 时 如何使用模式匹配或其他方式假设 false type kv Dictionary
  • FParsec:如何组合解析器以便它们以任意顺序匹配

    任务是找到特定的键值对并解析它们 这些对可以按任何顺序出现 我的部分工作尝试 open FParsec type Parser lt a gt Parser lt a unit gt type Status Running Done typ
  • 是 F# 映射上的迭代还是集合中序遍历?

    AFAIK F Map 和 set 被实现为红黑树 所以我猜这些的迭代将是有序遍历 我做了一些测试 迭代结果总是排序的 但我想确定一下 是按顺序遍历吗 MSDN 上的文档非常适合解决这个问题 例如 返回值Set toSeq http msd
  • 我缺少什么:可以使用多个参数进行函数组合吗?

    我了解 F 中函数组合的基础知识 例如所述here http blogs msdn com b chrsmith archive 2008 06 14 function composition aspx 不过 也许我错过了一些东西 这 gt
  • F# 参数传递

    我一直认为 F 有两种不同的方式来传递参数 柯里化风格和元组风格 这实际上是正确的吗 是不是很简单一种风格 柯里化风格和参数可以是简单值或元组 e g someFunc a b 这不是一个函数吗one咖喱风格的参数恰好是一个元组 因此允许我
  • ProjectCracker 与 .netstandard 2.0 项目

    我的团队最近从使用 net 框架转向使用 net 标准 2 0 作为我们的 F 库 我们有一些在项目上运行的内部脚本来自动生成 Markdown 文档 这些脚本使用 F 编译器服务 SDK 来分析代码并检索类型元数据 文档注释等 我们正在使
  • 如何在 F# 中将对象转换为泛型类型列表

    在下面的代码片段中 我的目的是将 System Object 可能是 FSharpList 转换为它所持有的任何泛型类型的列表 match o with list lt gt gt addChildList o gt list lt gt
  • C 或 C++ 中是否有轻量级的多部分/表单数据解析器? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在考虑将多部分表单数据解析集成到 Web 服务器模块中 以便可以减轻后端 Web 应用程序 通常用动
  • f# 运行总计序列

    好吧 这看起来应该很容易 但我就是不明白 如果我有一个数字序列 如何生成由运行总计组成的新序列 例如 对于序列 1 2 3 4 我想将其映射到 1 3 6 10 以适当的功能方式 Use List scan https msdn micro
  • F# 获取随机数列表

    我正在尝试用随机数填充列表 但很难获得随机数部分 我现在打印出一个随机数 10 次 我想要的是打印出 10 个不同的随机数 let a new System Random Next 1 1000 let listOfSquares for

随机推荐

  • 使用 Java 访问 Android Manifest 属性

    这是清单示例 是否可以从 Java 访问属性 versionCode 和 versionName 如何
  • 写入有符号整数就像在 C++ 中写入无符号整数一样

    Is reinterpret cast这样做是安全的 这是最好的方法吗 例如 在下面的代码中 我有一个名为ibytestream 这允许读取uint16 ts and int16 t是从它 ibytestream next is a vec
  • 如何使用纯 javascript 将子级附加到具有指定类名的所有节点

    var menuheader document createElement li document getElementsByClassName subMenu appendChild menuheader 上面是代码片段 我收到此错误 f
  • NetBeans 12.6 的 TAB 和缩进问题

    交易是这样的 如果我在一行代码中使用 TAB 键 效果很好 我按下它 它会正常插入空格 如果我转到一个新行 一个没有代码的空行 它就不起作用 无论 像这样 System out pri nt 这是第一个问题 第 2 号 缩进 如果我在任意位
  • 在 jquery datetimepicker 中设置最大和最小日期时间

    我正在使用jquery datetimepicker 我想在其中设置mindate和时间 这是在第二个datetimepicker中选择的值 我尝试的是 date start datetimepicker autoSize true cha
  • 在运行时检查 Python 模块版本

    许多第三方 Python 模块都有一个属性 用于保存模块的版本信息 通常类似于module VERSION or module version 但有些则不然 此类模块的具体示例是 libxslt 和 libxml2 我需要检查运行时是否使用
  • 为什么这个 BASH 数组没有构建?

    为什么这个 bash 数组没有填充 我相信我过去也这样做过 回声 XECOMMAND 显示无数据 DIR 1 TEMPFILE tmp dir tmp ls l DIR tail n 2 sed s s g cut d f5 9 gt TE
  • 为什么这个嵌套的 content_tag 无法正确呈现?

    我的助手中有这个 def favorites count node content tag span class card favorite count do content tag i class icon heart node cach
  • 如何有选择地更新 wpf 中的模型

    当单击 listviewitem 时 我会在列表视图中显示模型列表 我打开一个绑定到 listviewitem 数据模型的对话框 并允许用户编辑各种属性 我正在尝试弄清楚如何处理 确定 和 取消 按钮 一方面 如果我将对话框直接绑定到列表视
  • Xcode单一窗口,显示来自xib文件的自定义视图

    我正在创建一个 OSX 应用程序 它有一个窗口 该窗口包含一个视图 在整个使用过程中呈现不同的视图 我目前的做法 在默认的 MainMenu xib 中 我在默认生成的窗口 这是我将使用的窗口 中为自定义视图创建了一个出口 我们就这样称呼它
  • 我可以用 C++ 扩展 lisp 吗?

    我可以从用 c 或 c 编写的库中调用 lisp 函数吗 我怎样才能扩展 lisp 当您想要执行一些系统调用或类似的操作时 这非常有用 从 lisp 调用非 lisp 代码的情况很少见 而且很少有必要 CLX CL 的 X11 客户端实现
  • 在 Swift 中,可以使用字符串来访问结构体属性吗?

    我有一个结构 我想知道是否可以使用括号语法访问变量 这是我的结构 import UIKit public struct Pixel public var value UInt32 public var red UInt8 public va
  • Objective-C 解密 AES 128 cbc 十六进制字符串

    我正在使用 Xcode 3 1 在 Snow Leopard 上为 iPhone 开发一个应用程序 该应用程序从 Restful Web 服务接收使用 AES 128 位 CBC 算法的十六进制格式的加密文本 该算法使用初始化向量 密钥 我
  • Android,从元素中删除边距和填充

    我有一个包含 LinearLayout 水平 的活动 我希望 LinearLyout 内的所有元素都被附加 没有边距或填充 我尝试了很多方法但没有效果 这是我最后一次尝试
  • IE8 返回“预期对象”[].slice.call [重复]

    这个问题在这里已经有答案了 我是 js 新手 这段代码适用于除 li 元素 选项卡 之外的所有浏览器 function slice call document querySelectorAll tabs forEach function e
  • 在 Windows 命令行上设置应用程序的窗口位置

    我有一个从桌面位置 0x0 开始的应用程序 我想在桌面中央打开它 我不想打开它并使用移动命令将其移动到中心 而是我的应用程序应该立即在中心位置启动 有什么方法可以通过命令提示符执行此操作吗 您将需要一个额外的实用程序 例如cmdow exe
  • 父节点移动时子节点不移动?

    我的世界有三个节点 玩家和 玩家视野 世界和视觉 SKShapeNodes 和我的玩家都使用 SKShapeNode 的自定义子类 当我移动世界时 所有玩家都会随之移动 但是当我移动玩家时 视觉节点保持固定在其位置 这可能是什么原因 这是我
  • 使用 Proxy 对象检测 Javascript 数组中的更改

    在 Javascript 中观察数组的变化相对简单 我使用的一种方法是这样的 subscribe to add update delete and splice changes Array observe viewHelpFiles fun
  • 失败后重新启动 Promise

    我使用 Nodejs 和 Q 来运行一系列异步函数 如果一个函数失败 我想运行另一个函数 然后再次启动该序列 这是原样 var promise database getUserCookies user then function data
  • F#、FParsec 和更新用户状态

    好吧 自从我的最后一个问题没有引起任何反应 我正在朝不同的方向前进 哈哈 我找不到任何超出的例子官方文档管理用户状态或访问先前解析器的结果 注意 这段代码的作用是not编译 namespace MultipartMIMEParser ope