These are chat archives for sprache/Sprache

16th
June 2016
Sunday May 1, 2016Monday May 2, 2016Tuesday May 3, 2016Wednesday May 4, 2016Thursday May 5, 2016Friday May 6, 2016Saturday May 7, 2016Sunday May 8, 2016Monday May 9, 2016Tuesday May 10, 2016Wednesday May 11, 2016Thursday May 12, 2016Friday May 13, 2016Saturday May 14, 2016Sunday May 15, 2016Monday May 16, 2016Tuesday May 17, 2016Wednesday May 18, 2016Thursday May 19, 2016Friday May 20, 2016Saturday May 21, 2016Sunday May 22, 2016Monday May 23, 2016Tuesday May 24, 2016Wednesday May 25, 2016Thursday May 26, 2016Friday May 27, 2016Saturday May 28, 2016Sunday May 29, 2016Monday May 30, 2016Tuesday May 31, 2016MayWednesday June 1, 2016Thursday June 2, 2016Friday June 3, 2016Saturday June 4, 2016Sunday June 5, 2016Monday June 6, 2016Tuesday June 7, 2016Wednesday June 8, 20162 items on Thursday June 9, 20165 items on Friday June 10, 2016Saturday June 11, 20161 item on Sunday June 12, 20162 items on Monday June 13, 2016Tuesday June 14, 2016Wednesday June 15, 20166 items on Thursday June 16, 2016Friday June 17, 2016Saturday June 18, 2016Sunday June 19, 2016Monday June 20, 2016Tuesday June 21, 2016Wednesday June 22, 2016Thursday June 23, 2016Friday June 24, 2016Saturday June 25, 2016Sunday June 26, 2016Monday June 27, 2016Tuesday June 28, 2016Wednesday June 29, 2016Thursday June 30, 2016June3 items on Friday July 1, 2016Saturday July 2, 2016Sunday July 3, 2016Monday July 4, 2016Tuesday July 5, 2016Wednesday July 6, 2016Thursday July 7, 2016Friday July 8, 2016Saturday July 9, 2016Sunday July 10, 2016Monday July 11, 2016Tuesday July 12, 2016Wednesday July 13, 2016Thursday July 14, 2016Friday July 15, 2016Saturday July 16, 2016Sunday July 17, 2016Monday July 18, 2016Tuesday July 19, 2016Wednesday July 20, 2016Thursday July 21, 2016Friday July 22, 2016Saturday July 23, 2016Sunday July 24, 2016Monday July 25, 2016Tuesday July 26, 2016Wednesday July 27, 2016Thursday July 28, 2016Friday July 29, 2016Saturday July 30, 2016Sunday July 31, 2016July
roomaroo
@roomaroo
Jun 16 2016 10:01

Hi - I'm rewriting some old initialization-string parsing code, and I'm trying to use Sprache.

The text I'm parsing is simple delimited key-value pairs, e.g.

"com_port:1;baud_rate:9600;parity:None"

(you can see how old the original code is - it uses modem connection strings as an example!)

That's pretty easy to parse - I don't need Sprache, I could just use Split(...)

The difficulty is the grammar has the ability to modify itself - e.g.

"com_port:1;baud_rate:9600;@ASS=;parity=None"

That @ASS= means that from that point on, use '=' for assignment instead of ':'

I'm trying to get this to work in Sprache - but not getting far yet!

roomaroo
@roomaroo
Jun 16 2016 10:13

Here's what I've got so far:

        class KeyValue
        {
            public string Key { get; set; }
            public string Value { get; set; }
        }


        static Parser<char> delimiter = Parse.Char(';');

        static char assignmentChar = ':';
        static Parser<char> assignment = Parse.Char(assignmentChar);

        static Parser<string> key = Parse.AnyChar.Except(delimiter).Except(assignment).Many().Text();
        static Parser<string> value = Parse.AnyChar.Except(delimiter).Many().Text();

        static Parser<KeyValue> keyValue =
            from k in key
            from x in assignment
            from v in value
            select new KeyValue { Key = k, Value = v };

        static Parser<KeyValue> updateAssignment = 
            from _ in Parse.String("@ASS").Text()
            from c in Parse.AnyChar
            select UpdateAssignment(c);

        static KeyValue UpdateAssignment(char c)
        {
            assignmentChar = c;
            return null;
        }

        static Parser<KeyValue> item = keyValue.Or(updateAssignment);

        static Parser<Dictionary<string, string>> items =
            from leading in item
            from rest in delimiter.Then(_ => item).Many()
            let list = Cons(leading, rest)
            select list.Where(i => i != null).ToDictionary(x => x.Key, x => x.Value);

        [Test]
        public void Assignment_can_be_modified_while_parsing_string()
        {
            // Given
            var input = "com_port:1;baud_rate:9600;@ASS=;parity=None";

            // When
            var result = items.Parse(input);

            // Then
            Assert.AreEqual("1", result["com_port"]);
            Assert.AreEqual("None", result["parity"]);
        }

The updateAssignment parser calls the UpdateAssignment method, which updates the assignment character - that does get called when I parse the string, but the new assignment character isn't used when parsing the parity=None section.

roomaroo
@roomaroo
Jun 16 2016 10:26
Aha - I've made it work by changing all the parsers from fields to properties. That forces them to be re-evaulated at the point of use
Nicholas Blumhardt
@nblumhardt
Jun 16 2016 21:25
@roomaroo wow, that's a crazy grammar to have to deal with! Glad to hear you got a solution :-)
Hard to cook up, but passing the assignment character right through the parser as a parameter might be a more "functional" feeling solution
sometimes I've found writing more complex functional parsers is easier outside the static context, e.g each parser is a local variable or function call inside some static method, rather than using static properties to hold the assembled bits and pieces