Search code examples
c#parsingsprache

Aggregate List into Dictionary


I'm trying to create a Sprache parser where a part of the input should be parsed into a dictionary

input=some/fixed/stuff;and=a;list=of;arbitrary=key;value=pairs

The and=a;list=of;arbitrary=key;value=pairs part is supposed to end up in a Dictionary<string,string>.
For this i have

    public static Parser<string> Key = Parse.CharExcept('=').Many().Text();
    public static Parser<string> Value = Parse.CharExcept(';').Many().Text();

    public static Parser<KeyValuePair<string, string>> ParameterTuple =
        from key in Key
        from eq in Parse.Char('=')
        from value in Value
        select new KeyValuePair<string, string>(key, value);

and the extension methods

    public static IEnumerable<T> Cons<T>(this T head, IEnumerable<T> rest)
    {
        yield return head;
        foreach (var item in rest)
            yield return item;
    }

    public static Parser<IEnumerable<T>> ListDelimitedBy<T>(this Parser<T> parser, char delimiter)
    {
        return
            from head in parser
            from tail in Parse.Char(delimiter).Then(_ => parser).Many()
            select head.Cons(tail);
    }

(copied from the examples)

then I tried

public static Parser<IEnumerable<KVP>> KeyValuePairList = KVPair.ListDelimitedBy(';'); // KVP is just an alias for KeyValuePair<string,string>

and now I'm stuck on how to do something like

public static Parser<???> Configuration =
        from fixedstuff in FixedStuff
        from kvps in Parse.Char(';').Then(_ => KeyValuePairList)
        select new ???(fixedstuff, MakeDictionaryFrom(kvps))

or something like that.
How would I parse the arbitrary key=value[;] pairs into a dictionary?


Solution

  • It is actually very easy to make a dictionary out of anything IEnumerable, just be sure to include System.Linq. It really is just a matter of the query being correct and understanding it, which in your case is the actual string parsing so I leave that to you. The following code builds a dictionary you just need to provide the strings and parsing.

    //If the parse is simple it can be done inline with the dictionary creation
    private string GenerateKey(string fullString)
    {
       //parse key from original string and return
    }
    
    //If the parse is simple it can be done inline with the dictionary creation
    private string GenerateValue(string fullString)
    {
         //Parse Values from your original string and return
    }
    
    
    private void UsageMethod(IEnumerable<fullString> sprachs)
    {
          var dictionary = sprachs.ToDictionary(
                                  fString => GenerateKey(fString), //The Key
                                  fString => GenerateValue(fString) //The Value
                           );
    
          //Now you can use Dicitonary as it is a IDictionary<string,string>
          // so it too can be overriden an extended if need be
    }