rap*_*ard 7 f# pattern-matching
这是我的问题:我正在尝试编写一个利用F#中活动模式的强大功能的解析器.解析函数的基本签名如下
LazyList<Token> -> 'a * LazyList<Token>
Run Code Online (Sandbox Code Playgroud)
这意味着它需要一个惰性的标记列表,并在解析后返回解析的结果和新的标记列表,以便遵循功能设计.
现在,作为下一步,我可以定义活动模式,这将帮助我直接在匹配表达式中匹配一些构造
let inline (|QualName|_|) token_stream =
match parse_qualified_name token_stream with
| Some id_list, new_stream -> Some (id_list, new_stream)
| None, new_stream -> None
let inline (|Tok|_|) token_stream =
match token_stream with
| Cons (token, tail) -> Some(token.variant, tail)
| _ -> None
Run Code Online (Sandbox Code Playgroud)
然后以这种方式以高级方式匹配解析结果
let parse_subprogram_profile = function
| Tok (Kw (KwProcedure | KwFunction),
QualName(qual_name,
Tok (Punc (OpeningPar), stream_tail))) as token_stream ->
// some code
| token_stream -> None, token_stream
Run Code Online (Sandbox Code Playgroud)
我对此代码的问题是每个新匹配的构造都是嵌套的,这是不可读的,特别是如果你有一长串的结果要匹配.我希望能够定义一个匹配的运算符,例如:: operator for list,这将使我能够执行以下操作:
let parse_subprogram_profile = function
| Tok (Kw (KwProcedure | KwFunction)) ::
QualName(qual_name) ::
Tok (Punc (OpeningPar)) :: stream_tail as token_stream ->
// some code
| token_stream -> None, token_stream
Run Code Online (Sandbox Code Playgroud)
但我不认为在F#中这样的事情是可能的.我甚至接受一种设计,其中我必须调用特定的"ChainN"活动模式,其中N是我想要解析的元素的数量,但是如果可能的话我不知道如何设计这样的函数.
有关于此的任何建议或指示?有没有明显的设计我没看到?
我也有类似的想法,但实际上放弃了这种精确的设计。您可以做的就是使用实际的列表。
\n\n在这种情况下,您将拥有一个 CombinedList,它由(首先)充当缓冲区的普通列表和(其次)惰性列表组成。
\n\n当你想匹配某个模式时,你可以这样做:
\n\nmatch tokens.EnsureBuffer(4) with\n| el1 :: el2 :: remaining -> (el1.v+el2.v, tokens.SetBuffer(remaining))\n| el3 :: el4 :: el5 :: el6 :: remaining -> (el1.v-el2.v+el3.v-el4.v, tokens.SetBuffer(remaining))\n
Run Code Online (Sandbox Code Playgroud)\n\n其中 EnsureBuffer 和 SetBuffer 可以改变“令牌”并返回它,或者如果不需要更改则返回它,否则返回新实例。
\n\n这能解决您的问题吗?\nFran\xc3\xa7ois
\n