0

我正在使用 SuperPower 库构建解析器。

这是我要解析的源输入示例:

|ABC|xyz|1 3|~~~|

  • 第一个|OpeningPipe.
  • 最后一个|ClosingPipe.
  • 第 2、3、4 个|是分隔符。
  • 最终,我希望能够在解析过程中产生这种结构:
new string[]{"ABC", "xyz", "1 3", "~~~"}

我认为我遇到的问题是我的分隔符与我的ClosingPipe角色相同。

我应该如何构建这个TextParser<string[]>

4

1 回答 1

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();
于 2019-07-29T13:54:48.757 回答