Парсер шаблонов готов
This commit is contained in:
@@ -2,7 +2,7 @@ using System;
|
||||
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public class DefineTemplateSection : ITemplateSection, ITagged
|
||||
public class DefineTemplateSection : ITagged
|
||||
{
|
||||
public TemplateDocument Context { get; set; }
|
||||
public string StoredText { get; }
|
||||
@@ -18,14 +18,10 @@ namespace mROA.CodegenTools
|
||||
public string Tag => _tag;
|
||||
public int TargetLength => StoredText.Length;
|
||||
|
||||
public string Bake()
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return StoredText;
|
||||
return $"{nameof(_tag)}: {_tag}, {nameof(StoredText)}: {StoredText}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,14 @@ namespace mROA.CodegenTools
|
||||
{
|
||||
TemplateDocument Context { get; set; }
|
||||
int TargetLength { get; }
|
||||
string Bake();
|
||||
}
|
||||
|
||||
public interface IBaking
|
||||
{
|
||||
string Bake();
|
||||
}
|
||||
|
||||
|
||||
public interface ITagged : ITemplateSection
|
||||
{
|
||||
string Tag { get; }
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public class InnerTemplateSection : ITemplateSection, ITagged
|
||||
{
|
||||
private readonly string _tag;
|
||||
public TemplateDocument Context { get; set; }
|
||||
public int TargetLength => 0;
|
||||
|
||||
public string Tag => _tag;
|
||||
|
||||
public TemplateDocument InnerTemplate { get; }
|
||||
|
||||
public InnerTemplateSection(string tag, TemplateDocument innerTemplate, TemplateDocument context)
|
||||
{
|
||||
_tag = tag;
|
||||
Context = context;
|
||||
InnerTemplate = innerTemplate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public class InsertTemplatePart : ITagged
|
||||
public class InsertTemplatePart : ITagged, IBaking
|
||||
{
|
||||
private object _insertedValue;
|
||||
private string _tag;
|
||||
@@ -11,10 +12,10 @@ namespace mROA.CodegenTools
|
||||
public TemplateDocument Context { get; set; }
|
||||
public readonly List<string> Parameters;
|
||||
|
||||
public InsertTemplatePart(string tag, List<string> parameters, TemplateDocument context)
|
||||
public InsertTemplatePart(string tag, TemplateDocument context, params string[] parameters)
|
||||
{
|
||||
_tag = tag;
|
||||
Parameters = parameters;
|
||||
Parameters = parameters.ToList();
|
||||
Context = context;
|
||||
}
|
||||
|
||||
@@ -61,7 +62,7 @@ namespace mROA.CodegenTools
|
||||
case string s:
|
||||
return s;
|
||||
default:
|
||||
return ((ITemplateSection)_insertedValue).Bake();
|
||||
return ((ITemplateSection)_insertedValue).ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.Linq;
|
||||
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public class LinkTemplateSection : ITemplateSection
|
||||
public class LinkTemplateSection : ITemplateSection, IBaking
|
||||
{
|
||||
private readonly string _linkedTag;
|
||||
|
||||
@@ -16,11 +16,23 @@ namespace mROA.CodegenTools
|
||||
|
||||
public string LinkedTag => _linkedTag;
|
||||
|
||||
public int TargetLength { get; }
|
||||
public int TargetLength
|
||||
{
|
||||
get
|
||||
{
|
||||
var attached = Context[_linkedTag];
|
||||
return attached?.TargetLength ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
public string Bake()
|
||||
{
|
||||
return Context[_linkedTag]?.Bake();
|
||||
return Context[_linkedTag]?.ToString();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(LinkedTag)}: {_linkedTag}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public class LiteralTemplateSection : ITemplateSection
|
||||
public class LiteralTemplateSection : ITemplateSection, IBaking
|
||||
{
|
||||
private string _internalText;
|
||||
|
||||
@@ -11,11 +11,11 @@ namespace mROA.CodegenTools
|
||||
}
|
||||
|
||||
public TemplateDocument Context { get; set; }
|
||||
public int TargetLength { get; }
|
||||
public int TargetLength => _internalText.Length;
|
||||
|
||||
public string Bake()
|
||||
{
|
||||
return _internalText;
|
||||
return ToString();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public class ProgrammableTextSection : ITemplateSection
|
||||
public class ProgrammableTextSection : ITemplateSection, IBaking
|
||||
{
|
||||
public TemplateDocument Context { get; set; }
|
||||
public int TargetLength => 0;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public class DefineSectionReader : LeadingTextSectionReader
|
||||
{
|
||||
public DefineSectionReader() : base("<!D")
|
||||
{
|
||||
}
|
||||
|
||||
public override ITemplateSection ExtractSection(ref int index, TemplateDocument document)
|
||||
{
|
||||
var tagEnd = TemplateText.IndexOf(">", index, StringComparison.Ordinal);
|
||||
var sectionName = GetTagValue(index, tagEnd);
|
||||
tagEnd += 1;
|
||||
var endIndex = TemplateText.IndexOf("<!D>", tagEnd, StringComparison.Ordinal);
|
||||
var storedText = TemplateText.Substring(tagEnd, endIndex - tagEnd);
|
||||
index = endIndex + 4;
|
||||
PassCaretToCloseSymbol();
|
||||
PassCaretToCloseSymbol();
|
||||
return new DefineTemplateSection(storedText, sectionName, document);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public interface ISectionReader
|
||||
{
|
||||
string TemplateText { get; set; }
|
||||
int GetNextSectionIndex(int currentIndex);
|
||||
ITemplateSection ExtractSection(ref int index, TemplateDocument document);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public class InnerTemplateSectionReader : LeadingTextSectionReader
|
||||
{
|
||||
public InnerTemplateSectionReader() : base("<!T")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public override ITemplateSection ExtractSection(ref int index, TemplateDocument document)
|
||||
{
|
||||
var end = FindEnd(index + 4);
|
||||
var from = index;
|
||||
var to = PassCaretToCloseSymbol();
|
||||
index = to;
|
||||
|
||||
var tagName = GetTagValue(from, to);
|
||||
|
||||
var innerDocText = TemplateText.Substring(index, end - index);
|
||||
var innerDoc = TemplateReader.Parce(innerDocText);
|
||||
_currentCaretPosition = end + 4;
|
||||
index = _currentCaretPosition;
|
||||
return new InnerTemplateSection(tagName, innerDoc, document);
|
||||
}
|
||||
|
||||
private int FindEnd(int start)
|
||||
{
|
||||
var endSymbol = TemplateText.IndexOf("<!T>", start, StringComparison.Ordinal);
|
||||
var innerStartSymbol = TemplateText.IndexOf("<!T ", start, StringComparison.Ordinal);
|
||||
if (endSymbol < innerStartSymbol || innerStartSymbol == -1)
|
||||
return endSymbol;
|
||||
|
||||
return FindEnd(endSymbol + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public class InsertSectionReader : LeadingTextSectionReader
|
||||
{
|
||||
public InsertSectionReader() : base("<!I")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public override ITemplateSection ExtractSection(ref int index, TemplateDocument document)
|
||||
{
|
||||
var from = index;
|
||||
var to = PassCaretToCloseSymbol();
|
||||
index = to;
|
||||
|
||||
var tagText = GetTagValue(from, to);
|
||||
var parts = tagText.Split(' ');
|
||||
|
||||
return new InsertTemplatePart(parts[0], document, parts.Skip(1).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public abstract class LeadingTextSectionReader : ISectionReader
|
||||
{
|
||||
protected int _currentCaretPosition;
|
||||
private string _tagLeading;
|
||||
|
||||
protected LeadingTextSectionReader(string tagLeading)
|
||||
{
|
||||
_tagLeading = tagLeading + " ";
|
||||
}
|
||||
|
||||
protected int PassCaretToCloseSymbol()
|
||||
{
|
||||
_currentCaretPosition = TemplateText.IndexOf(">", _currentCaretPosition, StringComparison.Ordinal) + 1;
|
||||
return _currentCaretPosition;
|
||||
}
|
||||
|
||||
public string TemplateText { get; set; }
|
||||
|
||||
public int GetNextSectionIndex(int currentIndex)
|
||||
{
|
||||
_currentCaretPosition = Math.Max(currentIndex, _currentCaretPosition);
|
||||
var index = TemplateText.IndexOf(_tagLeading, _currentCaretPosition, StringComparison.Ordinal);
|
||||
_currentCaretPosition = index;
|
||||
return index;
|
||||
}
|
||||
|
||||
public abstract ITemplateSection ExtractSection(ref int index, TemplateDocument document);
|
||||
|
||||
protected string GetTagValue(int from, int to)
|
||||
{
|
||||
return TemplateText.Substring(from + 4, to - from - 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public class LinkSectionReader : LeadingTextSectionReader
|
||||
{
|
||||
public LinkSectionReader() : base("<!L")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public override ITemplateSection ExtractSection(ref int index, TemplateDocument document)
|
||||
{
|
||||
var from = index;
|
||||
var to = PassCaretToCloseSymbol();
|
||||
index = to;
|
||||
|
||||
var tagText = GetTagValue(from, to);
|
||||
return new LinkTemplateSection(tagText, document);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace mROA.CodegenTools
|
||||
{
|
||||
public static class TemplateReader
|
||||
{
|
||||
private static readonly List<Type> ReaderTypes = new List<Type>
|
||||
{
|
||||
typeof(DefineSectionReader),
|
||||
typeof(InsertSectionReader),
|
||||
typeof(LinkSectionReader),
|
||||
typeof(InnerTemplateSectionReader)
|
||||
};
|
||||
|
||||
public static TemplateDocument Parce(string templateText)
|
||||
{
|
||||
|
||||
int currentIndex = 0;
|
||||
var activeReaders = new List<ISectionReader>();
|
||||
|
||||
foreach (var readerType in ReaderTypes)
|
||||
{
|
||||
var reader = Activator.CreateInstance(readerType) as ISectionReader;
|
||||
reader.TemplateText = templateText;
|
||||
activeReaders.Add(reader);
|
||||
}
|
||||
|
||||
var doc = new TemplateDocument();
|
||||
|
||||
while (currentIndex < templateText.Length)
|
||||
{
|
||||
List<(ISectionReader reader, int index)> indices = activeReaders.Select(i => ((ISectionReader Readers, int index))(i, i.GetNextSectionIndex(currentIndex))).Where(i => i.index > -1).ToList();
|
||||
int minIndex = templateText.Length;
|
||||
ISectionReader minReader = null;
|
||||
if (indices.Count != 0)
|
||||
{
|
||||
minIndex = indices.Min(i => i.index);
|
||||
minReader = indices.FirstOrDefault(i => i.index == minIndex).reader;
|
||||
|
||||
if (indices.Count != activeReaders.Count)
|
||||
{
|
||||
activeReaders = indices.Select(i => i.reader).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (currentIndex != minIndex)
|
||||
{
|
||||
var literalText = templateText.Substring(currentIndex, minIndex - currentIndex);
|
||||
var literal =
|
||||
new LiteralTemplateSection(literalText, doc);
|
||||
doc.Parts.Add(literal);
|
||||
currentIndex = minIndex;
|
||||
}
|
||||
|
||||
if (indices.Count != 0)
|
||||
{
|
||||
var section = minReader.ExtractSection(ref currentIndex, doc);
|
||||
doc.Parts.Add(section);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace mROA.CodegenTools
|
||||
{
|
||||
public class TemplateDocument
|
||||
{
|
||||
public List<ITemplateSection> Parts { get; }
|
||||
public List<ITemplateSection> Parts { get; set; } = new List<ITemplateSection>();
|
||||
public object AdditionalContext { get; set; }
|
||||
public ITagged this[string tag] => Parts.OfType<ITagged>().FirstOrDefault(i => i.Tag == tag);
|
||||
public void Insert(string tag, object value)
|
||||
@@ -22,10 +22,9 @@ namespace mROA.CodegenTools
|
||||
{
|
||||
var approximatelyLength = Parts.Sum(i => i.TargetLength);
|
||||
var stringBuilder = new StringBuilder(approximatelyLength);
|
||||
|
||||
for (int i = 0; i < Parts.Count; i++)
|
||||
|
||||
foreach (var part in Parts.OfType<IBaking>())
|
||||
{
|
||||
var part = Parts[i];
|
||||
var baked = part.Bake();
|
||||
stringBuilder.Append(baked);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user