/// <summary>
        /// Check command line semantics.
        /// </summary>
        public static void Check(CmdLineNode commandLine, CmdLineRules rules)
        {
            // Check rules consistency
            var cmds = new HashSet <string>();

            foreach (var command in rules.Commands)
            {
                if (!cmds.Add(command.Name))
                {
                    throw new CommandLineCheckException($"Duplicate commands '{command.Name}'");
                }
            }
            var cmdOpts = new Dictionary <string, HashSet <string> >();

            foreach (var cmdOpt in
                     rules
                     .Options
                     .SelectMany(
                         opt =>
                         !opt.DependOnCommands.Any()
                                                                ? new[] { new { Cmd = "", Opt = opt.Name } }
                                                                : opt.DependOnCommands.Select(cn => new { Cmd = cn, Opt = opt.Name })))
            {
                HashSet <string> opts;
                if (!cmdOpts.TryGetValue(cmdOpt.Cmd, out opts))
                {
                    opts = new HashSet <string>();
                    cmdOpts.Add(cmdOpt.Cmd, opts);
                }
                if (!opts.Add(cmdOpt.Opt))
                {
                    throw new CommandLineCheckException(
                              $"Duplicate option {cmdOpt.Opt}{(cmdOpt.Cmd == "" ? "" : $" in command {cmdOpt.Cmd}")}");
                }
            }
 /// <summary>
 /// Check command line semantics.
 /// </summary>
 public static void Check(CmdLineNode commandLine, CmdLineRules rules) =>
 CommandLineChecker.Check(commandLine, rules);