Попытка построить TextParser<string []> с одинаковыми символами открытия / закрытия / разделителя
Я работаю над созданием парсера с библиотекой SuperPower.
Вот пример исходного ввода, который я хочу проанализировать:
|ABC|xyz|1 3|~~~|
- Первый
|
этоOpeningPipe
, - Последний
|
этоClosingPipe
, - 2-й, 3-й и 4-й
|
являются разделителями. - В конечном счете, я хотел бы иметь возможность создавать эту структуру во время синтаксического анализа:
new string[]{"ABC", "xyz", "1 3", "~~~"}
Я думаю, что проблема у меня в том, что мой символ разделителя такой же, как мой ClosingPipe
характер.
Как я должен построить это TextParser<string[]>
?
1 ответ
Вот некоторые парсеры, которые должны работать на вас:
public static TextParser<char> Pipe =>
from c in Character.EqualTo('|')
select c;
public static TextParser<string> Content =>
from c in Character.Except('|').Many()
select new string(c);
public static TextParser<string[]> Parser =>
from openingPipe in Pipe
from content1 in Content
from closingPipe in Pipe
from contents in Content.ManyDelimitedBy(Pipe)
select new[] { content1 }
.Concat(contents.Take(contents.Length - 1)) // remove the empty string on the end
.ToArray();
Тогда используйте это так:
string[] result = Parser.Parse("|ABC|xyz|1 3|~~~|");
А также result
должно быть { "ABC", "xyz", "1 3", "~~~" }
Идея состоит в том, чтобы проанализировать открывающий канал, сначала содержимое, затем закрывающий канал, а затем, поскольку (я предполагаю) остальное количество разделителей может измениться, вы можете использовать встроенный метод Superpower. ManyDelimitedBy
проанализировать как можно больше других частей контента, разделенных трубами. Но так как ваш ввод всегда имеет канал в конце, ManyDelimitedBy
оставит пустую строку в конце contents
массив, который я удаляю перед возвращением окончательного результата.
РЕДАКТИРОВАТЬ
Вот способ сделать это без необходимости отрубать пустую строку:
public static TextParser<string> ExtraContent =>
from content in Content
from pipe in Pipe
select content;
public static TextParser<string[]> Parser2 =>
from openingPipe in Pipe
from content1 in Content
from closingPipe in Pipe
from contents in ExtraContent.Many()
select new[] { content1 }.Concat(contents).ToArray();