尝试用相似的 open/close/delimiter 个字符构建 TextParser<string[]>
Trying to build TextParser<string[]> with alike open/close/delimiter characters
我正在使用 SuperPower 库构建解析器。
这是我要解析的源输入示例:
|ABC|xyz|1 3|~~~|
- 第一个
|
是 OpeningPipe
。
- 最后一个
|
是ClosingPipe
.
- 第二个、第三个、第四个
|
是分隔符。
- 最终,我希望能够在解析过程中生成此结构:
new string[]{"ABC", "xyz", "1 3", "~~~"}
我认为我遇到的问题是我的分隔符与我的 ClosingPipe
字符相同。
我应该如何构建这个 TextParser<string[]>
?
以下是一些适合您的解析器:
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();
我正在使用 SuperPower 库构建解析器。
这是我要解析的源输入示例:
|ABC|xyz|1 3|~~~|
- 第一个
|
是OpeningPipe
。 - 最后一个
|
是ClosingPipe
. - 第二个、第三个、第四个
|
是分隔符。 - 最终,我希望能够在解析过程中生成此结构:
new string[]{"ABC", "xyz", "1 3", "~~~"}
我认为我遇到的问题是我的分隔符与我的 ClosingPipe
字符相同。
我应该如何构建这个 TextParser<string[]>
?
以下是一些适合您的解析器:
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();