3

Sprache を使用して、次のようなファイルのセクションを解析しています。

OneThing=Foo
AnotherThing=Bar
YetAnotherThing=Baz

3 つの行はすべて必須ですが、任意の順序で表示できます。次のような個々の行のパーサーがあります。

public static readonly Parser<string> OneThing = (
    from open in Parse.String("OneThing=")
    from rest in Parse.AnyChar.Except(Parse.LineTerminator).Many().Text()
    from newLine in Parse.LineEnd
    select rest
);

そして、次のように、それらを組み合わせてセクション全体を解析します。

public static readonly Parser<MyClass> Section = (
    from oneThing in SectionGrammar.OneThing
    from anaotherThing in SectionGrammar.AnotherThing
    from yetAnotherThing in SectionGrammar.YetAnotherThing
    select new MyClass(oneThing, anotherThing, yetAnotherThing)
);

ただし、これは行が OneThing、AnotherThing、YetAnotherThing の順序で表示される場合にのみ機能します。これを変更して、行を任意の順序で表示できるようにするにはどうすればよいですか?

どんな助けでも大歓迎です!ありがとう

4

3 に答える 3

0

私は Sprache について非常に素朴ですが、おそらく冗長な方法の 1 つは、各行の各オプションのタプルを選択し、最終的な選択でタプル配列をフィルタリングすることです。何かのようなもの:

public static readonly Parser<MyClass> Section = (
select a from (from oneThing in SectionGrammar.OneThing select Tuple.Create(oneThing, null, null))
    .Or(from anotherThing in SectionGrammar.AnotherThing select Tuple.Create(null, anotherThing, null))
    .Or(from yetAnotherThing in SectionGrammar.YetAnotherThing select Tuple.Create(null, null, yetAnotherThing))

select b from (from oneThing in SectionGrammar.OneThing select Tuple.Create(oneThing, null, null))
    .Or(from anotherThing in SectionGrammar.AnotherThing select Tuple.Create(null, anotherThing, null))
    .Or(from yetAnotherThing in SectionGrammar.YetAnotherThing select Tuple.Create(null, null, yetAnotherThing))

select c from (from oneThing in SectionGrammar.OneThing select Tuple.Create(oneThing, null, null))
    .Or(from anotherThing in SectionGrammar.AnotherThing select Tuple.Create(null, anotherThing, null))
    .Or(from yetAnotherThing in SectionGrammar.YetAnotherThing select Tuple.Create(null, null, yetAnotherThing))

select new MyClass(
    new[] { a, b, c }.Where(i => i.Item1 != null).Select(i => i.Item1).First(),
    new[] { a, b, c }.Where(i => i.Item2 != null).Select(i => i.Item2).First(),
    new[] { a, b, c }.Where(i => i.Item3 != null).Select(i => i.Item3).First()
));

しかし、もっと良い方法があるべきだと感じています。一意の解析を行い、異なる順序である可能性がある 20 行があったとあなたが私に言った場合、上記もあまりスケーラブルではありません。

于 2020-05-28T09:53:34.290 に答える