using System.Collections.Generic;
using System.Text.RegularExpressions;
public static void Main()
var expressions = new[] {
@"First Param Value -p1 Second Param Value -p2[Third-Param-Value] -X ""-Fourth -Param -Value"" -pl LastParamValue Last Value",
@"-p0 First Param Value -p1 Second Param Value -p2[Third-Param-Value] -X ""-Fourth -Param -Value"" -pl LastParamValue Last Value",
@"First Param Value -p1 Second Param Value -p2[Third-Param-Value] -p3[nested [param ""value""] ] -p4{nested { -param "" } } -p5(nested ( () -param ] ]""[) ) -X ""-Fourth -Param\"" -Value"" -pl ""Last Param Value"" Last Value",
var tokensRegex = new Regex(@"
\s*(?<token> (?>(?'o'\[)[^][]*)+(?>[^][]*(?'-o'\]))+ )\s* # balanced [...] group
| \s*(?<token> (?>(?'o'\{)[^{}]*)+(?>[^{}]*(?'-o'\}))+ )\s* # balanced {...} group
| \s*(?<token> (?>(?'o'\()[^()]*)+(?>[^()]*(?'-o'\)))+ )\s* # balanced (...) group
| \s*(?<token> ""(?:\\""|[^""])*"" )\s* # quoted group with possible escaped quotes within
| \s*(?<token> -[^\s""({[]+ ) # parameter name
| (?<token> \s*\S+\s* ) # parameter value part not in group/quotes
foreach (var expression in expressions)
var paramDict = new Dictionary<string, string>();
var currParam = "<FIRST>";
var currValues = new List<string>();
var lastParam = currParam;
foreach (var token in tokensRegex.Matches(expression)
.Cast<Match>().Select(m => m.Groups["token"].Value))
if (token.StartsWith("-"))
if (currParam == "<FIRST>" && currValues.Count == 0)
paramDict.Add(currParam, string.Join("", currValues));
currValues = new List<string>();
if (currValues.Count > 1)
paramDict[currParam] = currValues[0];
paramDict["<LAST>"] = string.Join("", currValues.Skip(1));
Console.WriteLine("Expression parsed: {0}", expression);
foreach (var kvp in paramDict)
Console.WriteLine("\t{0}\t => {1}", kvp.Key, kvp.Value);