Я создаю приложение, похожее на vim, небольшой консольный текстовый редактор. И у меня проблема с реализацией подсветки текста.
Я знаю, что есть два способа написать это: либо с помощью регулярных выражений, либо с помощью абстрактного синтаксического дерева. Я не хочу использовать регулярные выражения, потому что они не дают достаточно информации. Я использовал токенизатор, разделил свой текст на токены и присвоил каждому тип, но этой информации недостаточно (мне также нужно положение токена относительно остальных, чтобы определить, является ли набор символов функцией или назначением класса) .
Как мне создать это абстрактное синтаксическое дерево и, самое главное, как я могу использовать его для выделения текста?
Я хочу иметь возможность (говоря о HTML) выделите имя тега цветом 1, имя параметрической метки цветом 2, кавычки цветом 3, знак равенства цветом 4 и т. д.
Возможно, есть другой способ сделать это без использования абстрактного синтаксическое дерево.
Если возможно, предоставьте фрагмент кода, реализующий эту логику, например, для html или css.
Это фрагмент кода токенизатора
public enum HTMLTokenType
{
End,
Quotes,
Equal,
String,
Close,
Open,
}
public class Token
{
public Token(HTMLTokenType type, int start, int length)
{
Type = type;
Start = start;
Length = length;
}
public HTMLTokenType Type { get; set; }
public int Start { get; set; }
public int Length { get; set; }
}
public class HTMLLexer
{
private readonly string _text;
private int _cursor;
private readonly Dictionary _keywords = new()
{
{ "".Length) },
{ "=", (HTMLTokenType.Equal, "=".Length) },
{ "\"", (HTMLTokenType.Quotes, "\"".Length) },
};
public HTMLLexer(string text)
{
_text = text;
}
public Token NextToken()
{
if (_cursor >= _text.Length)
{
return new Token(HTMLTokenType.End, _cursor, 0);
}
if (_cursor + 1 < _text.Length && _keywords.ContainsKey(_text[_cursor..(_cursor + 2)]))
{
(HTMLTokenType type, int length) = _keywords[_text[_cursor..(_cursor + 2)].ToString()];
Token token = new(type, _cursor, length);
_cursor += length;
return token;
}
if (_keywords.ContainsKey(_text[_cursor].ToString()))
{
(HTMLTokenType type, int length) = _keywords[_text[_cursor].ToString()];
Token token = new(type, _cursor, length);
_cursor += length;
return token;
}
string @string = "";
while (_cursor < _text.Length)
{
if (_text[_cursor] == ' ')
{
Token token = new(HTMLTokenType.String, _cursor - @string.Length, @string.Length);
_cursor++;
return token;
}
if (_keywords.ContainsKey(_text[_cursor].ToString()) || (_cursor + 1 < _text.Length && _keywords.ContainsKey(_text[_cursor..(_cursor + 2)])))
{
return new Token(HTMLTokenType.String, _cursor - @string.Length, @string.Length);
}
@string += _text[_cursor].ToString();
_cursor++;
}
return new Token(HTMLTokenType.End, _cursor, 0);
}
}
Подробнее здесь: https://stackoverflow.com/questions/787 ... or-c-sharp