This is part of a series of posts documenting Sprache:

This post covers Select and Return, which are used for transforming the result of parsing, e.g. into an abstract syntax tree, as well as Regex and RegexMatch, which as you might expect allow you to augment Sprache parsers with regular expressions.

Select

Take the result of parsing, and project it onto a different domain:

  • Parser<U> Select<T, U>(this Parser<T> parser, Func<T, U> convert)

This example takes the parser Number, which outputs a string, and converts it into a parser which produces integers using int.Parse.

1
2
Parser<int> number = Parse.Number.Select(int.Parse);
Assert.Equal(12, number.Parse("12"));

This method is also used extensively when parsing using linq expressions, for example in the following example which parses an XML element, select is used both to concatenate the to parsed parts of the identifier, and to return the tag name.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var identifier =
    from first in Parse.Letter.Once()
    from rest in Parse.LetterOrDigit.XOr(Parse.Char('-')).XOr(Parse.Char('_')).Many()
    select new string(first.Concat(rest).ToArray());

var tag =
    from lt in Parse.Char('<')
    from t in identifier
    from gt in Parse.Char('>').Token()
    select t;

Assert.Equal("test", tag.Parse("<test>"));

Return

Succeed immediately and return value, a bit like select, but ignorings the result of the parser. It has two overloads, but I’m honestly not sure when you would use the first:

  • Parser<T> Return<T>(T value)
  • Parser<U> Return<T, U>(this Parser<T> parser, U value)

Although similar to Select, this is handy to use in situations where the return value from the parser doesn’t matter, e.g when parsing operators or keywords.

1
2
3
Parser<OperatorType> add = Parse.String("+").Return(OperatorType.Add);

Assert.Equal(OperatorType.Add, add.Parse("+"));

Regex

Construct a parser from the given regular expression. Has 2 overloads allowing you to supply the regex as either a string or a Regex object. Like Char, this also lets you supply a description for the parser.

  • Parser<string> Regex(string pattern, string description = null)
  • Parser<string> Regex(Regex regex, string description = null)
1
2
3
4
Parser<string> digits = Parse.Regex(@"\d(\d*)");

Assert.Equal("123", digits.Parse("123d"));
Assert.Throws<ParseException>(() => digits.Parse("d123"));

RegexMatch

Construct a parser from the given regular expression, however differs from Regex in that it returns the Match object returned by the regular expression instead of the matched value.

  • Parser<Match> RegexMatch(string pattern, string description = null)
  • Parser<Match> RegexMatch(Regex regex, string description = null)
1
2
3
Parser<Match> digits = Parse.RegexMatch(@"\d(\d*)");

Assert.Equal("23", digits.Parse("123d").Groups[1].Value);