Superpower: Create parser to Match against "\r\n" or "\n" ( More general: match against a string literal)

156 Views Asked by At

I want to create a parser for EOL, I can't just do whitespace because I need it to ignore spaces.

So I want to create a parser that will match on "\r\n" or '\n'. Doing a single character is easy Character.EqualTo('\n') but trying to match a specific string literal is perplexing me. I would think this should be a regular thing that needs to be done for keywords, but I am at a loss.

1

There are 1 best solutions below

4
Fredrik Blom On BEST ANSWER

The \r\n combination is a string, which means that you need to combine the simple \n parser (that is a character parser) with a string parser.

How about:

    public static void Main()
    {
            var crlf = 
                from carriageReturn in Character.EqualTo('\r')
                from lineFeed in Character.EqualTo('\n')
                select new string(carriageReturn, 1) + lineFeed;

            var lf =
                from lineFeed in Character.EqualTo('\n')
                select new string(lineFeed, 1);

            var eol = crlf.Or(lf);
        
        
        eol.TryParse("\r\n").Dump();  // Successful parsing of \r\n
        eol.TryParse("\n").Dump();    // Successful parsing of \n
        eol.TryParse("\r").Dump();    // Syntax error: unexpected end of input, expected line feed.
    }

If you prefer the non-LINQ syntax:

            var eol = Character.EqualTo('\r')
                .Then(carriageReturn => Character.EqualTo('\n').Select( lineFeed => new [] {carriageReturn, lineFeed}))
                .Or(Character.EqualTo('\n').Select(lineFeed => new[] { lineFeed }));

Edited: Use the Span parser to parse strings:

            var eol = Span.EqualTo("\n")
                .Or(Span.EqualTo("\r\n"));