나는 각 토큰은 텍스트 또는 태그의 블록 중 하나입니다 FParsec와 토큰의 목록을 구문 분석하려고와 토큰의 목록을 구문 분석 - 예를 들어 :어떻게 FParsec
파서이다} 성공 또는 실패이 인 {
type Parser<'t> = Parser<'t, unit> type Token = | Text of string | Tag of string let escape fromString toString : Parser<_> = pstring fromString |>> (fun c -> toString) let content : Parser<_> = let contentNormal = many1Satisfy (fun c -> c <> '{' && c <> '}') let openBraceEscaped = escape "{{" "{" let closeBraceEscaped = escape "}}" "}" let contentEscaped = openBraceEscaped <|> closeBraceEscaped stringsSepBy contentNormal contentEscaped let ident : Parser<_> = let isIdentifierFirstChar c = isLetter c || c = '_' let isIdentifierChar c = isLetter c || isDigit c || c = '_' spaces >>. many1Satisfy2L isIdentifierFirstChar isIdentifierChar "identifier" .>> spaces let text = content |>> Text let tag = ident |> between (skipString "{") (skipString "}") |>> Tag let token = text <|> tag let tokens = many token .>>. eof
는 다음의 시험 작동 :
테스트} 테스트의 종류, 그리고 {여기
> run token "abc def" ;;
val it : ParserResult<Token,unit> = Success: Text "abc def"
> run token "{abc def}" ;;
val it : ParserResult<Token,unit> = Success: Tag "abc def"
하지만 예외 토큰 결과를 실행하려고 :
> run tokens "{abc} def" ;;
System.InvalidOperationException: (Ln: 1, Col: 10): The combinator 'many' was
applied to a parser that succeeds without consuming input and without
changing the parser state in any other way. (If no exception had been raised,
the combinator likely would have entered an infinite loop.)
내가 this stackoverflow question 이상 갔어요 아무것도하지만, 내가 일을 시도하지했습니다. 난 다음을 추가,하지만 난 같은 예외를 얻을 :
let tokenFwd, tokenRef = createParserForwardedToRef<Token, unit>()
do tokenRef := choice [tag; text]
let readEndOfInput : Parser<unit, unit> = spaces >>. eof
let readExprs = many tokenFwd
let readExprsTillEnd = readExprs .>> readEndOfInput
run readExprsTillEnd "{abc} def" // System.InvalidOperationException ... The combinator 'many' was applied ...
나는 문제가 내용의 stringsSepBy이다 생각하지만, 나는 탈출 항목 문자열을 얻을 수있는 다른 방법을 알아낼 수 없습니다를
어떤 도움이라도 대단히 감사 할 것입니다 - 저는 지금 이틀 동안이 일을 겪어 왔으며 그것을 이해할 수 없습니다.
고마워요! 그냥 String으로 파이핑하면됩니다.concat 완벽하게 작동합니다 ('many1 (contentNormal <|> contentEscaped) | >> String.Concat'),하지만 올바르게 작동하도록 notEmpty를 얻을 수 있는지 알고 싶습니다. – jjmac