Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Вильданов Савелий #226

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions cs/Markdown/Converter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Text;

namespace Markdown;

public class Converter
{
public string ConvertWithTokens(List<Token> tokens)
{
StringBuilder result = new();

foreach (var token in tokens)
{
result.Append(token.Context);
}

return result.ToString();
}
}
10 changes: 10 additions & 0 deletions cs/Markdown/ListOfTokens.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Markdown;

public class ListOfTokens<T> : List<T>
{
public new void Add(T token)
{
if (!(token is null))
base.Add(token);
}
}
10 changes: 10 additions & 0 deletions cs/Markdown/Markdown.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
11 changes: 11 additions & 0 deletions cs/Markdown/Md.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Markdown;

public class Md
{
public static string Render(string markdown)
{
TokenGenerator tokenGenerator = new TokenGenerator();
Converter converter = new Converter();
return converter.ConvertWithTokens(tokenGenerator.SplitParagraphs(markdown));
}
}
118 changes: 118 additions & 0 deletions cs/Markdown/Parsers/BoldParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
using System.Collections;
using System.Security.Principal;
using Markdown.TagsType;

namespace Markdown.Parsers;

public class BoldParser : IParser
{
private readonly Stack<Token> tagsStack;
private readonly GeneralParser.IsValidTag isValidOpenBoldTag;
private readonly GeneralParser.IsValidTag isValidCloseBoldTag;
private readonly GeneralParser.AddInsert addBoldTag;
public bool IsHaveInsideBoldTag;
public static bool IsBoldClosed;
private int index;

public BoldParser()
{
IsBoldClosed = true;
IsHaveInsideBoldTag = false;
tagsStack = GeneralParser.tagsStack;
addBoldTag = GeneralParser.AddInsideTag;
isValidOpenBoldTag = GeneralParser.IsValidOpenTag;
isValidCloseBoldTag = GeneralParser.IsValidCloserTag;
index = 0;
}

private Token BoldParse(string text, int i)
{
index = i;
index++;

if (i != 0 && i != text.Length - 2)
IsHaveInsideBoldTag = true;
if (IsEmptyStringInsideBold(text, i))
{
index = text.Length;
return new Token("____", new TextTag());
}

if (IsBoldClosed)
{
if (!isValidOpenBoldTag(text, i + 1))
{
return (new Token("__", new TextTag()));
}
}
else
{
if (!isValidCloseBoldTag(text, i))
{
if (isValidOpenBoldTag(text, i))
{
if (tagsStack.Count != 0)
tagsStack.Pop();
return addBoldTag(new BoldTag(), true);
}

return new Token("__", new TextTag());
}
}

if (tagsStack.Count > 1 &&
tagsStack.Any(p => p.Type is {MarkdownTag: "_"}) &&
tagsStack.Peek().Type is {MarkdownTag: "__"})
{
tagsStack.Pop();
}

if (!IsBoldClosed && i == text.Length - 1)
{
tagsStack.Pop();
}

var boldTag = addBoldTag(new BoldTag(), IsBoldClosed);
IsBoldClosed = !IsBoldClosed;


return boldTag;
}

public bool IsNextSymbolBold(string text, int i)
{
var nextIndex = i + 1;
if (nextIndex < text.Length)
{
if (text[nextIndex] == '_')
{
return true;
}
}

return false;
}

private bool IsEmptyStringInsideBold(string text, int i)
{
int nextIndex = i + 1;
if (nextIndex < text.Length - 2 && IsNextSymbolBold(text, nextIndex))
{
return true;
}

return false;
}

public bool TryParse(char symbol, string text, int i)
{
return symbol == '_' && IsNextSymbolBold(text, i);
}

public Token Parse(string text, ref int i)
{
var token = BoldParse(text, i);
i = index;
return token;
}
}
59 changes: 59 additions & 0 deletions cs/Markdown/Parsers/GeneralParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using Markdown.TagsType;

namespace Markdown.Parsers;

