2016-11-03 7 views
3

オプションの末尾のカンマを処理するにはどうすればよいですか?

let maxCount = System.Int32.MaxValue 
let pmlcomment = pstring "/*" >>. skipCharsTillString "*/" true (maxCount) 
let ws = pspaces >>. many (pspaces >>. pmlcomment .>> pspaces) |>> (function | [] ->() | _ ->()) 
let str_ws s = pstring s .>> ws 
let exprBraceSeqOpt p = 
    let trailingComma = (str_ws "," |>> fun _ -> None) 
    between (str_ws "{") (str_ws "}") ((opt (attempt (sepBy p (str_ws ",")))) <|> (attempt trailingComma)) 
let sampleP = exprBraceSeqOpt (str_ws "x") 

与えられ、それが正しく、最後の1を除いて、次のすべてに一致します。

["{}";"{x}";"{x,x}";"{x,x,}"] 

私は何かが状態か何かを変えている推測しています。

fparsecでオプションの後続カンマを処理するにはどうすればよいですか?

+0

おそらく 'opt(試みtrailingComma)'でしょうか? – Yawar

+0

いいえ、それはコンパイルされません – Maslow

答えて

4

sepBy「余分な区切り文字がある場合はそれを食べます」。それはちょうどそれがどのように動作するか、期間です。 attemptをさまざまな場所に適用してハックすることはできません。attemptをセパレータに適用すると、最後のセパレータが実際に成功しているので、役に立たないので、attemptは効果がありません。そして、sepBy全体にattemptを適用すると、最後のセパレータだけでなく、sepBy全体がロールバックされるので、役に立たないでしょう。また、「x」パーサー自体にattemptを適用すると、目的の末尾のコンマの動作を達成すると、パーサーが複数のカンマを連続して受け入れることに悪影響を及ぼします。

コンビネータを巧みに使って目的の結果を達成することは不可能であるため、実際にはあなたの後ろのものを実行する特別な機能があります。sepEndBy必要に応じて、これが働くだろう

また
let exprBraceSeqOpt p = 
    between (str_ws "{") (str_ws "}") (sepEndBy p (str_ws ",")) 

、余談として、私はfunction | [] ->() | _ ->()ignoreを行うには非常に精巧な方法であることを指摘すべきです。 :-)

+1

非常に良い情報。無視して...私は一般的な消費のためにこれを整えていないが、そこには実際のコード= – Maslow

関連する問題