F#:高级使用活动模式
这是我的问题:我试图编写一个解析器,利用F#中活动模式的强大功能。 解析函数的基本签名如下
LazyList<Token> -> 'a * LazyList<Token>
这意味着需要一个懒惰的令牌列表,并在解析后返回解析结果和新的令牌列表,以便遵循功能设计。
现在,作为下一步,我可以定义活动模式,这样可以帮助我直接在匹配表达式中匹配一些结构
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
然后通过这种方式匹配高级别的解析结果
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
我在这段代码中遇到的问题是每个新匹配的构造都是嵌套的,这是不可读的,特别是如果你有很长的匹配结果链。 我希望能够定义一个匹配的运算符,如::运算符列表,这将使我能够执行以下操作:
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
但我不认为F#中有这样的事情是可能的。 我甚至会接受一个设计,在这个设计中我必须调用一个特定的“ChainN”活动模式,其中N是我想要分析的元素的数量,但是如果可能的话我不知道如何设计这样的函数。
有关这方面的任何建议或指示? 有没有明显的设计我没有看到?
我也有这样的想法,但实际上放弃了这个确切的设计。 你可以做的事情是使用实际列表。
在这种情况下,您将拥有一个CombinedList,它由(首先)作为缓冲区的普通列表和(其次)一个懒惰列表组成。
当你想匹配一个模式时,你可以这样做:
match tokens.EnsureBuffer(4) with
| el1 :: el2 :: remaining -> (el1.v+el2.v, tokens.SetBuffer(remaining))
| el3 :: el4 :: el5 :: el6 :: remaining -> (el1.v-el2.v+el3.v-el4.v, tokens.SetBuffer(remaining))
其中EnsureBuffer和SetBuffer可能会突变“标记”并将其返回或返回,如果不需要更改或者返回新的实例。
这能解决你的问题吗? 弗朗索瓦
链接地址: http://www.djcxy.com/p/20453.html