public static class GeneralParser
{
public static Stack<Token> tagsStack = new();

public delegate Token AddInsert(ITagsType tags, bool isClose);

public delegate bool IsValidTag(string text, int index);

public static Token AddInsideTag(ITagsType tag, bool isClose)
{
var result = GenerateTagToken(tag, isClose);
if (!isClose && tagsStack.Count != 0 && tagsStack.Peek().Type?.MarkdownTag == tag.MarkdownTag)
ClosePairTag(tagsStack.Pop());
return result;
}

public static Token GenerateTagToken(ITagsType tag, bool isClose)
{
if (isClose)
{
var temp = new Token(tag.GetHtmlOpenTag, tag);
tagsStack.Push(temp);
return temp;
}

if (tagsStack.Count != 0 && tagsStack.Peek().Type?.MarkdownTag == tag.MarkdownTag)
tag.HasPair = true;
return new Token(tag.GetHtmlCloseTag, tag);
}

public static void ClosePairTag(Token token)
{
if (token.Type != null) token.Type.HasPair = true;
}

public static bool IsValidCloserTag(string text, int index)
{
if (index == 0)
return false;
if (index > 0 && text[index - 1] == ' ')
return false;

return true;
}

public static bool IsValidOpenTag(string text, int index)
{
if (index == text.Length - 1)
return false;
if (index < text.Length - 1 && text[index + 1] == ' ')
return false;

return true;
}
}
17 changes: 17 additions & 0 deletions cs/Markdown/Parsers/HeadingParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Markdown.TagsType;

namespace Markdown.Parsers;

public class HeadingParser : IParser
{
public bool TryParse(char symbol, string text, int index)
{
return symbol == '#';
}

public Token Parse(string text, ref int index)
{
var headingTag = new HeadingTag();
return new Token(headingTag.GetHtmlOpenTag, headingTag);
}
}
7 changes: 7 additions & 0 deletions cs/Markdown/Parsers/IParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Markdown.Parsers;

public interface IParser
{
bool TryParse(char symbol, string text, int index);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это скорее CanParse наверное? Обычно методы Try... пытаются вернуть какой-то результат в out параметре, то есть "пытаются что-то сделать и вернуть успешность этого действия" - например, int.TryParse(..., out value), dictionary.TryGetValue(..., out value), а в твоем случае этого параметра нет

Token Parse(string text, ref int index);
}
75 changes: 75 additions & 0 deletions cs/Markdown/Parsers/ItalicParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using Markdown.TagsType;

namespace Markdown.Parsers;

public class ItalicParser : IParser
{
private readonly GeneralParser.IsValidTag isValidOpenItalicTag;
private readonly GeneralParser.IsValidTag isValidCloseItalicTag;
private readonly GeneralParser.AddInsert addItalicTag;
private bool isItalicClosed;
private readonly Stack<Token> tagsStack;
public bool IsHaveInsideItalicTag;


public ItalicParser()
{
isItalicClosed = true;
tagsStack = GeneralParser.tagsStack;
addItalicTag = GeneralParser.AddInsideTag;
isValidOpenItalicTag = GeneralParser.IsValidOpenTag;
isValidCloseItalicTag = GeneralParser.IsValidCloserTag;
IsHaveInsideItalicTag = false;
}

private Token ItalicParse(string text, int i)
{
if (i != 0 && i != text.Length - 1)
IsHaveInsideItalicTag = true;
if (isItalicClosed)
{
if (!isValidOpenItalicTag(text, i))
{
return new Token("_", new TextTag());
}
}
else
{
if (!isValidCloseItalicTag(text, i))
{
if (isValidOpenItalicTag(text, i))
{
if (tagsStack.Count != 0)
tagsStack.Pop();
return addItalicTag(new ItalicTag(), true);
}

return new Token("_", new TextTag());
}
}

if (tagsStack.Count > 1 && !isItalicClosed && BoldParser.IsBoldClosed)
{
tagsStack.Pop();
}

var result = addItalicTag(new ItalicTag(), isItalicClosed);
isItalicClosed = !isItalicClosed;
if (!isItalicClosed && i == text.Length - 1)
{
tagsStack.Pop();
}

return result;
}

public bool TryParse(char symbol, string text, int i)
{
return symbol == '_';
}

public Token Parse(string text, ref int index)
{
return ItalicParse(text, index);
}
}
Loading