private void AddStringSwitch(ref PathSplit psp, string value, string arg, ParseResult.Builder result) { CommandSwitch sw = FindSwitchIdentifiedBy(value); if (sw == null) { throw new InvalidInput("Invalid switch: " + value); } if (arg != null) { if (sw.arity != Arity.NoneOrOne) { throw new InvalidInput($"Switch {value} has argument, which is not allowed for the given switch."); } result.AddSwitch(sw); if ((sw.arity == Arity.One || sw.arity == Arity.NoneOrOne) && result.AlreadyHasArgumentForLastSwitch()) { throw new InvalidInput($"Switch {value} can accept only one argument, but two are supplied."); } result.AddArgForLastSwitch(arg); psp = PathSplit.Maybe; } else { switch (sw.arity) { case Arity.None: psp = PathSplit.Maybe; break; case Arity.One: psp = PathSplit.NotForOne; break; case Arity.NoneOrOne: psp = PathSplit.Maybe; break; case Arity.Any: psp = PathSplit.Not; break; default: throw new Termination("Should not reach this."); } result.AddSwitch(sw); } }
/// <summary> /// Main parsing method /// </summary> /// <exception cref="Termination">Internal error</exception> /// <exception cref="InvalidInput">Input was not valid according to parsing rules</exception> public ParseResult Parse(string[] args) { var result = new ParseResult.Builder(); PathSplit psp = PathSplit.Maybe; foreach (var arg in args) { switch (psp) { case PathSplit.Not: case PathSplit.Maybe: { var(argType, value, swArg) = GetArgType(arg); if (argType == ArgType.Separator) { psp = PathSplit.Yes; break; } else if (argType == ArgType.SingleCharSwitch) { AddSingleCharSwitch(ref psp, value, swArg, result); break; } else if (argType == ArgType.StringSwitch) { AddStringSwitch(ref psp, value, swArg, result); break; } else if (argType == ArgType.Path) { if (psp == PathSplit.Not) { result.AddArgForLastSwitch(value); // psp remains .Not. break; } else if (psp == PathSplit.Maybe) { result.AddPath(value); psp = PathSplit.Yes; break; } throw new Termination("Should never reach this."); } throw new Termination("Should never reach this."); } case PathSplit.NotForOne: { var(argType, value, swArg) = GetArgType(arg); if (argType != ArgType.Path) { throw new InvalidInput("Expected path but got a switch at " + arg); } var lastSwitch = result.GetLastSwitch(); if (lastSwitch.arity == Arity.One && result.AlreadyHasArgumentForLastSwitch()) { throw new InvalidInput($"Switch {value} can accept only one argument, but two are supplied."); } psp = PathSplit.Maybe; result.AddArgForLastSwitch(arg); break; } case PathSplit.Yes: { result.AddPath(arg); break; } default: throw new Termination("Should never reach this."); } } return(result.Build()); }
private void AddSingleCharSwitch(ref PathSplit psp, string value, string arg, ParseResult.Builder result) { // Add all but last with null arg for (int i = 0; i < value.Length - 1; i++) { AddStringSwitch(ref psp, value[0].ToString(), null, result); } // Add last with actual arg AddStringSwitch(ref psp, value[value.Length - 1].ToString(), arg, result); }