These are chat archives for sprache/Sprache
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!
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.