コード例 #1
0
        private MarkdownParsingResult <INode> ParseFormatModificator(ITokenizer <IMdToken> tokenizer,
                                                                     Md modificatorAttribute)
        {
            var boundedTokenizer = tokenizer.UntilNotMatch(token => token.Has(Md.Close, modificatorAttribute));

            var open = boundedTokenizer.Match(token => token.Has(Md.Open, modificatorAttribute));

            var children = open.IfSuccess(
                childrenTokenizer => ParseNodesUntilMatch(childrenTokenizer,
                                                          t => ParseTextWithEscaped(t)
                                                          .IfFail(ParseFormatModificator)
                                                          .IfFail(ParseAnyTokenAsText))
                );

            var close = children.IfSuccess(t => t.UnboundTokenizer()
                                           .Match(token => token.Has(Md.Close, modificatorAttribute))
                                           );

            if (close.Succeed && close.Parsed.Text == open.Parsed.Text)
            {
                var node = CreateModificatorNode(modificatorAttribute, children.Parsed);
                return(close.Remainder.SuccessWith(node));
            }
            return(tokenizer.Fail <INode>());
        }
コード例 #2
0
        private MarkdownParsingResult <INode> ParseCodeIndented(ITokenizer <IMdToken> tokenizer)
        {
            var codeLines = ParseNodesUntilMatch(tokenizer, t =>
            {
                var start    = t.Match(token => token.Has(Md.Indent));
                var codeLine = start.IfSuccess(inner =>
                {
                    var bounded = inner.UntilNotMatch(token => token.Has(Md.NewLine));
                    return(ParseNodesUntilMatch(bounded, ParseAnyTokenAsEscaped));
                });
                if (codeLine.Succeed)
                {
                    var codeNodes = codeLine.Parsed;
                    var newLine   = codeLine.Remainder.UnboundTokenizer().Match(token => token.Has(Md.NewLine));
                    if (newLine.Succeed)
                    {
                        codeNodes.Add(new EscapedTextNode(newLine.Parsed.Text));
                    }
                    return(newLine.Remainder.SuccessWith(codeNodes));
                }
                return(t.Fail <List <INode> >());
            });

            if (!codeLines.Parsed.Any())
            {
                return(tokenizer.Fail <INode>());
            }
            var unpackedText = codeLines.Parsed.SelectMany(node => node);

            return(codeLines.Remainder.SuccessWith <INode>(new CodeModificatorNode(unpackedText)));
        }
コード例 #3
0
 private MarkdownParsingResult <INode> ParseAnyTokenAsText(ITokenizer <IMdToken> tokenizer)
 {
     if (tokenizer.AtEnd)
     {
         return(tokenizer.Fail <INode>());
     }
     return(tokenizer.Advance().SuccessWith <INode>(new TextNode(tokenizer.CurrentToken.Text)));
 }
コード例 #4
0
 public static MarkdownParsingResult <IMdToken> Match(this ITokenizer <IMdToken> tokenizer,
                                                      Predicate <IMdToken> predicate)
 {
     if (tokenizer.AtEnd || !predicate(tokenizer.CurrentToken))
     {
         return(tokenizer.Fail <IMdToken>());
     }
     return(tokenizer.Advance().SuccessWith(tokenizer.CurrentToken));
 }
コード例 #5
0
        public MarkdownParsingResult <INode> ParseParagraph(ITokenizer <IMdToken> tokenizer)
        {
            var children = ParseNodesUntilMatch(tokenizer, ParseFormattedText);

            if (children.Parsed.Any())
            {
                return(children.Remainder.SuccessWith <INode>(new ParagraphNode(children.Parsed)));
            }
            return(tokenizer.Fail <INode>());
        }
コード例 #6
0
        private MarkdownParsingResult <INode> ParseEscaped(ITokenizer <IMdToken> tokenizer)
        {
            var tokens = tokenizer.Match(token => token.Has(Md.Escaped));

            if (tokens.Succeed)
            {
                return(tokens.Remainder.SuccessWith <INode>(new EscapedTextNode(tokens.Parsed.Text)));
            }
            return(tokenizer.Fail <INode>());
        }
