Skip to content

Instantly share code, notes, and snippets.

@shanecelis
Last active January 6, 2018 13:14
Show Gist options
  • Save shanecelis/55d2d888cf57ab8ef0a3432456953281 to your computer and use it in GitHub Desktop.
Save shanecelis/55d2d888cf57ab8ef0a3432456953281 to your computer and use it in GitHub Desktop.
A little parser that handles escaping, single-, and double-quotes.
/* Original code Copyright (c) 2018 Shane Celis[1]
Licensed under the MIT License[2]
Original code posted here[3].
This comment generated by code-cite[4].
[1]: https://github.com/shanecelis
[2]: https://opensource.org/licenses/MIT
[3]: https://gist.github.com/shanecelis/55d2d888cf57ab8ef0a3432456953281
[4]: https://github.com/shanecelis/code-cite
*/
using System.Collections.Generic;
using Sprache;
/*
A little parser that handles escaping, single-, and double-quotes. It's meant
to make a quick-and-dirty Command Line Interface (CLI)-like parser.
Also shows how one can do monadic parsing in C# using Linq syntax too.
Examples of usage:
CLILikeParser.ParseString(@"hello world") -> {"hello", "world"}
CLILikeParser.ParseString(@"hello\ world") -> {"hello world"}
CLILikeParser.ParseString(@"hello 'world'") -> {"hello", "world"}
CLILikeParser.ParseString(@"hello 'world thing'") -> {"hello", "world thing"}
CLILikeParser.ParseString(@"hello \"world 'thing'\"") -> {"hello", "world 'thing'"}
CLILikeParser.ParseString(@"hello 'world \"thing\"') -> {"hello", "world \"thing\""}
*/
public static class CLILikeParser {
// https://www.thomaslevesque.com/2017/02/23/easy-text-parsing-in-c-with-sprache/
public static readonly Parser<char> escapedChar =
from _ in Parse.Char('\\')
from c in Parse.AnyChar
select c;
private static readonly Parser<char> _quotedText =
Parse.AnyChar.Except(Parse.Char('\''));
private static readonly Parser<char> _doubleQuotedText =
Parse.AnyChar.Except(Parse.Char('"'));
public static readonly Parser<string> quotedString =
from open in Parse.Char('\'')
from text in escapedChar.Or(_quotedText).Many().Text()
from close in Parse.Char('\'')
select text;
public static readonly Parser<string> doubleQuotedString =
from open in Parse.Char('"')
from text in escapedChar.Or(_doubleQuotedText).Many().Text()
from close in Parse.Char('"')
select text;
public static readonly Parser<string> bareWord =
escapedChar.Or(Parse.CharExcept(' ')).AtLeastOnce().Text();
public static readonly Parser<string> argument =
from leading in Parse.WhiteSpace.Many()
from arg in quotedString.Or(doubleQuotedString).Or(bareWord)
select arg;
public static readonly Parser<IEnumerable<string>> commandLine =
from arguments in argument.Many()
from trailing in Parse.WhiteSpace.Many()
select arguments;
public static IEnumerable<string> ParseString(string cmdLine) {
return commandLine.Parse(cmdLine);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment