Skip to content

Commit

Permalink
feat: 优化 Literal 字符串拼接逻辑。
Browse files Browse the repository at this point in the history
  • Loading branch information
CYJB committed Mar 24, 2024
1 parent 5b64f5a commit 4678ef7
Show file tree
Hide file tree
Showing 9 changed files with 492 additions and 136 deletions.
4 changes: 2 additions & 2 deletions Cyjb.Markdown/ParseInline/BracketInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal sealed class BracketInfo
/// <summary>
/// 括号对应的节点。
/// </summary>
public readonly Literal Node;
public readonly TempLiteral Node;
/// <summary>
/// 是否表示图片。
/// </summary>
Expand Down Expand Up @@ -39,7 +39,7 @@ internal sealed class BracketInfo
/// <param name="node">括号对应的节点。</param>
/// <param name="isImage">是否表示图片。</param>
/// <param name="startMark">源文件的起始标记。</param>
public BracketInfo(Literal node, bool isImage, SourceMark startMark)
public BracketInfo(TempLiteral node, bool isImage, SourceMark startMark)
{
Node = node;
IsImage = isImage;
Expand Down
4 changes: 2 additions & 2 deletions Cyjb.Markdown/ParseInline/DelimiterInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ internal sealed class DelimiterInfo
/// <summary>
/// 分隔符对应的节点。
/// </summary>
public readonly Literal Node;
public readonly TempLiteral Node;
/// <summary>
/// 分隔符的处理器。
/// </summary>
Expand All @@ -53,7 +53,7 @@ internal sealed class DelimiterInfo
/// <param name="canClose">是否可以用作结束分隔符。</param>
/// <param name="node">分隔符对应的节点。</param>
/// <param name="processor">分隔符的处理器。</param>
public DelimiterInfo(char delimiter, int length, bool canOpen, bool canClose, Literal node,
public DelimiterInfo(char delimiter, int length, bool canOpen, bool canClose, TempLiteral node,
DelimiterProcessor processor)
{
Delimiter = delimiter;
Expand Down
91 changes: 31 additions & 60 deletions Cyjb.Markdown/ParseInline/InlineLexer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ internal partial class InlineLexer : LexerController<int>
/// </summary>
private static readonly StrikethroughProcessor StrikethroughProcessor = new();

/// <summary>
/// 关联到的行级语法分析器。
/// </summary>
private InlineParser parser;
/// <summary>
/// 解析选项。
/// </summary>
Expand All @@ -47,9 +51,9 @@ internal partial class InlineLexer : LexerController<int>
/// </summary>
private char lastChar = '\n';
/// <summary>
/// 字面量缓冲区
/// 当前字面量
/// </summary>
private readonly PooledList<char> literalBuffer = new(0x1000);
private StringView literal;
/// <summary>
/// 当前字面量文本的起始位置。
/// </summary>
Expand Down Expand Up @@ -77,22 +81,6 @@ public override TextSpan Span
}
}

/// <summary>
/// 返回并清空当前字面量文本。
/// </summary>
/// <returns>当前字面量文本。</returns>
public string GetLiteralText()
{
if (literalBuffer.Length == 0)
{
return string.Empty;
}
Span<char> span = literalBuffer.AsSpan();
string result = span.Unescape();
literalBuffer.Clear();
return result;
}

/// <summary>
/// 文件结束的动作。
/// </summary>
Expand Down Expand Up @@ -338,34 +326,24 @@ private void HtmlCDataAction()
[LexerSymbol(@"<LinkClose>]{LinkLabel}")]
private void LinkLabelAction()
{
InlineParser parser = (InlineParser)SharedContext!;
// 标签不为空,使用标签本身。
ReadOnlySpan<char> text = Text.AsSpan(2);
ReadOnlySpan<char> label = ReadOnlySpan<char>.Empty;
if (!MarkdownUtil.TryParseLinkLabel(ref text, ref label))
int idx = Text.AsSpan(2).IndexOfUnescaped(']');
if (idx > 1000)
{
// [ 和 ] 之间最多允许 999 个字符。
Reject();
return;
}
StringView label = Text.Substring(2, idx);
if (label.Length == 0)
{
// 标签为空,将前面的文本作为标签使用。
// 如果标签为空,将前面的文本作为标签使用。
label = parser.GetCurrentLinkText(Start);
}
if (!label.IsEmpty && parser.TryGetLinkDefine(LinkUtil.NormalizeLabel(label), out LinkDefinition? define))
TextSpan span = Span;
if (!label.IsEmpty && parser.ParseLinkDefinition(label, span))
{
TextSpan span = Span;
AddLiteral(span.Start);
if (parser.ParseLinkDefinition(define, span))
{
// 调整字面量起始位置。
literalStart = span.End;
}
else
{
// 链接匹配失败,作为字面量字符添加。
AppendLiteralText(Text);
}
// 调整字面量起始位置。
literalStart = span.End;
}
else
{
Expand Down Expand Up @@ -426,9 +404,7 @@ private void LinkBodyAction()
{
Source.Index -= attrLen;
}
InlineParser parser = (InlineParser)SharedContext!;
TextSpan span = Span;
AddLiteral(span.Start);
if (parser.ParseLinkBody(body, span))
{
// 调整字面量起始位置。
Expand Down Expand Up @@ -498,7 +474,7 @@ private void MathSpanAction()
{
Source.Drop();
Source.Index = idx;
string content = Source.GetReadedText().ToString();
StringView content = Source.GetReadedText();
// 如果内容两边都有一个空格(或换行),那么可以移除前后各一的空格(或换行)。
// 不要移除多个空格,也不要修改只由空格组成的代码。
if (content.Length >= 2 && content.Any(ch => !MarkdownUtil.IsWhitespace(ch)))
Expand All @@ -525,7 +501,7 @@ private void MathSpanAction()
}
// 跳过结束标志。
Source.Index += dollarCount;
Add(new MathSpan(content, Span));
Add(new MathSpan(content.ToString(), Span));
}
else
{
Expand All @@ -542,9 +518,9 @@ private void MathSpanAction()
private void LinkStartAction()
{
bool isImage = Text.Length > 1;
Literal node = new(Text.ToString(), Span);
TempLiteral node = new(Text, Span);
Add(node);
(SharedContext as InlineParser)!.AddBracket(node, isImage);
parser.AddBracket(node, isImage);
// 允许识别链接闭合。
EnterContext(LinkCloseContext);
}
Expand All @@ -557,8 +533,7 @@ private void LinkStartAction()
private void LinkCloseAction()
{
TextSpan span = Span;
AddLiteral(span.Start);
if ((SharedContext as InlineParser)!.ParseCloseBracket(span))
if (parser.ParseCloseBracket(span))
{
// 链接匹配成功,调整字面量起始位置。
literalStart = span.End;
Expand Down Expand Up @@ -592,7 +567,7 @@ private void EmphasisAction()
if (info != null)
{
Add(info.Node);
(SharedContext as InlineParser)!.AddDelimiter(info);
parser.AddDelimiter(info);
return;
}
// 在 ScanDelimiters 可能会将后续的分隔符一起消费掉。
Expand All @@ -612,7 +587,7 @@ private void StrikethroughAction()
if (info != null)
{
Add(info.Node);
(SharedContext as InlineParser)!.AddDelimiter(info);
parser.AddDelimiter(info);
return;
}
}
Expand Down Expand Up @@ -678,7 +653,7 @@ private void CharAction()
if (canOpen || canClose)
{
return new DelimiterInfo(delimiter, length, canOpen, canClose,
new Literal(new string(delimiter, length), Span), processor);
new TempLiteral(Source.GetReadedText(), Span), processor);
}
else
{
Expand Down Expand Up @@ -738,20 +713,20 @@ private void AppendLiteralText(StringView text)
if (text.Length > 0)
{
lastChar = text[^1];
literalBuffer.Add(text);
literal.TryConcat(text, out literal);
}
}

/// <summary>
/// 添加字面量节点。
/// </summary>
/// <param name="end">字面量节点的结束位置。</param>
private void AddLiteral(int end)
public void AddLiteral(int end)
{
string text = GetLiteralText();
if (text.Length > 0)
if (literal.Length > 0)
{
children.Add(new Literal(text, new TextSpan(literalStart, end)));
children.Add(new TempLiteral(literal, new TextSpan(literalStart, end)));
literal = StringView.Empty;
}
literalStart = end;
}
Expand All @@ -765,7 +740,7 @@ public override object? SharedContext
set
{
base.SharedContext = value;
InlineParser parser = (InlineParser)value!;
parser = (value as InlineParser)!;
options = parser.Options;
parser.Controller = this;
}
Expand All @@ -779,7 +754,7 @@ protected override void SourceLoaded()
base.SourceLoaded();
lastChar = '\n';
literalStart = MapLocation(0);
children = (SharedContext as InlineParser)!.children;
children = parser.children;
}

/// <summary>
Expand All @@ -789,7 +764,7 @@ protected override void SourceLoaded()
/// <returns>映射后的位置。</returns>
private int MapLocation(int location)
{
return ((InlineParser)SharedContext!).MapLocation(location);
return parser.MapLocation(location);
}

/// <summary>
Expand All @@ -809,10 +784,6 @@ private void Add(InlineNode node)

protected override void Dispose(bool disposing)
{
if (disposing)
{
literalBuffer.Dispose();
}
base.Dispose(disposing);
}
}
Loading

0 comments on commit 4678ef7

Please sign in to comment.