Superpower: соответствует любому небелому персонажу, кроме токенизатора
Я хотел бы использовать Nuget
пакет Superpower
соответствовать всем небелым символам, если это не токенизированное значение. Например,
var s = "some random text{variable}";
Должно привести к:
["some", "random", "text", "variable"]
Но то, что я имею сейчас:
["some", "random", "text{variable}"]
Парсеры для него выглядят так:
public static class TextParser
{
public static TextParser<string> EncodedContent =>
from open in Character.EqualTo('{')
from chars in Character.Except('}').Many()
from close in Character.EqualTo('}')
select new string(chars);
public static TextParser<string> HtmlContent =>
from content in Span.NonWhiteSpace
select content.ToString();
}
Конечно, я возвращаю строки в другой переменной в парсере. Но это просто упрощено.
Надеюсь, этого достаточно. Если нет, у меня есть все репо на Github. https://github.com/jon49/FlowSharpHtml
2 ответа
Может быть много разных способов для анализа вашего ввода, и в зависимости от того, насколько сложнее ваши входные данные на самом деле (как вы говорите, вы упростили это), вам, вероятно, придется настроить это. Но лучший способ использовать Superpower - это создавать небольшие парсеры, а затем использовать их. Смотрите мои парсеры и их описания ниже (каждый из которых построен на предыдущем):
/// <summary>
/// Parses any character other than whitespace or brackets.
/// </summary>
public static TextParser<char> NonWhiteSpaceOrBracket =>
from c in Character.Except(c =>
char.IsWhiteSpace(c) || c == '{' || c == '}',
"Anything other than whitespace or brackets"
)
select c;
/// <summary>
/// Parses any piece of valid text, i.e. any text other than whitespace or brackets.
/// </summary>
public static TextParser<string> TextContent =>
from content in NonWhiteSpaceOrBracket.Many()
select new string(content);
/// <summary>
/// Parses an encoded piece of text enclosed in brackets.
/// </summary>
public static TextParser<string> EncodedContent =>
from open in Character.EqualTo('{')
from text in TextContent
from close in Character.EqualTo('}')
select text;
/// <summary>
/// Parse a single content, e.g. "name{variable}" or just "name"
/// </summary>
public static TextParser<string[]> Content =>
from text in TextContent
from encoded in EncodedContent.OptionalOrDefault()
select encoded != null ? new[] { text, encoded } : new[] { text };
/// <summary>
/// Parse multiple contents and flattens the result.
/// </summary>
public static TextParser<string[]> AllContent =>
from content in Content.ManyDelimitedBy(Span.WhiteSpace)
select content.SelectMany(x => x.Select(y => y)).ToArray();
Затем запустить его:
string input = "some random text{variable}";
var result = AllContent.Parse(input);
Какие выводы:
["some", "random", "text", "variable"]
Идея заключается в том, чтобы создать синтаксический анализатор для анализа одного контента, а затем использовать встроенный синтаксический анализатор Superpower, который называется ManyDelimitedBy
чтобы имитировать "разделение" на пустое пространство между реальным контентом, который вы хотите разобрать. Это приводит к массиву "содержимого" частей.
Также вы можете воспользоваться функциональностью токена Superpower для получения более качественных сообщений об ошибках при сбое анализа. Это немного другой подход, но посмотрите этот пост в блоге, чтобы узнать больше о том, как использовать токенизатор, но он совершенно необязателен, если вам не нужны более понятные сообщения об ошибках.
Может быть, вы можете написать это проще, но это была моя первая идея. Я надеюсь, что это помогает:
Regex tokenizerRegex = new Regex(@"\{(.+?)\}");
var s = "some random text{variable}";
string[] splitted = s.Split(' ');
List<string> result = new List<string>();
foreach (string word in splitted)
{
if (tokenizerRegex.IsMatch(word)) //when a tokenized value were recognized
{
int nextIndex = 0;
foreach (Match match in tokenizerRegex.Matches(word)) //loop throug all matches
{
if (nextIndex < match.Index - 1) //if there is a gap between two tokens or at the beginning, add the word
result.Add(word.Substring(nextIndex, match.Index - nextIndex));
result.Add(match.Value);
nextIndex = match.Index + match.Length; //Save the endposition of the token
}
}
else
result.Add(word);//no token found, just add the word.
}
Console.WriteLine("[\"{0}\"]",string.Join("\", \"", result));
Примеры
Текст: some random text{variable}
["some", "random", "text", "{variable}"]
Текст: some random text{variable}{next}
["some", "random", "text", "{variable}", "{next}"]
Текст: some random text{variable}and{next}
["some", "random", "text", "{variable}","and", "{next}"]