2016-02-18 00:34:26 +09:00
|
|
|
|
using System;
|
2016-02-18 22:32:45 +09:00
|
|
|
|
using System.Collections.ObjectModel;
|
|
|
|
|
|
using System.Text;
|
2016-02-19 05:53:48 +09:00
|
|
|
|
using Textamina.Markdig.Helpers;
|
2016-02-17 01:00:26 +09:00
|
|
|
|
using Textamina.Markdig.Parsing;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Textamina.Markdig.Syntax
|
|
|
|
|
|
{
|
2016-02-18 22:32:45 +09:00
|
|
|
|
public class StringLineGroup : Collection<StringLine>
|
2016-02-17 01:00:26 +09:00
|
|
|
|
{
|
2016-02-17 20:34:26 +09:00
|
|
|
|
private StringLine currentLine;
|
|
|
|
|
|
|
2016-02-18 22:32:45 +09:00
|
|
|
|
public StringLineGroup()
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public StringLineGroup(string text)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (text == null) throw new ArgumentNullException(nameof(text));
|
|
|
|
|
|
Add(new StringLine(text));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-17 20:34:26 +09:00
|
|
|
|
public int LinePosition { get; private set; }
|
|
|
|
|
|
|
|
|
|
|
|
public int ColumnPosition { get; private set; }
|
|
|
|
|
|
|
2016-02-19 07:22:54 +09:00
|
|
|
|
public StringLine Current => currentLine;
|
|
|
|
|
|
|
|
|
|
|
|
public char CurrentChar { get; private set; }
|
2016-02-17 20:34:26 +09:00
|
|
|
|
|
2016-02-18 00:34:26 +09:00
|
|
|
|
public char PreviousChar1 { get; private set; }
|
|
|
|
|
|
|
|
|
|
|
|
public char PreviousChar2 { get; private set; }
|
|
|
|
|
|
|
2016-02-18 22:32:45 +09:00
|
|
|
|
public void Reset()
|
2016-02-17 20:34:26 +09:00
|
|
|
|
{
|
|
|
|
|
|
ColumnPosition = -1;
|
2016-02-20 01:18:40 +09:00
|
|
|
|
LinePosition = 0;
|
2016-02-17 20:34:26 +09:00
|
|
|
|
currentLine = Count > 0 ? this[0] : null;
|
2016-02-18 22:32:45 +09:00
|
|
|
|
if (currentLine != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
ColumnPosition = currentLine.Start - 1;
|
|
|
|
|
|
}
|
2016-02-17 20:34:26 +09:00
|
|
|
|
NextChar();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-22 20:40:34 +09:00
|
|
|
|
public void SetColumn(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Current != null && index <= Current.End)
|
|
|
|
|
|
{
|
|
|
|
|
|
CurrentChar = Current[index];
|
|
|
|
|
|
ColumnPosition = index;
|
|
|
|
|
|
// Don't set previous char
|
|
|
|
|
|
PreviousChar1 = '\0';
|
|
|
|
|
|
PreviousChar2 = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-21 22:58:14 +09:00
|
|
|
|
public char PeekCharOnSameLine()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Current != null && (ColumnPosition+1) <= Current.End)
|
|
|
|
|
|
{
|
|
|
|
|
|
return Current[ColumnPosition + 1];
|
|
|
|
|
|
}
|
|
|
|
|
|
return (char)0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-18 22:32:45 +09:00
|
|
|
|
protected override void ClearItems()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.ClearItems();
|
|
|
|
|
|
Reset();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void InsertItem(int index, StringLine item)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.InsertItem(index, item);
|
|
|
|
|
|
if (index == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Reset();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void SetItem(int index, StringLine item)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.SetItem(index, item);
|
|
|
|
|
|
if (index == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Reset();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void RemoveItem(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.RemoveItem(index);
|
|
|
|
|
|
if (index == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Reset();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-19 07:22:54 +09:00
|
|
|
|
public bool IsEndOfLines => CurrentChar == '\0';
|
2016-02-17 20:34:26 +09:00
|
|
|
|
|
|
|
|
|
|
public State Save()
|
|
|
|
|
|
{
|
2016-02-19 07:22:54 +09:00
|
|
|
|
return new State(currentLine, LinePosition, ColumnPosition, CurrentChar, PreviousChar1, PreviousChar2);
|
2016-02-17 20:34:26 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-24 01:01:40 +09:00
|
|
|
|
public void Save(ref State state)
|
|
|
|
|
|
{
|
|
|
|
|
|
state.CurrentLine = currentLine;
|
|
|
|
|
|
state.LinePosition = LinePosition;
|
|
|
|
|
|
state.ColumnPosition = ColumnPosition;
|
|
|
|
|
|
state.Current = CurrentChar;
|
|
|
|
|
|
state.PreviousChar1 = PreviousChar1;
|
|
|
|
|
|
state.PreviousChar2 = PreviousChar2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-17 20:34:26 +09:00
|
|
|
|
public void Restore(ref State state)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentLine = state.CurrentLine;
|
|
|
|
|
|
LinePosition = state.LinePosition;
|
|
|
|
|
|
ColumnPosition = state.ColumnPosition;
|
2016-02-19 07:22:54 +09:00
|
|
|
|
CurrentChar = state.Current;
|
2016-02-18 00:34:26 +09:00
|
|
|
|
PreviousChar1 = state.PreviousChar1;
|
|
|
|
|
|
PreviousChar2 = state.PreviousChar2;
|
2016-02-17 20:34:26 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public char NextChar()
|
|
|
|
|
|
{
|
2016-02-18 00:34:26 +09:00
|
|
|
|
PreviousChar2 = PreviousChar1;
|
2016-02-19 07:22:54 +09:00
|
|
|
|
PreviousChar1 = CurrentChar;
|
2016-02-17 20:34:26 +09:00
|
|
|
|
if (currentLine != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
ColumnPosition++;
|
|
|
|
|
|
if (ColumnPosition <= currentLine.End)
|
|
|
|
|
|
{
|
2016-02-19 07:22:54 +09:00
|
|
|
|
CurrentChar = currentLine[ColumnPosition];
|
2016-02-17 20:34:26 +09:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
LinePosition++;
|
2016-02-20 01:18:40 +09:00
|
|
|
|
if (LinePosition < Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentLine = this[LinePosition];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
currentLine = null;
|
|
|
|
|
|
LinePosition = Count;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-18 22:32:45 +09:00
|
|
|
|
ColumnPosition = -1;
|
|
|
|
|
|
if (currentLine != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
ColumnPosition = currentLine.Start - 1;
|
|
|
|
|
|
}
|
2016-02-19 07:22:54 +09:00
|
|
|
|
CurrentChar = currentLine != null ? '\n' : '\0';
|
2016-02-17 20:34:26 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2016-02-19 07:22:54 +09:00
|
|
|
|
CurrentChar = '\0';
|
2016-02-17 20:34:26 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-19 07:22:54 +09:00
|
|
|
|
return CurrentChar;
|
2016-02-17 20:34:26 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-18 22:32:45 +09:00
|
|
|
|
public bool SkipWhiteSpaces()
|
|
|
|
|
|
{
|
|
|
|
|
|
bool hasWhitespaces = false;
|
2016-02-21 21:38:57 +09:00
|
|
|
|
while (CurrentChar.IsWhitespace())
|
2016-02-18 22:32:45 +09:00
|
|
|
|
{
|
|
|
|
|
|
NextChar();
|
|
|
|
|
|
hasWhitespaces = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return hasWhitespaces;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-21 21:38:57 +09:00
|
|
|
|
public bool SkipWhiteSpaces(out int newLineCount)
|
|
|
|
|
|
{
|
|
|
|
|
|
bool hasWhitespaces = false;
|
|
|
|
|
|
newLineCount = 0;
|
|
|
|
|
|
while (CurrentChar.IsWhitespace())
|
|
|
|
|
|
{
|
|
|
|
|
|
if (CurrentChar == '\n')
|
|
|
|
|
|
{
|
|
|
|
|
|
newLineCount++;
|
|
|
|
|
|
}
|
|
|
|
|
|
NextChar();
|
|
|
|
|
|
hasWhitespaces = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return hasWhitespaces;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-17 01:00:26 +09:00
|
|
|
|
public void TrimStart()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Strip leading and
|
2016-02-18 22:32:45 +09:00
|
|
|
|
this[0].TrimStart();
|
|
|
|
|
|
Reset();
|
2016-02-17 01:00:26 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void TrimEnd()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-18 22:32:45 +09:00
|
|
|
|
this[Count - 1].TrimEnd();
|
|
|
|
|
|
Reset();
|
2016-02-17 01:00:26 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Trim()
|
|
|
|
|
|
{
|
|
|
|
|
|
TrimStart();
|
|
|
|
|
|
TrimEnd();
|
|
|
|
|
|
}
|
2016-02-17 20:34:26 +09:00
|
|
|
|
|
2016-02-18 22:32:45 +09:00
|
|
|
|
public override string ToString()
|
|
|
|
|
|
{
|
|
|
|
|
|
var stringBuilder = new StringBuilder();
|
|
|
|
|
|
bool firstLine = true;
|
|
|
|
|
|
foreach (var line in this)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!firstLine)
|
|
|
|
|
|
{
|
|
|
|
|
|
stringBuilder.Append('\n');
|
|
|
|
|
|
}
|
|
|
|
|
|
stringBuilder.Append(line);
|
|
|
|
|
|
firstLine = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
return stringBuilder.ToString();
|
|
|
|
|
|
}
|
2016-02-17 20:34:26 +09:00
|
|
|
|
|
2016-02-24 01:01:40 +09:00
|
|
|
|
public struct State
|
2016-02-17 20:34:26 +09:00
|
|
|
|
{
|
2016-02-18 00:34:26 +09:00
|
|
|
|
public State(StringLine currentLine, int linePosition, int columnPosition, char current, char previousChar1, char previousChar2)
|
2016-02-17 20:34:26 +09:00
|
|
|
|
{
|
|
|
|
|
|
CurrentLine = currentLine;
|
|
|
|
|
|
LinePosition = linePosition;
|
|
|
|
|
|
ColumnPosition = columnPosition;
|
|
|
|
|
|
Current = current;
|
2016-02-18 00:34:26 +09:00
|
|
|
|
PreviousChar1 = previousChar1;
|
|
|
|
|
|
PreviousChar2 = previousChar2;
|
2016-02-17 20:34:26 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-24 01:01:40 +09:00
|
|
|
|
public StringLine CurrentLine;
|
2016-02-17 20:34:26 +09:00
|
|
|
|
|
2016-02-24 01:01:40 +09:00
|
|
|
|
public int LinePosition;
|
2016-02-17 20:34:26 +09:00
|
|
|
|
|
2016-02-24 01:01:40 +09:00
|
|
|
|
public int ColumnPosition;
|
2016-02-17 20:34:26 +09:00
|
|
|
|
|
2016-02-24 01:01:40 +09:00
|
|
|
|
public char Current;
|
2016-02-18 00:34:26 +09:00
|
|
|
|
|
2016-02-24 01:01:40 +09:00
|
|
|
|
public char PreviousChar1;
|
2016-02-18 00:34:26 +09:00
|
|
|
|
|
2016-02-24 01:01:40 +09:00
|
|
|
|
public char PreviousChar2;
|
2016-02-17 20:34:26 +09:00
|
|
|
|
}
|
2016-02-17 01:00:26 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|