1

I'm attempting to write a parser in Sprache that will parse a phrase

The basic rule is that it should include words seperated by a single space, with both the first and last character of the string being a space.

I would expect to call something like the following:

string phrase = PhraseParser.Parse("         I want to return up to this point        ");

And have the resulting string be "I want to return up to this point".

I have tried numerous implementations with none quite doing it for me.

Update Thanks to @PanagiotisKanavos, the trick would be to use the .Then() operator. The following words:

public static Parser<string> WordParser =
        Parse.Letter.Many().Text().Token();

public static Parser<string> PhraseParser =
        from leading in Parse.LetterOrDigit.Many().Text()
        from rest in Parse.Char(' ').Then(_ => WordParser).Many()
        select leading + " " + String.Join(" ", rest);

Can probably still clean it up a bit, but the concept is there.

Heinrich Walkenshaw
  • 327
  • 1
  • 4
  • 11
  • 1
    Is this different from [`" I want to return up to this point ".Trim()`](https://learn.microsoft.com/en-us/dotnet/api/system.string.trim?view=netframework-4.8)? – grooveplex May 13 '19 at 11:49
  • 5
    @grooveplex the OP is asking how to create a parser using a parser combinator. Not how to trim a string. Handling whitespace is the first step in almost any parser. Besides, `Trim()` generates temporary strings which can eradicate performance when parsing a lot of text or using a complex grammar – Panagiotis Kanavos May 13 '19 at 11:50
  • @PanagiotisKanavos Correct,, Basically the premise is match any letter multiple times with only single spaces allowed in between untill more than one space is detected. – Heinrich Walkenshaw May 13 '19 at 11:56
  • Seems your question is duplicate with https://stackoverflow.com/questions/206717/how-do-i-replace-multiple-spaces-with-a-single-space-in-c – Vadim Alekseevsky May 13 '19 at 12:56
  • 2
    @VadimAlekseevsky not at all. The OP asked a question about *Sprache*, a parser combinator library. The linked question has nothing to do with it. – Panagiotis Kanavos May 13 '19 at 12:57
  • 1
    @HeinrichWalkenshaw what have you tried? Post your attempts, it may be the only way to stop people from assuming you ask about `String.Trim`. Also check [this article](http://www.magnuslindhe.com/2014/09/parsing-whitespace-and-new-lines-with-sprache/). Have you tried using `Token()` or `WhiteSpace` ? Using parsers that match leading or trailing whitespaces it common, eg [like the leading/trailing](https://github.com/sprache/Sprache#usage) parsers in the library's example – Panagiotis Kanavos May 13 '19 at 13:01
  • 1
    @HeinrichWalkenshaw the parser you want insn't all that different from a CSV parser, where the separator is a space instead of a comma. You could check the [record parser](https://github.com/sprache/Sprache/blob/master/test/Sprache.Tests/Scenarios/CsvTests.cs#L47) from the CSV example. – Panagiotis Kanavos May 13 '19 at 13:08
  • Thank you @PanagiotisKanavos, the trick seems to be to use .Then(). Will update the question. – Heinrich Walkenshaw May 13 '19 at 13:29

1 Answers1

3

Thanks to @PanagiotisKanavos, the trick would be to use the .Then() operator. The following works:

public static Parser<string> WordParser =
    Parse.Letter.Many().Text().Token();

public static Parser<string> PhraseParser =
    from leading in Parse.LetterOrDigit.Many().Text()
    from rest in Parse.Char(' ').Then(_ => WordParser).Many()
    select leading + " " + String.Join(" ", rest);
Heinrich Walkenshaw
  • 327
  • 1
  • 4
  • 11