From bd56788542d4b346268f39c22e48e3c7ac5776db Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Wed, 27 Nov 2024 04:25:56 +0100 Subject: [PATCH] [parsing/mfm] Optimize restOfLineContains case for single char, remove unnecessary pushLine/assertLine calls --- Iceshrimp.Parsing/Mfm.fs | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/Iceshrimp.Parsing/Mfm.fs b/Iceshrimp.Parsing/Mfm.fs index b75af4a1..471cf51d 100644 --- a/Iceshrimp.Parsing/Mfm.fs +++ b/Iceshrimp.Parsing/Mfm.fs @@ -261,6 +261,20 @@ module private MfmParser = | c when c.Contains(s) -> Reply(()) | _ -> Reply(Error, error) + let restOfLineContainsChar (c: char) : Parser = + let error = messageError "No match found" + let func ch = ch <> c && isNotNewline ch + + fun (stream: CharStream<_>) -> + let pos = stream.Position + let _ = stream.SkipCharsOrNewlinesWhile(func) + let ch = stream.Read() + do stream.Seek pos.Index + + match ch with + | m when m = c -> Reply(()) + | _ -> Reply(Error, error) + let restOfSegmentContains (s: string, segment: char -> bool) : Parser = let error = messageError "No match found" @@ -329,19 +343,19 @@ module private MfmParser = let italicAsteriskNode = previousCharSatisfiesNot isNotWhitespace >>. italicPatternAsterisk - >>. restOfLineContains "*" - >>. pushLine + >>. restOfLineContainsChar '*' // TODO: this doesn't cover the case where a bold node ends before the italic one + >>. pushLine // Remove when above TODO is resolved >>. manyInlineNodesTill italicPatternAsterisk - .>> assertLine + .>> assertLine // Remove when above TODO is resolved |>> fun c -> MfmItalicNode(aggregateTextInline c, Symbol) :> MfmNode let italicUnderscoreNode = previousCharSatisfiesNot isNotWhitespace >>. italicPatternUnderscore - >>. restOfLineContains "_" - >>. pushLine + >>. restOfLineContainsChar '_' // TODO: this doesn't cover the case where a bold node ends before the italic one + >>. pushLine // Remove when above TODO is resolved >>. manyInlineNodesTill italicPatternUnderscore - .>> assertLine + .>> assertLine // Remove when above TODO is resolved |>> fun c -> MfmItalicNode(aggregateTextInline c, Symbol) :> MfmNode let italicTagNode = @@ -354,18 +368,14 @@ module private MfmParser = previousCharSatisfiesNot isNotWhitespace >>. skipString "**" >>. restOfLineContains "**" - >>. pushLine >>. manyInlineNodesTill (skipString "**") - .>> assertLine |>> fun c -> MfmBoldNode(aggregateTextInline c, Symbol) :> MfmNode let boldUnderscoreNode = previousCharSatisfiesNot isNotWhitespace >>. skipString "__" >>. restOfLineContains "__" - >>. pushLine >>. manyInlineNodesTill (skipString "__") - .>> assertLine |>> fun c -> MfmBoldNode(aggregateTextInline c, Symbol) :> MfmNode let boldTagNode = @@ -377,9 +387,7 @@ module private MfmParser = let strikeNode = skipString "~~" >>. restOfLineContains "~~" - >>. pushLine >>. manyInlineNodesTill (skipString "~~") - .>> assertLine |>> fun c -> MfmStrikeNode(aggregateTextInline c, Symbol) :> MfmNode let strikeTagNode = @@ -390,10 +398,10 @@ module private MfmParser = let codeNode = codePattern - >>. restOfLineContains "`" - >>. pushLine + >>. restOfLineContainsChar '`' // TODO: this doesn't cover the case where a code block node ends before the inline one + >>. pushLine // Remove when above TODO is resolved >>. manyCharsTill anyChar codePattern - .>> assertLine + .>> assertLine // Remove when above TODO is resolved |>> fun v -> MfmInlineCodeNode(v) :> MfmNode let codeBlockNode = @@ -413,9 +421,7 @@ module private MfmParser = let mathNode = skipString "\(" >>. restOfLineContains "\)" - >>. pushLine >>. manyCharsTill anyChar (skipString "\)") - .>> assertLine |>> fun f -> MfmMathInlineNode(f) :> MfmNode let mathBlockNode =