Superpower: соответствует любому небелому персонажу, кроме токенизатора - PullRequest
0 голосов
/ 04 июля 2019

Я хотел бы использовать пакет 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 ]

1 голос
/ 09 июля 2019

Там может быть много разных способов для анализа вашего ввода, и в зависимости от того, насколько сложнее ваши входные данные (как вы говорите, вы упростили это), вам, вероятно, придется настроить это.Но лучший способ использовать 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"]
* 1009Идея состоит в том, чтобы создать синтаксический анализатор для анализа одного контента, а затем использовать встроенный синтаксический анализатор Superpower с именем ManyDelimitedBy, чтобы имитировать «расщепление» в пустом пространстве между реальным контентом, который вы хотите проанализировать.Это приводит к массиву «контентных» фрагментов.

Также вы можете воспользоваться функциональностью токена Superpower для получения лучших сообщений об ошибках при сбое анализа.Это немного другой подход, но посмотрите на этот пост в блоге , чтобы узнать больше о том, как использовать токенизатор, но это совершенно необязательно, если вам не нужны более дружественные сообщения об ошибках.

0 голосов
/ 04 июля 2019

Может быть, вы можете написать это проще, но это была моя первая идея.Надеюсь, это поможет:

    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}"]
...