F #과 FParsec을 사용하여 다중 부분 MIME 파서를 개발 중입니다. 저는 반복적으로 개발하고 있습니다. 그래서 이것은 매우 정제되지 않은 부서지기 쉬운 코드입니다 - 그것은 단지 나의 첫 번째 즉각적인 문제를 해결할뿐입니다. 빨강, 녹색, 리펙터.F #, FParsec 및 스트림 파서를 반복적으로 호출
문자열 대신 문자열을 구문 분석해야하는데 실제로 루프를 보내고 있습니다. 그 제약 조건을 감안할 때 최선을 다해 파서를 재귀 적으로 호출해야합니다. 그 일을하는 방법은 최소한 내가 지금까지 진행 한 방식대로, 나의 켄을 초월한 것이다.
namespace MultipartMIMEParser
open FParsec
open System.IO
type private Post = { contentType : string
; boundary : string
; subtype : string
; content : string }
type MParser (s:Stream) =
let ($) f x = f x
let ascii = System.Text.Encoding.ASCII
let str cs = System.String.Concat (cs:char list)
let q = "\""
let qP = pstring q
let pSemicolon = pstring ";"
let manyNoDoubleQuote = many $ noneOf q
let enquoted = between qP qP manyNoDoubleQuote |>> str
let skip = skipStringCI
let pContentType = skip "content-type: "
>>. manyTill anyChar (attempt $ preturn() .>> pSemicolon)
|>> str
let pBoundary = skip " boundary=" >>. enquoted
let pSubtype = opt $ pSemicolon >>. skip " type=" >>. enquoted
let pContent = many anyChar |>> str // TODO: The content parser needs to recurse on the stream.
let pStream = pipe4 pContentType pBoundary pSubtype pContent
$ fun c b t s -> { contentType=c; boundary=b; subtype=t; content=s }
let result s = match runParserOnStream pStream() "" s ascii with
| Success (r,_,_) -> r
| Failure (e,_,_) -> failwith (sprintf "%A" e)
let r = result s
member p.ContentType = r.contentType
member p.Boundary = r.boundary
member p.ContentSubtype = r.subtype
member p.Content = r.content
예시적인 POST의 첫 번째 라인은 다음과
content-type: Multipart/related; boundary="RN-Http-Body-Boundary"; type="multipart/related"
그것은 파일 내의 단일 행에 걸쳐있다. 내용의 하위 부분은 여러 줄에 걸쳐있는 content-type
값을 포함하므로 재사용 할 경우 파서를 수정해야합니다.
어떻게 든 pContent
(문자열?) 결과는 pBoundary
입니다. 나머지 스트림 부분을 적절한 경계에서 분리하여 포스트의 각 내용에 대해 여러 부분을 반환 할 수 있습니다. 그 중 헤더와 내용 (분명히 문자열이 아닌 다른 것이어야 함)이있는 별도의 게시물이됩니다. 내 머리가 돌고있다. 이 코드는 이미 너무 복잡해서 한 줄을 파싱하지 못했습니다.
통찰력과 지혜에 대한 감사!
나는 차별화 된 노동 조합을 만들었지 만 잘 설계되었는지는 잘 모르겠다. 나는이 피드백과 피드백을 바탕으로 [새로운 질문] (http://stackoverflow.com/questions/26891564/f-fparsec-and-calling-a-stream-parser-recursively-second-take)을 요청했다. [내 두 번째 질문] (http://stackoverflow.com/questions/26875192/f-fparsec-and-updating-userstate). 고맙습니다! –