コード例 #7
0
        private MarkdownParsingResult <INode> ParseAnyTokenAsEscaped(ITokenizer <IMdToken> tokenizer)
        {
            if (tokenizer.AtEnd)
            {
                return(tokenizer.Fail <INode>());
            }
            var underlyingText = tokenizer.CurrentToken.UnderlyingText;

            return(tokenizer.Advance().SuccessWith <INode>(new EscapedTextNode(underlyingText)));
        }
コード例 #8
0
        private MarkdownParsingResult <INode> ParsePlainText(ITokenizer <IMdToken> tokenizer)
        {
            var tokens = tokenizer.UntilMatch(token => token.Has(Md.PlainText));
            var text   = string.Join("", tokens.Parsed.Select(t => t.Text));

            if (tokens.Parsed.Any())
            {
                return(tokens.Remainder.SuccessWith <INode>(new TextNode(text)));
            }
            return(tokenizer.Fail <INode>());
        }
コード例 #9
0
        private MarkdownParsingResult <INode> ParseTextWithEscaped(ITokenizer <IMdToken> tokenizer)
        {
            var parsingResult = ParseNodesUntilMatch(tokenizer, t => ParsePlainText(t).IfFail(ParseEscaped));
            var nodes         = parsingResult.Parsed;

            if (!nodes.Any())
            {
                return(tokenizer.Fail <INode>());
            }

            // No need to create extra nodes if we can
            INode result = nodes.Count == 1 ? nodes[0] : new GroupNode(nodes);

            return(parsingResult.Remainder.SuccessWith(result));
        }
コード例 #10
0
        private MarkdownParsingResult <INode> ParseCodeInBackticks(ITokenizer <IMdToken> tokenizer)
        {
            var boundedTokenizer = tokenizer.UntilNotMatch(token => token.Has(Md.Close, Md.Code));

            var open     = boundedTokenizer.Match(token => token.Has(Md.Open, Md.Code));
            var children =
                open.IfSuccess(childrenTokenizer => ParseNodesUntilMatch(childrenTokenizer, ParseAnyTokenAsEscaped));

            var close = children.IfSuccess(t => t.UnboundTokenizer()
                                           .Match(token => token.Has(Md.Close, Md.Code)));

            if (close.Succeed)
            {
                return(close.Remainder.SuccessWith <INode>(new CodeModificatorNode(children.Parsed)));
            }
            return(tokenizer.Fail <INode>());
        }
コード例 #11
0
        private MarkdownParsingResult <INode> ParseHeader(ITokenizer <IMdToken> tokenizer)
        {
            var header           = tokenizer.Match(token => token.Has(Md.Header));
            var boundedTokenizer = header.IfSuccess(t =>
            {
                var bounded = t.UntilNotMatch(token => token.HasAny(Md.NewLine, Md.Break));
                return(SkipWhiteSpaces(bounded));
            });
            var headerContent = boundedTokenizer.IfSuccess(t => ParseNodesUntilMatch(t, ParseFormattedText));

            if (headerContent.Succeed)
            {
                return(headerContent.Remainder.UnboundTokenizer().SuccessWith <INode>(
                           new HeaderNode(header.Parsed.Text.Length, headerContent.Parsed)
                           ));
            }
            return(tokenizer.Fail <INode>());
        }
コード例 #12
0
        private MarkdownParsingResult <INode> ParseLink(ITokenizer <IMdToken> tokenizer)
        {
            var openText  = tokenizer.Match(token => token.Has(Md.LinkText, Md.Open));
            var text      = openText.IfSuccess(ParseTextWithEscaped);
            var closeText = text.IfSuccess(t => t.Match(token => token.Has(Md.LinkText, Md.Close)));

            var openLink = closeText
                           .IfSuccess(SkipWhiteSpaces)
                           .IfSuccess(t => t.Match(token => token.Has(Md.LinkReference, Md.Open)));
            var link      = openLink.IfSuccess(ParsePlainText);
            var closeLink = link.IfSuccess(t => t.Match(token => token.Has(Md.LinkReference, Md.Close)));

            if (closeLink.Succeed)
            {
                var linkText = ((TextNode)link.Parsed).Text;
                return(closeLink.Remainder.SuccessWith <INode>(new LinkNode(linkText, text.Parsed)));
            }
            return(tokenizer.Fail <INode>());
        }