Hier ist mein Problem: Ich versuche, einen Parser zu schreiben, der die Kraft aktiver Muster in F # nutzt. Die grundlegende Signatur einer Parsing-Funktion ist die folgendeF #: Erweiterte Verwendung von aktiven Mustern
LazyList<Token> -> 'a * LazyList<Token>
Bedeutung eine faul Liste von Token nimmt, und gibt das Ergebnis des Parsing und die neue Liste von Tokens nach dem Parsen, so wie funktionales Design zu folgen.
nun als nächsten Schritt kann ich aktive Muster definieren, die mir einige Konstrukte direkt in Übereinstimmung Ausdrücke passen helfen, thusly
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
und dann passen Ergebnisse analysieren in einem hohen Maß Art und Weise auf diese Weise
Das Problem, das ich mit diesem Code habe, ist, dass jedes neue übereinstimmende Konstrukt geschachtelt ist, was nicht lesbar ist, vor allem, wenn Sie eine lange Kette von Ergebnissen haben. Ich möchte die Möglichkeit haben, einen Anpassungsoperator wie der Operator :: für die Liste zu definieren, die es mir ermöglichen würde folgendes zu tun:
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
Aber ich glaube nicht, so etwas ist möglich F #. Ich würde sogar ein Design akzeptieren, bei dem ich ein spezifisches aktives "ChainN" -Muster aufrufen muss, wobei N die Nummer des Elementes ist, das ich analysieren möchte, aber ich weiß nicht, wie ich eine solche Funktion entwerfen soll, wenn es möglich ist.
Irgendwelche Ratschläge oder Anweisungen diesbezüglich? Gibt es ein offensichtliches Design, das ich nicht gesehen habe?